Skip to content

Commit 96be58b

Browse files
committed
made sure async codepath retries properly too
1 parent 272692b commit 96be58b

File tree

5 files changed

+258
-56
lines changed

5 files changed

+258
-56
lines changed

src/Elasticsearch.Net.Tests.Unit/Connection/RetryTests.cs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,35 @@ public void ThrowsOutOfNodesException_AndRetriesTheSpecifiedTimes()
5151
}
5252
}
5353

54+
[Test]
55+
public async void ThrowsOutOfNodesException_AndRetriesTheSpecifiedTimes_Async()
56+
{
57+
using (var fake = new AutoFake(callsDoNothing: true))
58+
{
59+
fake.Provide<IConnectionConfigurationValues>(_connectionConfig);
60+
this.ProvideTransport(fake);
61+
var getCall = A.CallTo(() => fake.Resolve<IConnection>().Get(A<Uri>._));
62+
Func<ElasticsearchResponse> badTask = () => { throw new Exception(); };
63+
var t = new Task<ElasticsearchResponse>(badTask);
64+
t.Start();
65+
getCall.Returns(t);
66+
67+
var client = fake.Resolve<ElasticsearchClient>();
68+
69+
client.Settings.MaxRetries.Should().Be(_retries);
70+
try
71+
{
72+
var result = await client.InfoAsync();
73+
}
74+
catch (Exception e)
75+
{
76+
Assert.AreEqual(e.GetType(), typeof(OutOfNodesException));
77+
}
78+
getCall.MustHaveHappened(Repeated.Exactly.Times(_retries + 1));
79+
80+
}
81+
}
82+
5483
[Test]
5584
public void ShouldNotRetryOn400()
5685
{
@@ -69,7 +98,24 @@ public void ShouldNotRetryOn400()
6998

7099
}
71100
}
72-
101+
[Test]
102+
public async void ShouldNotRetryOn400_Async()
103+
{
104+
using (var fake = new AutoFake(callsDoNothing: true))
105+
{
106+
var settings = fake.Provide<IConnectionConfigurationValues>(_connectionConfig);
107+
this.ProvideTransport(fake);
108+
109+
var getCall = A.CallTo(() => fake.Resolve<IConnection>().Get(A<Uri>._));
110+
getCall.Returns(Task.FromResult(ElasticsearchResponse.Create(settings, 400, "GET", "/", null, null)));
111+
112+
var client = fake.Resolve<ElasticsearchClient>();
113+
114+
var result = await client.InfoAsync();
115+
getCall.MustHaveHappened(Repeated.Exactly.Once);
116+
117+
}
118+
}
73119
[Test]
74120
public void ShouldNotRetryOn500()
75121
{
@@ -126,5 +172,30 @@ public void ShouldRetryOn503()
126172

127173
}
128174
}
175+
176+
[Test]
177+
public async void ShouldRetryOn503_Async()
178+
{
179+
using (var fake = new AutoFake(callsDoNothing: true))
180+
{
181+
var settings = fake.Provide<IConnectionConfigurationValues>(_connectionConfig);
182+
this.ProvideTransport(fake);
183+
184+
var getCall = A.CallTo(() => fake.Resolve<IConnection>().Get(A<Uri>._));
185+
getCall.Returns(Task.FromResult(ElasticsearchResponse.Create(settings, 503, "GET", "/", null, null)));
186+
187+
var client = fake.Resolve<ElasticsearchClient>();
188+
try
189+
{
190+
var result = await client.InfoAsync();
191+
}
192+
catch (Exception e)
193+
{
194+
Assert.AreEqual(e.GetType(), typeof(OutOfNodesException));
195+
}
196+
getCall.MustHaveHappened(Repeated.Exactly.Times(_retries + 1));
197+
198+
}
199+
}
129200
}
130201
}

src/Elasticsearch.Net.Tests.Unit/Connection/SkipDeadNodesTests.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,90 @@ public void DeadNodesAreNotVisited()
104104
//var nowCall = A.CallTo(() => fake.Resolve<IDateTimeProvider>().Sniff(A<Uri>._, A<int>._));
105105
}
106106
}
107+
108+
[Test]
109+
public async void DeadNodesAreNotVisited_Async()
110+
{
111+
using (var fake = new AutoFake())
112+
{
113+
var now = DateTime.UtcNow;
114+
var dateTimeProvider = fake.Resolve<IDateTimeProvider>();
115+
var nowCall = A.CallTo(()=>dateTimeProvider.Now());
116+
nowCall.ReturnsNextFromSequence(
117+
DateTime.UtcNow, //info 1
118+
DateTime.UtcNow, //info 2
119+
DateTime.UtcNow, //info 2 retry
120+
DateTime.UtcNow, //info 3
121+
DateTime.UtcNow, //info 4
122+
DateTime.UtcNow, //info 5 pass over node 3
123+
DateTime.UtcNow, //info 5
124+
DateTime.UtcNow, //info 6
125+
DateTime.UtcNow.AddMinutes(2), //info 7
126+
DateTime.UtcNow.AddMinutes(2), //info 8
127+
DateTime.UtcNow.AddMinutes(2) //info 9
128+
);
129+
A.CallTo(()=>dateTimeProvider.AliveTime(A<Uri>._, A<int>._))
130+
.Returns(new DateTime());
131+
A.CallTo(() => dateTimeProvider.DeadTime(A<Uri>._, A<int>._))
132+
.Returns(DateTime.UtcNow.AddMinutes(1));
133+
//make sure the transport layer uses a different datetimeprovider
134+
fake.Provide<IDateTimeProvider>(new DateTimeProvider());
135+
var connectionPool = new StaticConnectionPool(new[]
136+
{
137+
new Uri("http://localhost:9204"),
138+
new Uri("http://localhost:9203"),
139+
new Uri("http://localhost:9202"),
140+
new Uri("http://localhost:9201")
141+
}, randomizeOnStartup: false, dateTimeProvider: dateTimeProvider);
142+
var config = new ConnectionConfiguration(connectionPool);
143+
fake.Provide<IConnectionConfigurationValues>(config);
144+
fake.Provide<ITransport>(fake.Resolve<Transport>());
145+
var connection = fake.Resolve<IConnection>();
146+
147+
var ok = Task.FromResult(ElasticsearchResponse.Create(config, 200, "GET", "/", null, null));
148+
var bad = Task.FromResult(ElasticsearchResponse.Create(config, 503, "GET", "/", null, null));
149+
150+
var seenNodes = new List<Uri>();
151+
var getCall = A.CallTo(() => connection.Get(A<Uri>._));
152+
getCall.ReturnsNextFromSequence(
153+
ok, //info 1 - 9204
154+
bad, //info 2 - 9203 DEAD
155+
ok, //info 2 retry - 9202
156+
ok, //info 3 - 9201
157+
ok, //info 4 - 9204
158+
ok, //info 5 - 9202
159+
ok, //info 6 - 9201
160+
ok, //info 7 - 9204
161+
ok, //info 8 - 9203 (Now > Timeout)
162+
ok //info 9 - 9202
163+
);
164+
getCall.Invokes((Uri u) => seenNodes.Add(u));
165+
166+
var client1 = fake.Resolve<ElasticsearchClient>();
167+
await client1.InfoAsync(); //info call 1
168+
await client1.InfoAsync(); //info call 2
169+
await client1.InfoAsync(); //info call 3
170+
await client1.InfoAsync(); //info call 4
171+
await client1.InfoAsync(); //info call 5
172+
await client1.InfoAsync(); //info call 6
173+
await client1.InfoAsync(); //info call 7
174+
await client1.InfoAsync(); //info call 8
175+
await client1.InfoAsync(); //info call 9
176+
177+
seenNodes.Should().NotBeEmpty().And.HaveCount(10);
178+
seenNodes[0].Port.Should().Be(9204);
179+
seenNodes[1].Port.Should().Be(9203);
180+
//after sniff
181+
seenNodes[2].Port.Should().Be(9202);
182+
seenNodes[3].Port.Should().Be(9201);
183+
seenNodes[4].Port.Should().Be(9204);
184+
seenNodes[5].Port.Should().Be(9202);
185+
seenNodes[6].Port.Should().Be(9201);
186+
seenNodes[7].Port.Should().Be(9204);
187+
seenNodes[8].Port.Should().Be(9203);
188+
189+
//var nowCall = A.CallTo(() => fake.Resolve<IDateTimeProvider>().Sniff(A<Uri>._, A<int>._));
190+
}
191+
}
107192
}
108193
}

src/Elasticsearch.Net/Connection/ITransport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ public interface ITransport
1010
Task<ElasticsearchResponse> DoRequestAsync(
1111
string method,
1212
string path,
13-
object data = null, NameValueCollection queryString = null, int retried = 0);
13+
object data = null, NameValueCollection queryString = null, int retried = 0, int? seed = null);
1414
}
1515
}

0 commit comments

Comments
 (0)