Skip to content

Commit 61ed271

Browse files
committed
Tests to show that ElasticsearchServerExceptions shortcut the retry logic (known errros should fail fast)
1 parent bc7fc17 commit 61ed271

File tree

4 files changed

+126
-4
lines changed

4 files changed

+126
-4
lines changed

src/Elasticsearch.Net/Connection/Transport.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@ private ElasticsearchResponse<T> DoRequest<T>(TransportRequestState<T> requestSt
311311
return typedResponse;
312312
}
313313
}
314+
catch (ElasticsearchServerException)
315+
{
316+
throw;
317+
}
314318
catch (Exception e)
315319
{
316320
if (maxRetries == 0 && retried == 0)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System;
2+
using System.IO;
3+
using System.Runtime.InteropServices;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Autofac.Extras.FakeItEasy;
7+
using Elasticsearch.Net.Connection;
8+
using Elasticsearch.Net.ConnectionPool;
9+
using Elasticsearch.Net.Exceptions;
10+
using Elasticsearch.Net.Tests.Unit.Stubs;
11+
using FakeItEasy;
12+
using FluentAssertions;
13+
using NUnit.Framework;
14+
15+
namespace Elasticsearch.Net.Tests.Unit.Connection
16+
{
17+
[TestFixture]
18+
public class NoRetryOnServerExceptionTests
19+
{
20+
private MemoryStream CreateServerExceptionResponse(int status, string exceptionType, string exceptionMessage)
21+
{
22+
var format = @"{{ ""status"": {0}, ""error"" : ""{1}[{2}]"" }}";
23+
var bytes = Encoding.UTF8.GetBytes(string.Format(format, status, exceptionType, exceptionMessage));
24+
var stream = new MemoryStream(bytes);
25+
return stream;
26+
}
27+
28+
[Test]
29+
[TestCase(505, "SomeException", "Some Error Message")]
30+
[TestCase(505, "", "")]
31+
public void IfResponseIsKnowError_DoNotRetry_ThrowServerException(int status, string exceptionType, string exceptionMessage)
32+
{
33+
var response = CreateServerExceptionResponse(status, exceptionType, exceptionMessage);
34+
using (var fake = new AutoFake(callsDoNothing: true))
35+
{
36+
var connectionPool = new StaticConnectionPool(new[]
37+
{
38+
new Uri("http://localhost:9200"),
39+
new Uri("http://localhost:9201"),
40+
});
41+
var connectionConfiguration = new ConnectionConfiguration(connectionPool)
42+
.ThrowOnElasticsearchServerExceptions()
43+
.ExposeRawResponse(false);
44+
45+
fake.Provide<IConnectionConfigurationValues>(connectionConfiguration);
46+
FakeCalls.ProvideDefaultTransport(fake);
47+
48+
var pingCall = FakeCalls.PingAtConnectionLevel(fake);
49+
pingCall.Returns(FakeResponse.Ok(connectionConfiguration));
50+
51+
var getCall = FakeCalls.GetSyncCall(fake);
52+
getCall.Returns(FakeResponse.Any(connectionConfiguration, status, response: response));
53+
54+
var client = fake.Resolve<ElasticsearchClient>();
55+
56+
var e = Assert.Throws<ElasticsearchServerException>(()=>client.Info());
57+
AssertServerErrorsOnResponse(e, status, exceptionType, exceptionMessage);
58+
59+
//make sure a know ElasticsearchServerException does not cause a retry
60+
//In this case we want to fail early
61+
62+
getCall.MustHaveHappened(Repeated.Exactly.Once);
63+
64+
}
65+
}
66+
67+
[Test]
68+
[TestCase(505, "SomeException", "Some Error Message")]
69+
[TestCase(505, "", "")]
70+
public async void IfResponseIsKnowError_DoNotRetry_ThrowServerException_Async(int status, string exceptionType, string exceptionMessage)
71+
{
72+
var response = CreateServerExceptionResponse(status, exceptionType, exceptionMessage);
73+
using (var fake = new AutoFake(callsDoNothing: true))
74+
{
75+
var connectionPool = new StaticConnectionPool(new[]
76+
{
77+
new Uri("http://localhost:9200"),
78+
new Uri("http://localhost:9201"),
79+
});
80+
var connectionConfiguration = new ConnectionConfiguration(connectionPool)
81+
.ThrowOnElasticsearchServerExceptions()
82+
.ExposeRawResponse(false);
83+
84+
fake.Provide<IConnectionConfigurationValues>(connectionConfiguration);
85+
FakeCalls.ProvideDefaultTransport(fake);
86+
87+
var pingCall = FakeCalls.PingAtConnectionLevelAsync(fake);
88+
pingCall.Returns(FakeResponse.OkAsync(connectionConfiguration));
89+
90+
var getCall = FakeCalls.GetCall(fake);
91+
getCall.Returns(FakeResponse.AnyAsync(connectionConfiguration, status, response: response));
92+
93+
var client = fake.Resolve<ElasticsearchClient>();
94+
95+
var e = Assert.Throws<ElasticsearchServerException>(async ()=>await client.InfoAsync());
96+
AssertServerErrorsOnResponse(e, status, exceptionType, exceptionMessage);
97+
98+
//make sure a know ElasticsearchServerException does not cause a retry
99+
//In this case we want to fail early
100+
101+
getCall.MustHaveHappened(Repeated.Exactly.Once);
102+
103+
}
104+
}
105+
106+
private static void AssertServerErrorsOnResponse(
107+
ElasticsearchServerException serverException, int status, string exceptionType, string exceptionMessage)
108+
{
109+
serverException.Should().NotBeNull();
110+
serverException.ExceptionType.Should().Be(exceptionType);
111+
serverException.Message.Should().Be(exceptionMessage);
112+
serverException.Status.Should().Be(status);
113+
}
114+
}
115+
}

src/Tests/Elasticsearch.Net.Tests.Unit/Elasticsearch.Net.Tests.Unit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
<ItemGroup>
6161
<Compile Include="Connection\BuildInResponseAsyncTests.cs" />
6262
<Compile Include="Connection\BuildInResponseTests.cs" />
63+
<Compile Include="Connection\NoRetryOnServerExceptionTests.cs" />
6364
<Compile Include="Connection\ElasticsearchServerExceptions.cs" />
6465
<Compile Include="Connection\NoRetryTests.cs" />
6566
<Compile Include="Stubs\FakeCalls.cs" />

src/Tests/Elasticsearch.Net.Tests.Unit/Stubs/FakeResponse.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,20 @@ public static ElasticsearchResponse<Stream> Any(
4949
IConnectionConfigurationValues config,
5050
int statusCode,
5151
string method = "GET",
52-
string path = "/")
52+
string path = "/",
53+
Stream response = null)
5354
{
54-
return ElasticsearchResponse<Stream>.Create(config, statusCode, method, path, null);
55+
return ElasticsearchResponse<Stream>.Create(config, statusCode, method, path, null, response);
5556
}
5657

5758
public static Task<ElasticsearchResponse<Stream>> AnyAsync(
5859
IConnectionConfigurationValues config,
5960
int statusCode,
6061
string method = "GET",
61-
string path = "/")
62+
string path = "/",
63+
Stream response = null)
6264
{
63-
return Task.FromResult(ElasticsearchResponse<Stream>.Create(config, statusCode, method, path, null));
65+
return Task.FromResult(ElasticsearchResponse<Stream>.Create(config, statusCode, method, path, null, response));
6466
}
6567
}
6668
}

0 commit comments

Comments
 (0)