Skip to content

Commit 1f74fde

Browse files
committed
can now specify custom ping timeout, dead timeout, max dead timeout
1 parent dc3da33 commit 1f74fde

11 files changed

+62
-19
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public void DeadNodesAreNotVisited()
4646
);
4747
A.CallTo(()=>dateTimeProvider.AliveTime(A<Uri>._, A<int>._))
4848
.Returns(new DateTime());
49-
A.CallTo(() => dateTimeProvider.DeadTime(A<Uri>._, A<int>._))
49+
A.CallTo(() => dateTimeProvider.DeadTime(A<Uri>._, A<int>._, A<int?>._, A<int?>._))
5050
.Returns(DateTime.UtcNow.AddMinutes(1));
5151
//make sure the transport layer uses a different datetimeprovider
5252
fake.Provide<IDateTimeProvider>(new DateTimeProvider());
@@ -106,7 +106,7 @@ public void DeadNodesAreNotVisited()
106106
}
107107

108108
[Test]
109-
public async void DeadNodesAreNotVisited_Async()
109+
public async void DeadNodesAreNotVisited_Async()
110110
{
111111
using (var fake = new AutoFake())
112112
{
@@ -128,7 +128,7 @@ public async void DeadNodesAreNotVisited_Async()
128128
);
129129
A.CallTo(()=>dateTimeProvider.AliveTime(A<Uri>._, A<int>._))
130130
.Returns(new DateTime());
131-
A.CallTo(() => dateTimeProvider.DeadTime(A<Uri>._, A<int>._))
131+
A.CallTo(() => dateTimeProvider.DeadTime(A<Uri>._, A<int>._, A<int?>._, A<int?>._))
132132
.Returns(DateTime.UtcNow.AddMinutes(1));
133133
//make sure the transport layer uses a different datetimeprovider
134134
fake.Provide<IDateTimeProvider>(new DateTimeProvider());

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public void AllNodesWillBeMarkedDead()
197197
var calls = _uris.Select(u =>
198198
A.CallTo(()=> dateTimeProvider.DeadTime(
199199
A<Uri>.That.Matches(uu=>uu.Port == u.Port),
200-
A<int>._
200+
A<int>._, A<int?>._, A<int?>._
201201
))).ToList();
202202

203203
//all the fake mark dead calls return 60 seconds into the future
@@ -234,7 +234,7 @@ public void IfAConnectionComesBackToLifeOnItsOwnItShouldBeMarked()
234234
//Setting up a datetime provider so that can track dead/alive marks
235235
var dateTimeProvider = fake.Resolve<IDateTimeProvider>();
236236
A.CallTo(() => dateTimeProvider.Now()).Returns(DateTime.UtcNow);
237-
var markDeadCall = A.CallTo(() => dateTimeProvider.DeadTime(A<Uri>._, A<int>._));
237+
var markDeadCall = A.CallTo(() => dateTimeProvider.DeadTime(A<Uri>._, A<int>._, A<int?>._, A<int?>._));
238238
var markAliveCall = A.CallTo(() => dateTimeProvider.AliveTime(A<Uri>._, A<int>._));
239239
markDeadCall.Returns(DateTime.UtcNow.AddSeconds(60));
240240
markAliveCall.Returns(new DateTime());
@@ -292,9 +292,9 @@ public void IfAllButOneConnectionDiesSubsequentRequestsMustUseTheOneAliveConnect
292292
var dateTimeProvider = fake.Resolve<IDateTimeProvider>();
293293
A.CallTo(() => dateTimeProvider.Now()).Returns(DateTime.UtcNow);
294294
var markOthersDeadCall = A.CallTo(() => dateTimeProvider
295-
.DeadTime(A<Uri>.That.Not.Matches(u=>u.Port == 9203), A<int>._));
295+
.DeadTime(A<Uri>.That.Not.Matches(u=>u.Port == 9203), A<int>._, A<int?>._, A<int?>._));
296296
var markLastDead = A.CallTo(() => dateTimeProvider
297-
.DeadTime(A<Uri>.That.Matches(u=>u.Port == 9203), A<int>._));
297+
.DeadTime(A<Uri>.That.Matches(u=>u.Port == 9203), A<int>._, A<int?>._, A<int?>._));
298298
var markOthersAliveCall = A.CallTo(() => dateTimeProvider
299299
.AliveTime(A<Uri>.That.Not.Matches(u=>u.Port == 9203), A<int>._));
300300
var markLastAlive = A.CallTo(() => dateTimeProvider

src/Elasticsearch.Net/Connection/ConnectionConfiguration.cs

+34
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public class ConnectionConfiguration<T> : IConnectionConfigurationValues
3232
//public string Host { get; private set; }
3333
//public int Port { get; private set; }
3434
public int Timeout { get; private set; }
35+
public int? PingTimeout { get; private set; }
36+
public int? DeadTimeout { get; private set; }
37+
public int? MaxDeadTimeout { get; private set; }
3538
public string ProxyUsername { get; private set; }
3639
public string ProxyPassword { get; private set; }
3740
public string ProxyAddress { get; private set; }
@@ -119,6 +122,37 @@ public T SetTimeout(int timeout)
119122
return (T) this;
120123
}
121124

125+
/// <summary>
126+
/// This is a separate timeout for Ping() requests. A ping should fail as fast as possible.
127+
/// </summary>
128+
/// <param name="timeout">The ping timeout in milliseconds defaults to 50</param>
129+
public T SetPingTimeout(int timeout)
130+
{
131+
this.PingTimeout = timeout;
132+
return (T) this;
133+
}
134+
135+
/// <summary>
136+
/// Sets the default dead timeout factor when a node has been marked dead.
137+
/// </summary>
138+
/// <remarks>Some connection pools may use a flat timeout whilst others take this factor and increase it exponentially</remarks>
139+
/// <param name="timeout"></param>
140+
public T SetDeadTimeout(int timeout)
141+
{
142+
this.DeadTimeout = timeout;
143+
return (T) this;
144+
}
145+
146+
/// <summary>
147+
/// Sets the maximum time a node can be marked dead.
148+
/// Different implementations of IConnectionPool may choose a different default.
149+
/// </summary>
150+
/// <param name="timeout">The timeout in milliseconds</param>
151+
public T SetMaxDeadTimeout(int timeout)
152+
{
153+
this.MaxDeadTimeout = timeout;
154+
return (T) this;
155+
}
122156
/// <summary>
123157
/// Semaphore asynchronous connections automatically by giving
124158
/// it a maximum concurrent connections.

src/Elasticsearch.Net/Connection/IConnectionConfigurationValues.cs

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public interface IConnectionConfigurationValues
1313
//string Host { get; }
1414
//int Port { get; }
1515
int Timeout { get; }
16+
int? PingTimeout { get; }
17+
int? DeadTimeout { get; }
18+
int? MaxDeadTimeout { get; }
1619
int? MaxRetries { get; }
1720
string ProxyAddress { get; }
1821
string ProxyUsername { get; }
@@ -38,6 +41,7 @@ public interface IConnectionConfigurationValues
3841
/// </summary>
3942
TimeSpan? SniffInformationLifeSpan { get; }
4043

44+
4145
/// <summary>
4246
/// Append these query string parameters automatically to every request
4347
/// </summary>

src/Elasticsearch.Net/Connection/Transport.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ private ElasticsearchResponse RetryRequest(
116116
var maxRetries = this.GetMaximumRetries();
117117
var exceptionMessage = "Unable to perform request: '{0} {1}' on any of the nodes after retrying {2} times."
118118
.F( method, path, retried);
119-
this._connectionPool.MarkDead(baseUri);
119+
this._connectionPool.MarkDead(baseUri, this._configurationValues.DeadTimeout, this._configurationValues.MaxDeadTimeout);
120120
if (this._configurationValues.SniffsOnConnectionFault && retried == 0)
121121
this.Sniff();
122+
122123
if (retried < maxRetries)
123124
{
124125
return this.DoRequest(method, path, data, null, ++retried, initialSeed);
@@ -181,7 +182,7 @@ private Task<ElasticsearchResponse> RetryRequestAsync(
181182
var maxRetries = this.GetMaximumRetries();
182183
var exceptionMessage = "Unable to perform request: '{0} {1}' on any of the nodes after retrying {2} times."
183184
.F( method, path, retried);
184-
this._connectionPool.MarkDead(baseUri);
185+
this._connectionPool.MarkDead(baseUri, this._configurationValues.DeadTimeout, this._configurationValues.MaxDeadTimeout);
185186
if (this._configurationValues.SniffsOnConnectionFault && retried == 0)
186187
this.Sniff();
187188
if (retried < maxRetries)

src/Elasticsearch.Net/ConnectionPool/IConnectionPool.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public interface IConnectionPool
2020
/// <summary>
2121
/// Mark the specified Uri as dead
2222
/// </summary>
23-
void MarkDead(Uri uri);
23+
void MarkDead(Uri uri, int? deadTimeout = null, int? maxDeadtimeout = null);
2424

2525
/// <summary>
2626
/// Bring the specified uri back to life.

src/Elasticsearch.Net/ConnectionPool/SingleNodeConnectionPool.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public Uri GetNext(int? initialSeed, out int seed)
2424
return _uri;
2525
}
2626

27-
public void MarkDead(Uri uri)
27+
public void MarkDead(Uri uri, int? deadTimeout = null, int? maxDeadTimeout = null)
2828
{
2929

3030
}

src/Elasticsearch.Net/ConnectionPool/SniffingConnectionPool.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ public override void MarkAlive(Uri uri)
7575
}
7676
}
7777

78-
public override void MarkDead(Uri uri)
78+
public override void MarkDead(Uri uri, int? deadTimeout, int? maxDeadTimeout)
7979
{
8080
try
8181
{
8282
this._readerWriter.EnterReadLock();
83-
base.MarkDead(uri);
83+
base.MarkDead(uri, deadTimeout, maxDeadTimeout);
8484
}
8585
finally
8686
{

src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ public virtual Uri GetNext(int? initialSeed, out int seed)
6767
return this._nodeUris[i];
6868
}
6969

70-
public virtual void MarkDead(Uri uri)
70+
public virtual void MarkDead(Uri uri, int? deadTimeout, int? maxDeadTimeout)
7171
{
7272
EndpointState state = null;
7373
if (!this._uriLookup.TryGetValue(uri, out state))
7474
return;
7575
lock(state)
7676
{
77-
state.date = this._dateTimeProvider.DeadTime(uri, state._attempts);
77+
state.date = this._dateTimeProvider.DeadTime(uri, state._attempts, deadTimeout, maxDeadTimeout);
7878
}
7979
}
8080

src/Elasticsearch.Net/Providers/DateTimeProvider.cs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
using System;
2+
using Elasticsearch.Net.Connection;
23

34
namespace Elasticsearch.Net.Providers
45
{
56
public class DateTimeProvider : IDateTimeProvider
67
{
8+
79
public virtual DateTime Now()
810
{
911
return DateTime.UtcNow;
1012
}
1113

12-
public virtual DateTime DeadTime(Uri uri, int attempts)
14+
public virtual DateTime DeadTime(Uri uri, int attempts, int? timeoutFactor = null, int? maxDeadTimeout = null)
1315
{
14-
var seconds = Math.Min(60 * 2 * Math.Pow(2, (attempts * 0.5 - 1)), 60 * 30);
15-
return DateTime.UtcNow.AddSeconds(seconds);
16+
var timeout = timeoutFactor.GetValueOrDefault(60 * 1000);
17+
var maxTimeout = maxDeadTimeout.GetValueOrDefault(60 * 1000 * 30);
18+
var seconds = Math.Min(timeout * 2 * Math.Pow(2, (attempts * 0.5 - 1)), maxTimeout);
19+
return DateTime.UtcNow.AddMilliseconds(seconds);
1620
}
1721

1822
public virtual DateTime AliveTime(Uri uri, int attempts)

src/Elasticsearch.Net/Providers/IDateTimeProvider.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Elasticsearch.Net.Providers
55
public interface IDateTimeProvider
66
{
77
DateTime Now();
8-
DateTime DeadTime(Uri uri, int attempts);
8+
DateTime DeadTime(Uri uri, int attempts, int? timeoutFactor = null, int? maxDeadTimeout = null);
99
DateTime AliveTime(Uri uri, int attempts);
1010
}
1111
}

0 commit comments

Comments
 (0)