Skip to content

Commit 7ec53a8

Browse files
committed
Fix initial randomization of nodes (#4112)
This commit fixes the initial randomization of nodes in a StaticConnectionPool. Instead of calling the protected ctor, the initialization logic has been pulled out into a separate method that is now called from the ctor that accepts a randomize parameter. Fixes #4055
1 parent cea096c commit 7ec53a8

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

src/Elasticsearch.Net/ConnectionPool/SniffingConnectionPool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public SniffingConnectionPool(IEnumerable<Node> nodes, bool randomize = true, ID
1717
: base(nodes, randomize, dateTimeProvider) { }
1818

1919
public SniffingConnectionPool(IEnumerable<Node> nodes, Func<Node, float> nodeScorer, IDateTimeProvider dateTimeProvider = null)
20-
: base(nodes, nodeScorer, dateTimeProvider) { }
20+
: base(nodes, nodeScorer, false, dateTimeProvider) { }
2121

2222
/// <inheritdoc />
2323
public override IReadOnlyCollection<Node> Nodes

src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,29 @@ public StaticConnectionPool(IEnumerable<Uri> uris, bool randomize = true, IDateT
1515
: this(uris.Select(uri => new Node(uri)), randomize, dateTimeProvider) { }
1616

1717
public StaticConnectionPool(IEnumerable<Node> nodes, bool randomize = true, IDateTimeProvider dateTimeProvider = null)
18-
: this(nodes, null, dateTimeProvider) => Randomize = randomize;
18+
: this(nodes, null, randomize, dateTimeProvider) { }
1919

2020
//this constructor is protected because nodeScorer only makes sense on subclasses that support reseeding
2121
//otherwise just manually sort `nodes` before instantiating.
22-
protected StaticConnectionPool(IEnumerable<Node> nodes, Func<Node, float> nodeScorer, IDateTimeProvider dateTimeProvider = null)
22+
protected StaticConnectionPool(IEnumerable<Node> nodes, Func<Node, float> nodeScorer = null, bool randomize = true, IDateTimeProvider dateTimeProvider = null)
2323
{
2424
nodes.ThrowIfEmpty(nameof(nodes));
25-
DateTimeProvider = dateTimeProvider ?? Net.DateTimeProvider.Default;
26-
27-
var nn = nodes.ToList();
28-
var uris = nn.Select(n => n.Uri).ToList();
29-
if (uris.Select(u => u.Scheme).Distinct().Count() > 1)
30-
throw new ArgumentException("Trying to instantiate a connection pool with mixed URI Schemes");
31-
32-
UsingSsl = uris.Any(uri => uri.Scheme == "https");
25+
string scheme = null;
26+
foreach (var node in nodes)
27+
{
28+
if (scheme == null)
29+
{
30+
scheme = node.Uri.Scheme;
31+
UsingSsl = scheme == "https";
32+
}
33+
else if (scheme != node.Uri.Scheme)
34+
throw new ArgumentException("Trying to instantiate a connection pool with mixed URI Schemes");
35+
}
3336

37+
DateTimeProvider = dateTimeProvider ?? Net.DateTimeProvider.Default;
38+
Randomize = randomize;
3439
_nodeScorer = nodeScorer;
35-
InternalNodes = SortNodes(nn)
40+
InternalNodes = SortNodes(nodes)
3641
.DistinctBy(n => n.Uri)
3742
.ToList();
3843
LastUpdate = DateTimeProvider.Now();

src/Tests/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.doc.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Text;
5+
using System.Threading;
46
using Elastic.Xunit.XunitPlumbing;
57
using Elasticsearch.Net;
68
using FluentAssertions;
@@ -214,6 +216,33 @@ [U] public void Static()
214216
}
215217
}
216218

219+
// hide
220+
[U] public void RandomizedInitialNodes()
221+
{
222+
IEnumerable<StaticConnectionPool> CreatStaticConnectionPools()
223+
{
224+
Thread.Sleep(1);
225+
226+
var uris = new[]
227+
{
228+
new Uri("https://10.0.0.1:9200/"),
229+
new Uri("https://10.0.0.2:9200/"),
230+
new Uri("https://10.0.0.3:9200/")
231+
};
232+
233+
yield return new StaticConnectionPool(uris);
234+
}
235+
236+
// assertion works on the probability of seeing a Uri other than https://10.0.0.1:9200/
237+
// as the first value over 50 runs, when randomized.
238+
CreatStaticConnectionPools()
239+
.Take(50)
240+
.Select(p => p.CreateView().First().Uri.ToString())
241+
.All(uri => uri == "https://10.0.0.1:9200/")
242+
.Should()
243+
.BeFalse();
244+
}
245+
217246
/**[[sniffing-connection-pool]]
218247
* ==== SniffingConnectionPool
219248
*

0 commit comments

Comments
 (0)