Skip to content

Commit d5141a9

Browse files
authored
Refactor RequestData (#127)
1 parent f4c42c8 commit d5141a9

File tree

48 files changed

+988
-1037
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+988
-1037
lines changed

Elastic.Transport.sln.DotSettings

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ See the LICENSE file in the project root for more information</s:String>
104104
&lt;/Entry.Match&gt;&#xD;
105105
&lt;Entry.SortBy&gt;&#xD;
106106
&lt;Kind Is="Member" /&gt;&#xD;
107-
&lt;Name Is="Enter Pattern Here" /&gt;&#xD;
107+
&lt;Name /&gt;&#xD;
108108
&lt;/Entry.SortBy&gt;&#xD;
109109
&lt;/Entry&gt;&#xD;
110110
&lt;Entry DisplayName="Fields"&gt;&#xD;
@@ -119,7 +119,7 @@ See the LICENSE file in the project root for more information</s:String>
119119
&lt;Entry.SortBy&gt;&#xD;
120120
&lt;Access /&gt;&#xD;
121121
&lt;Readonly /&gt;&#xD;
122-
&lt;Name Is="Enter Pattern Here" /&gt;&#xD;
122+
&lt;Name /&gt;&#xD;
123123
&lt;/Entry.SortBy&gt;&#xD;
124124
&lt;/Entry&gt;&#xD;
125125
&lt;Entry DisplayName="Constructors"&gt;&#xD;
@@ -139,7 +139,7 @@ See the LICENSE file in the project root for more information</s:String>
139139
&lt;/Entry.Match&gt;&#xD;
140140
&lt;Entry.SortBy&gt;&#xD;
141141
&lt;Access /&gt;&#xD;
142-
&lt;Name Is="Enter Pattern Here" /&gt;&#xD;
142+
&lt;Name /&gt;&#xD;
143143
&lt;/Entry.SortBy&gt;&#xD;
144144
&lt;/Entry&gt;&#xD;
145145
&lt;Entry DisplayName="Setup/Teardown Methods" Priority="100"&gt;&#xD;
@@ -203,7 +203,7 @@ See the LICENSE file in the project root for more information</s:String>
203203
&lt;/Entry.Match&gt;&#xD;
204204
&lt;Entry.SortBy&gt;&#xD;
205205
&lt;Kind Is="Member" /&gt;&#xD;
206-
&lt;Name Is="Enter Pattern Here" /&gt;&#xD;
206+
&lt;Name /&gt;&#xD;
207207
&lt;/Entry.SortBy&gt;&#xD;
208208
&lt;/Entry&gt;&#xD;
209209
&lt;Entry DisplayName="Fields"&gt;&#xD;
@@ -218,7 +218,7 @@ See the LICENSE file in the project root for more information</s:String>
218218
&lt;Entry.SortBy&gt;&#xD;
219219
&lt;Access /&gt;&#xD;
220220
&lt;Readonly /&gt;&#xD;
221-
&lt;Name Is="Enter Pattern Here" /&gt;&#xD;
221+
&lt;Name /&gt;&#xD;
222222
&lt;/Entry.SortBy&gt;&#xD;
223223
&lt;/Entry&gt;&#xD;
224224
&lt;Entry DisplayName="Constructors"&gt;&#xD;
@@ -238,7 +238,7 @@ See the LICENSE file in the project root for more information</s:String>
238238
&lt;/Entry.Match&gt;&#xD;
239239
&lt;Entry.SortBy&gt;&#xD;
240240
&lt;Access /&gt;&#xD;
241-
&lt;Name Is="Enter Pattern Here" /&gt;&#xD;
241+
&lt;Name /&gt;&#xD;
242242
&lt;/Entry.SortBy&gt;&#xD;
243243
&lt;/Entry&gt;&#xD;
244244
&lt;Entry DisplayName="Interface Implementations"&gt;&#xD;
@@ -251,7 +251,7 @@ See the LICENSE file in the project root for more information</s:String>
251251
&lt;Entry.SortBy&gt;&#xD;
252252
&lt;ImplementsInterface Name="IDisposable" /&gt;&#xD;
253253
&lt;Access /&gt;&#xD;
254-
&lt;Name Is="Enter Pattern Here" /&gt;&#xD;
254+
&lt;Name /&gt;&#xD;
255255
&lt;/Entry.SortBy&gt;&#xD;
256256
&lt;/Entry&gt;&#xD;
257257
&lt;Entry DisplayName="All other members" /&gt;&#xD;
@@ -505,6 +505,7 @@ See the LICENSE file in the project root for more information</s:String>
505505
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
506506
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
507507
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
508+
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002EMemberReordering_002EMigrations_002ECSharpFileLayoutPatternRemoveIsAttributeUpgrade/@EntryIndexedValue">True</s:Boolean>
508509
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
509510
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
510511
<s:Boolean x:Key="/Default/HighlightingManager/HighlightingEnabledByDefault/@EntryValue">False</s:Boolean>

src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
#nullable enable
56
using System;
67
using System.Collections.Generic;
78
using System.IO;
@@ -34,7 +35,7 @@ public class VirtualClusterRequestInvoker : IRequestInvoker
3435
{
3536
private static readonly object Lock = new();
3637

37-
private static byte[] _defaultResponseBytes;
38+
private static byte[]? _defaultResponseBytes;
3839

3940
private VirtualCluster _cluster;
4041
private readonly TestableDateTimeProvider _dateTimeProvider;
@@ -45,7 +46,9 @@ public class VirtualClusterRequestInvoker : IRequestInvoker
4546

4647
internal VirtualClusterRequestInvoker(VirtualCluster cluster, TestableDateTimeProvider dateTimeProvider)
4748
{
48-
UpdateCluster(cluster);
49+
_cluster = cluster;
50+
_calls = cluster.Nodes.ToDictionary(n => n.Uri.Port, v => new State());
51+
_productRegistration = cluster.ProductRegistration;
4952
_dateTimeProvider = dateTimeProvider;
5053
_productRegistration = cluster.ProductRegistration;
5154
_inMemoryRequestInvoker = new InMemoryRequestInvoker();
@@ -100,52 +103,55 @@ private static object DefaultResponse
100103

101104
private void UpdateCluster(VirtualCluster cluster)
102105
{
103-
if (cluster == null) return;
104-
105106
lock (Lock)
106107
{
107108
_cluster = cluster;
108109
_calls = cluster.Nodes.ToDictionary(n => n.Uri.Port, v => new State());
109110
_productRegistration = cluster.ProductRegistration;
110111
}
112+
111113
}
112114

113-
private bool IsSniffRequest(RequestData requestData) => _productRegistration.IsSniffRequest(requestData);
115+
private bool IsSniffRequest(Endpoint endpoint) => _productRegistration.IsSniffRequest(endpoint);
114116

115-
private bool IsPingRequest(RequestData requestData) => _productRegistration.IsPingRequest(requestData);
117+
private bool IsPingRequest(Endpoint endpoint) => _productRegistration.IsPingRequest(endpoint);
116118

117119
/// <inheritdoc cref="IRequestInvoker.RequestAsync{TResponse}"/>>
118-
public Task<TResponse> RequestAsync<TResponse>(RequestData requestData, CancellationToken cancellationToken)
120+
public Task<TResponse> RequestAsync<TResponse>(Endpoint endpoint, RequestData requestData, PostData? postData, CancellationToken cancellationToken)
119121
where TResponse : TransportResponse, new() =>
120-
Task.FromResult(Request<TResponse>(requestData));
122+
Task.FromResult(Request<TResponse>(endpoint, requestData, postData));
121123

122124
/// <inheritdoc cref="IRequestInvoker.Request{TResponse}"/>>
123-
public TResponse Request<TResponse>(RequestData requestData)
125+
public TResponse Request<TResponse>(Endpoint endpoint, RequestData requestData, PostData? postData)
124126
where TResponse : TransportResponse, new()
125127
{
126-
if (!_calls.ContainsKey(requestData.Uri.Port))
127-
throw new Exception($"Expected a call to happen on port {requestData.Uri.Port} but received none");
128+
if (!_calls.ContainsKey(endpoint.Uri.Port))
129+
throw new Exception($"Expected a call to happen on port {endpoint.Uri.Port} but received none");
128130

129131
try
130132
{
131-
var state = _calls[requestData.Uri.Port];
132-
if (IsSniffRequest(requestData))
133+
var state = _calls[endpoint.Uri.Port];
134+
if (IsSniffRequest(endpoint))
133135
{
134136
_ = Interlocked.Increment(ref state.Sniffed);
135137
return HandleRules<TResponse, ISniffRule>(
138+
endpoint,
136139
requestData,
140+
postData,
137141
nameof(VirtualCluster.Sniff),
138142
_cluster.SniffingRules,
139143
requestData.RequestTimeout,
140144
(r) => UpdateCluster(r.NewClusterState),
141145
(r) => _productRegistration.CreateSniffResponseBytes(_cluster.Nodes, _cluster.ElasticsearchVersion, _cluster.PublishAddressOverride, _cluster.SniffShouldReturnFqnd)
142146
);
143147
}
144-
if (IsPingRequest(requestData))
148+
if (IsPingRequest(endpoint))
145149
{
146150
_ = Interlocked.Increment(ref state.Pinged);
147151
return HandleRules<TResponse, IRule>(
152+
endpoint,
148153
requestData,
154+
postData,
149155
nameof(VirtualCluster.Ping),
150156
_cluster.PingingRules,
151157
requestData.PingTimeout,
@@ -155,7 +161,9 @@ public TResponse Request<TResponse>(RequestData requestData)
155161
}
156162
_ = Interlocked.Increment(ref state.Called);
157163
return HandleRules<TResponse, IClientCallRule>(
164+
endpoint,
158165
requestData,
166+
postData,
159167
nameof(VirtualCluster.ClientCalls),
160168
_cluster.ClientCallRules,
161169
requestData.RequestTimeout,
@@ -165,22 +173,23 @@ public TResponse Request<TResponse>(RequestData requestData)
165173
}
166174
catch (TheException e)
167175
{
168-
return requestData.ConnectionSettings.ProductRegistration.ResponseBuilder.ToResponse<TResponse>(requestData, e, null, null, Stream.Null, null, -1, null, null);
176+
return requestData.ConnectionSettings.ProductRegistration.ResponseBuilder.ToResponse<TResponse>(endpoint, requestData, postData, e, null, null, Stream.Null, null, -1, null, null);
169177
}
170178
}
171179

172180
private TResponse HandleRules<TResponse, TRule>(
181+
Endpoint endpoint,
173182
RequestData requestData,
183+
PostData? postData,
174184
string origin,
175185
IList<TRule> rules,
176186
TimeSpan timeout,
177187
Action<TRule> beforeReturn,
178-
Func<TRule, byte[]> successResponse
188+
Func<TRule, byte[]?> successResponse
179189
)
180190
where TResponse : TransportResponse, new()
181191
where TRule : IRule
182192
{
183-
requestData.MadeItToResponse = true;
184193
if (rules.Count == 0)
185194
throw new Exception($"No {origin} defined for the current VirtualCluster, so we do not know how to respond");
186195

@@ -189,32 +198,31 @@ Func<TRule, byte[]> successResponse
189198
var always = rule.Times.Match(t => true, t => false);
190199
var times = rule.Times.Match(t => -1, t => t);
191200

192-
if (rule.OnPort == null || rule.OnPort.Value != requestData.Uri.Port) continue;
201+
if (rule.OnPort == null || rule.OnPort.Value != endpoint.Uri.Port) continue;
193202

194203
if (always)
195-
return Always<TResponse, TRule>(requestData, timeout, beforeReturn, successResponse, rule);
204+
return Always<TResponse, TRule>(endpoint, requestData, postData, timeout, beforeReturn, successResponse, rule);
196205

197206
if (rule.ExecuteCount > times) continue;
198207

199-
return Sometimes<TResponse, TRule>(requestData, timeout, beforeReturn, successResponse, rule);
208+
return Sometimes<TResponse, TRule>(endpoint, requestData, postData, timeout, beforeReturn, successResponse, rule);
200209
}
201210
foreach (var rule in rules.Where(s => !s.OnPort.HasValue))
202211
{
203212
var always = rule.Times.Match(t => true, t => false);
204213
var times = rule.Times.Match(t => -1, t => t);
205214
if (always)
206-
return Always<TResponse, TRule>(requestData, timeout, beforeReturn, successResponse, rule);
215+
return Always<TResponse, TRule>(endpoint, requestData, postData, timeout, beforeReturn, successResponse, rule);
207216

208217
if (rule.ExecuteCount > times) continue;
209218

210-
return Sometimes<TResponse, TRule>(requestData, timeout, beforeReturn, successResponse, rule);
219+
return Sometimes<TResponse, TRule>(endpoint, requestData, postData, timeout, beforeReturn, successResponse, rule);
211220
}
212221
var count = _calls.Select(kv => kv.Value.Called).Sum();
213-
throw new Exception($@"No global or port specific {origin} rule ({requestData.Uri.Port}) matches any longer after {count} calls in to the cluster");
222+
throw new Exception($@"No global or port specific {origin} rule ({endpoint.Uri.Port}) matches any longer after {count} calls in to the cluster");
214223
}
215224

216-
private TResponse Always<TResponse, TRule>(RequestData requestData, TimeSpan timeout, Action<TRule> beforeReturn,
217-
Func<TRule, byte[]> successResponse, TRule rule
225+
private TResponse Always<TResponse, TRule>(Endpoint endpoint, RequestData requestData, PostData? postData, TimeSpan timeout, Action<TRule> beforeReturn, Func<TRule, byte[]?> successResponse, TRule rule
218226
)
219227
where TResponse : TransportResponse, new()
220228
where TRule : IRule
@@ -231,12 +239,12 @@ private TResponse Always<TResponse, TRule>(RequestData requestData, TimeSpan tim
231239
}
232240

233241
return rule.Succeeds
234-
? Success<TResponse, TRule>(requestData, beforeReturn, successResponse, rule)
235-
: Fail<TResponse, TRule>(requestData, rule);
242+
? Success<TResponse, TRule>(endpoint, requestData, postData, beforeReturn, successResponse, rule)
243+
: Fail<TResponse, TRule>(endpoint, requestData, postData, rule);
236244
}
237245

238246
private TResponse Sometimes<TResponse, TRule>(
239-
RequestData requestData, TimeSpan timeout, Action<TRule> beforeReturn, Func<TRule, byte[]> successResponse, TRule rule
247+
Endpoint endpoint, RequestData requestData, PostData? postData, TimeSpan timeout, Action<TRule> beforeReturn, Func<TRule, byte[]?> successResponse, TRule rule
240248
)
241249
where TResponse : TransportResponse, new()
242250
where TRule : IRule
@@ -253,16 +261,16 @@ private TResponse Sometimes<TResponse, TRule>(
253261
}
254262

255263
if (rule.Succeeds)
256-
return Success<TResponse, TRule>(requestData, beforeReturn, successResponse, rule);
264+
return Success<TResponse, TRule>(endpoint, requestData, postData, beforeReturn, successResponse, rule);
257265

258-
return Fail<TResponse, TRule>(requestData, rule);
266+
return Fail<TResponse, TRule>(endpoint, requestData, postData, rule);
259267
}
260268

261-
private TResponse Fail<TResponse, TRule>(RequestData requestData, TRule rule, RuleOption<Exception, int> returnOverride = null)
269+
private TResponse Fail<TResponse, TRule>(Endpoint endpoint, RequestData requestData, PostData? postData, TRule rule, RuleOption<Exception, int>? returnOverride = null)
262270
where TResponse : TransportResponse, new()
263271
where TRule : IRule
264272
{
265-
var state = _calls[requestData.Uri.Port];
273+
var state = _calls[endpoint.Uri.Port];
266274
_ = Interlocked.Increment(ref state.Failures);
267275
var ret = returnOverride ?? rule.Return;
268276
rule.RecordExecuted();
@@ -271,25 +279,25 @@ private TResponse Fail<TResponse, TRule>(RequestData requestData, TRule rule, Ru
271279
throw new TheException();
272280

273281
return ret.Match(
274-
(e) => throw e,
275-
(statusCode) => _inMemoryRequestInvoker.BuildResponse<TResponse>(requestData, CallResponse(rule),
282+
e => throw e,
283+
statusCode => _inMemoryRequestInvoker.BuildResponse<TResponse>(endpoint, requestData, postData, CallResponse(rule),
276284
//make sure we never return a valid status code in Fail responses because of a bad rule.
277285
statusCode >= 200 && statusCode < 300 ? 502 : statusCode, rule.ReturnContentType)
278286
);
279287
}
280288

281-
private TResponse Success<TResponse, TRule>(RequestData requestData, Action<TRule> beforeReturn, Func<TRule, byte[]> successResponse,
289+
private TResponse Success<TResponse, TRule>(Endpoint endpoint, RequestData requestData, PostData? postData, Action<TRule> beforeReturn, Func<TRule, byte[]?> successResponse,
282290
TRule rule
283291
)
284292
where TResponse : TransportResponse, new()
285293
where TRule : IRule
286294
{
287-
var state = _calls[requestData.Uri.Port];
295+
var state = _calls[endpoint.Uri.Port];
288296
_ = Interlocked.Increment(ref state.Successes);
289297
rule.RecordExecuted();
290298

291299
beforeReturn?.Invoke(rule);
292-
return _inMemoryRequestInvoker.BuildResponse<TResponse>(requestData, successResponse(rule), contentType: rule.ReturnContentType);
300+
return _inMemoryRequestInvoker.BuildResponse<TResponse>(endpoint, requestData, postData, successResponse(rule), contentType: rule.ReturnContentType);
293301
}
294302

295303
private static byte[] CallResponse<TRule>(TRule rule)

src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public class VirtualizedCluster
1818
private Func<ITransport<ITransportConfiguration>, Func<RequestConfigurationDescriptor, IRequestConfiguration>, Task<TransportResponse>> _asyncCall;
1919
private Func<ITransport<ITransportConfiguration>, Func<RequestConfigurationDescriptor, IRequestConfiguration>, TransportResponse> _syncCall;
2020

21-
private class VirtualResponse : TransportResponse { }
21+
private class VirtualResponse : TransportResponse;
22+
23+
private static readonly EndpointPath RootPath = new(HttpMethod.GET, "/");
2224

2325
internal VirtualizedCluster(TestableDateTimeProvider dateTimeProvider, TransportConfiguration settings)
2426
{
@@ -27,24 +29,20 @@ internal VirtualizedCluster(TestableDateTimeProvider dateTimeProvider, Transport
2729
_exposingRequestPipeline = new ExposingPipelineFactory<ITransportConfiguration>(settings, _dateTimeProvider);
2830

2931
_syncCall = (t, r) => t.Request<VirtualResponse>(
30-
method: HttpMethod.GET,
31-
path: "/",
32+
path: RootPath,
3233
postData: PostData.Serializable(new { }),
33-
requestParameters: new DefaultRequestParameters(),
3434
openTelemetryData: default,
35-
localConfiguration: r?.Invoke(new RequestConfigurationDescriptor(null)),
35+
localConfiguration: r?.Invoke(new RequestConfigurationDescriptor()),
3636
responseBuilder: null
3737
);
3838
_asyncCall = async (t, r) =>
3939
{
4040
var res = await t.RequestAsync<VirtualResponse>
4141
(
42-
method: HttpMethod.GET,
43-
path: "/",
42+
path: RootPath,
4443
postData: PostData.Serializable(new { }),
45-
requestParameters: new DefaultRequestParameters(),
4644
openTelemetryData: default,
47-
localConfiguration: r?.Invoke(new RequestConfigurationDescriptor(null)),
45+
localConfiguration: r?.Invoke(new RequestConfigurationDescriptor()),
4846
responseBuilder: null,
4947
CancellationToken.None
5048
).ConfigureAwait(false);

src/Elastic.Transport.VirtualizedCluster/Products/Elasticsearch/ElasticsearchMockProductRegistration.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ public sealed class ElasticsearchMockProductRegistration : MockProductRegistrati
2222
public override byte[] CreateSniffResponseBytes(IReadOnlyList<Node> nodes, string stackVersion, string publishAddressOverride, bool returnFullyQualifiedDomainNames) =>
2323
ElasticsearchSniffResponseFactory.Create(nodes, stackVersion, publishAddressOverride, returnFullyQualifiedDomainNames);
2424

25-
public override bool IsSniffRequest(RequestData requestData) =>
26-
requestData.PathAndQuery.StartsWith(ElasticsearchProductRegistration.SniffPath, StringComparison.Ordinal);
25+
public override bool IsSniffRequest(Endpoint endpoint) =>
26+
endpoint.PathAndQuery.StartsWith(ElasticsearchProductRegistration.SniffPath, StringComparison.Ordinal);
2727

28-
public override bool IsPingRequest(RequestData requestData) =>
29-
requestData.Method == HttpMethod.HEAD &&
30-
(requestData.PathAndQuery == string.Empty || requestData.PathAndQuery.StartsWith("?"));
28+
public override bool IsPingRequest(Endpoint endpoint) =>
29+
endpoint.Method == HttpMethod.HEAD && (endpoint.PathAndQuery == string.Empty || endpoint.PathAndQuery.StartsWith("?"));
3130
}

src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public abstract class MockProductRegistration
3131
/// see <see cref="VirtualClusterRequestInvoker.Request{TResponse}"/> uses this to determine if the current request is a sniff request and should follow
3232
/// the sniffing rules
3333
/// </summary>
34-
public abstract bool IsSniffRequest(RequestData requestData);
34+
public abstract bool IsSniffRequest(Endpoint endpoint);
3535

36-
public abstract bool IsPingRequest(RequestData requestData);
36+
public abstract bool IsPingRequest(Endpoint endpoint);
3737
}

0 commit comments

Comments
 (0)