Unrecoverable exceptionsedit
Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately.
By default, the client won’t throw on any ElasticsearchClientException
but instead return an invalid response which
can be detected by checking .IsValid
on the response
You can configure the client to throw using ThrowExceptions()
on ConnectionSettings
. The following test
both a client that throws and one that returns an invalid response with an .OriginalException
exposed
The following are recoverable exceptions
var recoverablExceptions = new[] { new PipelineException(PipelineFailure.BadResponse), new PipelineException(PipelineFailure.PingFailure), }; recoverablExceptions.Should().OnlyContain(e => e.Recoverable);
and the unrecoverable exceptions
var unrecoverableExceptions = new[] { new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), new PipelineException(PipelineFailure.SniffFailure), new PipelineException(PipelineFailure.Unexpected), new PipelineException(PipelineFailure.BadAuthentication), new PipelineException(PipelineFailure.MaxRetriesReached), new PipelineException(PipelineFailure.MaxTimeoutReached) }; unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable);
As an example, let’s set up a 10 node cluster that will always succeed when pinged but will fail with a 401 response when making client calls
var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Ping(r => r.SucceedAlways()) .ClientCalls(r => r.FailAlways(401)) .StaticConnectionPool() .AllDefaults() );
Here we make a client call and determine that the first audit event was a successful ping, followed by a bad response as a result of a bad authentication response
audit = await audit.TraceElasticsearchException( new ClientCall { { AuditEvent.PingSuccess, 9200 }, { AuditEvent.BadResponse, 9200 }, }, (e) => { e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); } );
var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Ping(r => r.SucceedAlways()) .ClientCalls(r => r.FailAlways(401).ReturnResponse(ResponseHtml)) .StaticConnectionPool() .AllDefaults() ); audit = await audit.TraceElasticsearchException( new ClientCall { { AuditEvent.PingSuccess, 9200 }, { AuditEvent.BadResponse, 9200 }, }, (e) => { e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().BeNull(); } ); e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().BeNull();
var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Ping(r => r.SucceedAlways()) .ClientCalls(r => r.FailAlways(401).ReturnResponse(ResponseHtml)) .StaticConnectionPool() .Settings(s=>s.DisableDirectStreaming()) ); audit = await audit.TraceElasticsearchException( new ClientCall { { AuditEvent.PingSuccess, 9200 }, { AuditEvent.BadResponse, 9200 }, }, (e) => { e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); responseString.Should().Contain("nginx/"); e.DebugInformation.Should().Contain("nginx/"); } ); e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); responseString.Should().Contain("nginx/"); e.DebugInformation.Should().Contain("nginx/");
var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Ping(r => r.SucceedAlways()) .ClientCalls(r => r.FailAlways(401).ReturnResponse(ResponseHtml)) .StaticConnectionPool() .Settings(s=>s.DisableDirectStreaming().DefaultIndex("default-index")) .ClientProxiesTo( (c, r) => c.Get<Project>("1", s=>s.RequestConfiguration(r)), async (c, r) => await c.GetAsync<Project>("1", s=>s.RequestConfiguration(r)) as IResponse ) ); audit = await audit.TraceElasticsearchException( new ClientCall { { AuditEvent.PingSuccess, 9200 }, { AuditEvent.BadResponse, 9200 }, }, (e) => { e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); responseString.Should().Contain("nginx/"); e.DebugInformation.Should().Contain("nginx/"); } ); e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); responseString.Should().Contain("nginx/"); e.DebugInformation.Should().Contain("nginx/");