From 7a645e6eb595e3263c5e8332def3c7bf9cb59e63 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Tue, 15 Oct 2019 13:37:35 +1000 Subject: [PATCH 1/3] Fix test for random initialized node (#4134) The test was using a local method that yielded a single pool while later .Take(50) was requested on this sequence. This always yields an enumeration with 1 element which increases the chances for the assertion to turn false. Rather than relying on Thread.Sleep to create different seeded randoms the StaticConnectionPool now defines a protected constructor that allows one to pass in a seed value. (cherry picked from commit 9734f04a161e6cbbe8b632b2993e61cb7f553a6a) --- .../ConnectionPool/SniffingConnectionPool.cs | 2 +- .../ConnectionPool/StaticConnectionPool.cs | 39 +++++++++++++------ .../BuildingBlocks/ConnectionPooling.doc.cs | 27 +++++++++---- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/Elasticsearch.Net/ConnectionPool/SniffingConnectionPool.cs b/src/Elasticsearch.Net/ConnectionPool/SniffingConnectionPool.cs index fba255dd024..5f0accd9ace 100644 --- a/src/Elasticsearch.Net/ConnectionPool/SniffingConnectionPool.cs +++ b/src/Elasticsearch.Net/ConnectionPool/SniffingConnectionPool.cs @@ -17,7 +17,7 @@ public SniffingConnectionPool(IEnumerable nodes, bool randomize = true, ID : base(nodes, randomize, dateTimeProvider) { } public SniffingConnectionPool(IEnumerable nodes, Func nodeScorer, IDateTimeProvider dateTimeProvider = null) - : base(nodes, nodeScorer, false, dateTimeProvider) { } + : base(nodes, nodeScorer, dateTimeProvider) { } /// public override IReadOnlyCollection Nodes diff --git a/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs b/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs index 99afb9c22ae..06981ec1798 100644 --- a/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs +++ b/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs @@ -12,18 +12,36 @@ public class StaticConnectionPool : IConnectionPool private readonly Func _nodeScorer; public StaticConnectionPool(IEnumerable uris, bool randomize = true, IDateTimeProvider dateTimeProvider = null) - : this(uris.Select(uri => new Node(uri)), randomize, dateTimeProvider) { } + : this(uris.Select(uri => new Node(uri)), randomize, null, dateTimeProvider) { } public StaticConnectionPool(IEnumerable nodes, bool randomize = true, IDateTimeProvider dateTimeProvider = null) - : this(nodes, null, randomize, dateTimeProvider) { } + : this(nodes, randomize, null, dateTimeProvider) { } + protected StaticConnectionPool(IEnumerable nodes, bool randomize, int? randomizeSeed = null, IDateTimeProvider dateTimeProvider = null) + { + Randomize = randomize; + Random = !randomize || !randomizeSeed.HasValue + ? new Random() + : new Random(randomizeSeed.Value); + + Initialize(nodes, dateTimeProvider); + } //this constructor is protected because nodeScorer only makes sense on subclasses that support reseeding //otherwise just manually sort `nodes` before instantiating. - protected StaticConnectionPool(IEnumerable nodes, Func nodeScorer = null, bool randomize = true, IDateTimeProvider dateTimeProvider = null) + protected StaticConnectionPool(IEnumerable nodes, Func nodeScorer = null, IDateTimeProvider dateTimeProvider = null) { - nodes.ThrowIfEmpty(nameof(nodes)); + _nodeScorer = nodeScorer; + Initialize(nodes, dateTimeProvider); + } + + private void Initialize(IEnumerable nodes, IDateTimeProvider dateTimeProvider) + { + var nodesProvided = nodes?.ToList() ?? throw new ArgumentNullException(nameof(nodes)); + nodesProvided.ThrowIfEmpty(nameof(nodes)); + DateTimeProvider = dateTimeProvider ?? Net.DateTimeProvider.Default; + string scheme = null; - foreach (var node in nodes) + foreach (var node in nodesProvided) { if (scheme == null) { @@ -34,10 +52,7 @@ protected StaticConnectionPool(IEnumerable nodes, Func nodeSc throw new ArgumentException("Trying to instantiate a connection pool with mixed URI Schemes"); } - DateTimeProvider = dateTimeProvider ?? Net.DateTimeProvider.Default; - Randomize = randomize; - _nodeScorer = nodeScorer; - InternalNodes = SortNodes(nodes) + InternalNodes = SortNodes(nodesProvided) .DistinctBy(n => n.Uri) .ToList(); LastUpdate = DateTimeProvider.Now(); @@ -62,7 +77,7 @@ protected StaticConnectionPool(IEnumerable nodes, Func nodeSc public virtual bool SupportsReseeding => false; /// - public bool UsingSsl { get; } + public bool UsingSsl { get; set; } protected List AliveNodes { @@ -75,10 +90,10 @@ protected List AliveNodes } } - protected IDateTimeProvider DateTimeProvider { get; } + protected IDateTimeProvider DateTimeProvider { get; set; } protected List InternalNodes { get; set; } - protected Random Random { get; } = new Random(); + protected Random Random { get; } protected bool Randomize { get; } /// diff --git a/src/Tests/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.doc.cs b/src/Tests/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.doc.cs index b095d90069f..b08738ff166 100644 --- a/src/Tests/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.doc.cs +++ b/src/Tests/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.doc.cs @@ -7,6 +7,7 @@ using Elasticsearch.Net; using FluentAssertions; using Nest; +using Tests.Configuration; using Tests.Framework; using Tests.XPack.Security.Privileges; @@ -216,20 +217,30 @@ [U] public void Static() } } + //hide + private class SeededRandomConectionPool : StaticConnectionPool + { + public SeededRandomConectionPool(IEnumerable nodes, int seed) + : base(nodes, randomize: true, randomizeSeed: seed, dateTimeProvider: null) + {} + } + // hide [U] public void RandomizedInitialNodes() { - IEnumerable CreatStaticConnectionPools() + IEnumerable CreateSeededPools(int nodeCount, int pools) { - Thread.Sleep(1); - var uris = Enumerable.Range(1, 50).Select(i => new Uri($"https://10.0.0.{i}:9200/")); - yield return new StaticConnectionPool(uris); + var seed = TestConfiguration.Instance.Seed; + var nodes = Enumerable.Range(1, nodeCount) + .Select(i => new Node(new Uri($"https://10.0.0.{i}:9200/"))) + .ToList(); + for(var i = 0; i < nodeCount; i++) + yield return new SeededRandomConectionPool(nodes, seed + i); } - // assertion works on the probability of seeing a Uri other than https://10.0.0.1:9200/ - // as the first value over 50 runs, when randomized. - CreatStaticConnectionPools() - .Take(50) + var connectionPools = CreateSeededPools(100, 100).ToList(); + connectionPools.Should().HaveCount(100); + connectionPools .Select(p => p.CreateView().First().Uri.ToString()) .All(uri => uri == "https://10.0.0.1:9200/") .Should() From 0177cb913199ccf199fa8565b57839a64e9e30f2 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Fri, 18 Oct 2019 10:42:10 +1000 Subject: [PATCH 2/3] Add private setters --- src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs b/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs index 06981ec1798..1bb4895839d 100644 --- a/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs +++ b/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs @@ -77,7 +77,7 @@ private void Initialize(IEnumerable nodes, IDateTimeProvider dateTimeProvi public virtual bool SupportsReseeding => false; /// - public bool UsingSsl { get; set; } + public bool UsingSsl { get; private set; } protected List AliveNodes { @@ -90,7 +90,7 @@ protected List AliveNodes } } - protected IDateTimeProvider DateTimeProvider { get; set; } + protected IDateTimeProvider DateTimeProvider { get; private set;B } protected List InternalNodes { get; set; } protected Random Random { get; } From c03ad8f8618a79bc1e2b6c0bf8d0297a837aa254 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Tue, 22 Oct 2019 08:59:57 +1000 Subject: [PATCH 3/3] Fix compilation error Fat-fingered a 'B' when running a build with CTRL + SHIFT + b... --- src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs b/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs index 1bb4895839d..8ab43e4da80 100644 --- a/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs +++ b/src/Elasticsearch.Net/ConnectionPool/StaticConnectionPool.cs @@ -90,7 +90,7 @@ protected List AliveNodes } } - protected IDateTimeProvider DateTimeProvider { get; private set;B } + protected IDateTimeProvider DateTimeProvider { get; private set; } protected List InternalNodes { get; set; } protected Random Random { get; }