Skip to content

Commit 16c5cb2

Browse files
committed
Transport does not own Semaphore, ConnectionSettings does
1 parent d2c32ce commit 16c5cb2

File tree

6 files changed

+86
-55
lines changed

6 files changed

+86
-55
lines changed

src/Elasticsearch.Net/Configuration/ConnectionConfiguration.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Specialized;
33
using System.ComponentModel;
4+
using System.Threading;
45

56
namespace Elasticsearch.Net
67
{
@@ -56,6 +57,9 @@ public ConnectionConfiguration(IConnectionPool connectionPool, IConnection conne
5657
public abstract class ConnectionConfiguration<T> : IConnectionConfigurationValues, IHideObjectMembers
5758
where T : ConnectionConfiguration<T>
5859
{
60+
private SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
61+
SemaphoreSlim IConnectionConfigurationValues.BootstrapLock => this._semaphore;
62+
5963
private TimeSpan _requestTimeout;
6064
TimeSpan IConnectionConfigurationValues.RequestTimeout => _requestTimeout;
6165

@@ -316,6 +320,7 @@ protected virtual void DisposeManagedResources()
316320
{
317321
this._connectionPool?.Dispose();
318322
this._connection?.Dispose();
323+
this._semaphore?.Dispose();
319324
}
320325
}
321326
}

src/Elasticsearch.Net/Configuration/IConnectionConfigurationValues.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
using System;
22
using System.Collections.Specialized;
3+
using System.Threading;
34

45
namespace Elasticsearch.Net
56
{
67
public interface IConnectionConfigurationValues : IDisposable
78
{
9+
/// <summary> Provides a semaphoreslim to transport implementations that need to limit access to a resource</summary>
10+
SemaphoreSlim BootstrapLock { get; }
11+
812
/// <summary> The connection pool to use when talking with elasticsearch </summary>
913
IConnectionPool ConnectionPool { get; }
1014

src/Elasticsearch.Net/Transport/Transport.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ namespace Elasticsearch.Net
88
public class Transport<TConnectionSettings> : ITransport<TConnectionSettings>, IDisposable
99
where TConnectionSettings : IConnectionConfigurationValues
1010
{
11-
private readonly SemaphoreSlim _semaphore;
12-
1311
//TODO should all of these be public?
1412
public TConnectionSettings Settings { get; }
1513
public IDateTimeProvider DateTimeProvider { get; }
@@ -38,7 +36,6 @@ public Transport(
3836
IMemoryStreamFactory memoryStreamFactory
3937
)
4038
{
41-
4239
configurationValues.ThrowIfNull(nameof(configurationValues));
4340
configurationValues.ConnectionPool.ThrowIfNull(nameof(configurationValues.ConnectionPool));
4441
configurationValues.Connection.ThrowIfNull(nameof(configurationValues.Connection));
@@ -48,15 +45,14 @@ IMemoryStreamFactory memoryStreamFactory
4845
this.PipelineProvider = pipelineProvider ?? new RequestPipelineFactory();
4946
this.DateTimeProvider = dateTimeProvider ?? Net.DateTimeProvider.Default;
5047
this.MemoryStreamFactory = memoryStreamFactory ?? new MemoryStreamFactory();
51-
this._semaphore = new SemaphoreSlim(1, 1);
5248
}
5349

5450
public ElasticsearchResponse<TReturn> Request<TReturn>(HttpMethod method, string path, PostData<object> data = null, IRequestParameters requestParameters = null)
5551
where TReturn : class
5652
{
5753
using (var pipeline = this.PipelineProvider.Create(this.Settings, this.DateTimeProvider, this.MemoryStreamFactory, requestParameters))
5854
{
59-
pipeline.FirstPoolUsage(this._semaphore);
55+
pipeline.FirstPoolUsage(this.Settings.BootstrapLock);
6056

6157
var requestData = new RequestData(method, path, data, this.Settings, requestParameters, this.MemoryStreamFactory);
6258
ElasticsearchResponse<TReturn> response = null;
@@ -113,7 +109,7 @@ public async Task<ElasticsearchResponse<TReturn>> RequestAsync<TReturn>(HttpMeth
113109
{
114110
using (var pipeline = this.PipelineProvider.Create(this.Settings, this.DateTimeProvider, this.MemoryStreamFactory, requestParameters))
115111
{
116-
await pipeline.FirstPoolUsageAsync(this._semaphore);
112+
await pipeline.FirstPoolUsageAsync(this.Settings.BootstrapLock);
117113

118114
var requestData = new RequestData(method, path, data, this.Settings, requestParameters, this.MemoryStreamFactory);
119115
ElasticsearchResponse<TReturn> response = null;
@@ -193,9 +189,6 @@ private static async Task PingAsync(IRequestPipeline pipeline, Node node, List<P
193189

194190
void IDisposable.Dispose() => this.DisposeManagedResources();
195191

196-
protected virtual void DisposeManagedResources()
197-
{
198-
this._semaphore?.Dispose();
199-
}
192+
protected virtual void DisposeManagedResources() { }
200193
}
201194
}

src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,35 @@ await audit.TraceCall(new ClientCall
3737
});
3838
}
3939

40+
[U] [SuppressMessage("AsyncUsage", "AsyncFixer001:Unnecessary async/await usage", Justification = "Its a test")]
41+
public async Task ASniffOnStartupHappensOnce()
42+
{
43+
var audit = new Auditor(() => Framework.Cluster
44+
.Nodes(10)
45+
.Sniff(s => s.Fails(Always))
46+
.Sniff(s => s.OnPort(9202).Succeeds(Always))
47+
.SniffingConnectionPool()
48+
.AllDefaults()
49+
);
50+
51+
await audit.TraceCalls(
52+
new ClientCall
53+
{
54+
{ SniffOnStartup},
55+
{ SniffFailure, 9200},
56+
{ SniffFailure, 9201},
57+
{ SniffSuccess, 9202},
58+
{ PingSuccess , 9200},
59+
{ HealthyResponse, 9200}
60+
},
61+
new ClientCall
62+
{
63+
{ PingSuccess, 9201},
64+
{ HealthyResponse, 9201}
65+
}
66+
);
67+
}
68+
4069
[U] [SuppressMessage("AsyncUsage", "AsyncFixer001:Unnecessary async/await usage", Justification = "Its a test")]
4170
public async Task SniffOnStartUpTakesNewClusterState()
4271
{

src/Tests/Framework/VirtualClustering/FixedPipelineFactory.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ namespace Tests.Framework
55
{
66
public class FixedPipelineFactory : IRequestPipelineFactory
77
{
8-
public IConnectionSettingsValues Settings { get; }
9-
public Transport<IConnectionSettingsValues> Transport { get; }
10-
public IRequestPipeline Pipeline { get; }
8+
private IConnectionSettingsValues Settings { get; }
9+
private Transport<IConnectionSettingsValues> Transport =>
10+
new Transport<IConnectionSettingsValues>(this.Settings, this, this.DateTimeProvider, this.MemoryStreamFactory);
11+
12+
private IDateTimeProvider DateTimeProvider { get; }
13+
private MemoryStreamFactory MemoryStreamFactory { get; }
1114

12-
public IDateTimeProvider DateTimeProvider { get; }
13-
public MemoryStreamFactory MemoryStreamFactory { get; }
15+
public IRequestPipeline Pipeline { get; }
1416

1517
public ElasticClient Client => new ElasticClient(this.Transport);
1618

@@ -21,7 +23,6 @@ public FixedPipelineFactory(IConnectionSettingsValues connectionSettings, IDateT
2123

2224
this.Settings = connectionSettings;
2325
this.Pipeline = this.Create(this.Settings, this.DateTimeProvider, this.MemoryStreamFactory, new SearchRequestParameters());
24-
this.Transport = new Transport<IConnectionSettingsValues>(this.Settings, this, this.DateTimeProvider, this.MemoryStreamFactory);
2526
}
2627

2728
public IRequestPipeline Create(IConnectionConfigurationValues configurationValues, IDateTimeProvider dateTimeProvider, IMemoryStreamFactory memorystreamFactory, IRequestParameters requestParameters) =>
Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,41 @@
1-
using System;
2-
using System.Threading.Tasks;
1+
using System;
2+
using System.Threading.Tasks;
33
using Elasticsearch.Net;
44
using Nest;
5-
using Tests.Framework.MockData;
6-
7-
namespace Tests.Framework
8-
{
9-
public class VirtualizedCluster
10-
{
11-
private readonly ElasticClient _client;
12-
private readonly VirtualCluster _cluster;
13-
private readonly IConnectionPool _connectionPool;
14-
private readonly TestableDateTimeProvider _dateTimeProvider;
15-
private readonly ConnectionSettings _settings;
16-
public FixedPipelineFactory _fixedRequestPipeline;
17-
18-
public IConnectionPool ConnectionPool => this._client.ConnectionSettings.ConnectionPool;
19-
20-
public VirtualizedCluster(VirtualCluster cluster, IConnectionPool pool, TestableDateTimeProvider dateTimeProvider, ConnectionSettings settings)
21-
{
22-
this._dateTimeProvider = dateTimeProvider;
23-
_settings = settings;
24-
this._fixedRequestPipeline = new FixedPipelineFactory(settings, this._dateTimeProvider);
25-
this._client = this._fixedRequestPipeline.Client;
26-
27-
this._cluster = cluster;
28-
this._connectionPool = pool;
29-
}
30-
31-
public ISearchResponse<Project> ClientCall(Func<RequestConfigurationDescriptor, IRequestConfiguration> requestOverrides = null)
32-
=> this._client.Search<Project>(s => s.RequestConfiguration(requestOverrides));
33-
34-
public async Task<ISearchResponse<Project>> ClientCallAsync(Func<RequestConfigurationDescriptor, IRequestConfiguration> requestOverrides = null) =>
35-
await this._client.SearchAsync<Project>(s => s.RequestConfiguration(requestOverrides));
36-
37-
public void ChangeTime(Func<DateTime, DateTime> change) => _dateTimeProvider.ChangeTime(change);
38-
39-
public void ClientThrows(bool throws) => _settings.ThrowExceptions(throws);
40-
}
41-
5+
using Tests.Framework.MockData;
6+
7+
namespace Tests.Framework
8+
{
9+
public class VirtualizedCluster
10+
{
11+
private ElasticClient Client => this._fixedRequestPipeline?.Client;
12+
private readonly VirtualCluster _cluster;
13+
private readonly IConnectionPool _connectionPool;
14+
private readonly TestableDateTimeProvider _dateTimeProvider;
15+
private readonly ConnectionSettings _settings;
16+
public FixedPipelineFactory _fixedRequestPipeline;
17+
18+
public IConnectionPool ConnectionPool => this.Client.ConnectionSettings.ConnectionPool;
19+
20+
public VirtualizedCluster(VirtualCluster cluster, IConnectionPool pool, TestableDateTimeProvider dateTimeProvider, ConnectionSettings settings)
21+
{
22+
this._dateTimeProvider = dateTimeProvider;
23+
this._settings = settings;
24+
this._fixedRequestPipeline = new FixedPipelineFactory(settings, this._dateTimeProvider);
25+
26+
this._cluster = cluster;
27+
this._connectionPool = pool;
28+
}
29+
30+
public ISearchResponse<Project> ClientCall(Func<RequestConfigurationDescriptor, IRequestConfiguration> requestOverrides = null) =>
31+
this.Client.Search<Project>(s => s.RequestConfiguration(requestOverrides));
32+
33+
public async Task<ISearchResponse<Project>> ClientCallAsync(Func<RequestConfigurationDescriptor, IRequestConfiguration> requestOverrides = null) =>
34+
await this.Client.SearchAsync<Project>(s => s.RequestConfiguration(requestOverrides));
35+
36+
public void ChangeTime(Func<DateTime, DateTime> change) => _dateTimeProvider.ChangeTime(change);
37+
38+
public void ClientThrows(bool throws) => _settings.ThrowExceptions(throws);
39+
}
40+
4241
}

0 commit comments

Comments
 (0)