From bded14cddce2c649fe4e912f61ea6782e9695f49 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 30 Aug 2023 14:00:36 +0200 Subject: [PATCH 1/9] Renames - TransportClient => interface IRequestInvoker - HttpTransport => interface ITransport - DefaultHttpTransport => DistributedTransport --- .../TransportBenchmarks.cs | 10 +-- .../Elastic.Transport.Profiling/Program.cs | 2 +- .../Components/ExposingPipelineFactory.cs | 4 +- .../Components/SealedVirtualCluster.cs | 8 +- .../Components/VirtualClusterConnection.cs | 31 ++++--- .../Components/VirtualizedCluster.cs | 18 ++-- .../Products/MockProductRegistration.cs | 8 +- .../Components/NodePool/Node.cs | 4 +- .../Components/NodePool/NodePool.cs | 8 +- .../Components/NodePool/SniffingNodePool.cs | 2 +- .../Components/NodePool/StaticNodePool.cs | 2 +- .../Pipeline/DefaultRequestPipeline.cs | 18 ++-- .../Components/Pipeline/PipelineException.cs | 2 +- .../Components/Pipeline/RequestData.cs | 2 +- .../Components/Serialization/Serializer.cs | 4 +- .../RequestDataHttpClientFactory.cs | 2 +- ...ansportClient.cs => HttpRequestInvoker.cs} | 30 +++++-- .../HttpTransportClient-FullFramework.cs | 2 +- ...portClient.cs => HttpWebRequestInvoker.cs} | 19 +++-- ...{TransportClient.cs => IRequestInvoker.cs} | 53 ++---------- ...ortClient.cs => InMemoryRequestInvoker.cs} | 35 ++++---- .../Configuration/ITransportConfiguration.cs | 12 +-- .../Configuration/TransportConfiguration.cs | 18 ++-- .../Diagnostics/DiagnosticSources.cs | 4 +- .../HttpConnectionDiagnosticObserver.cs | 2 +- ...tpTransport.cs => DistributedTransport.cs} | 50 +++++------ .../{HttpTransport.cs => ITransport.cs} | 12 +-- src/Elastic.Transport/ITransportExtensions.cs | 83 +++++++++++++++++++ .../Products/DefaultProductRegistration.cs | 10 +-- .../ElasticsearchProductRegistration.cs | 16 ++-- .../Products/ProductRegistration.cs | 26 +++--- .../Requests/MetaData/MetaDataHeader.cs | 2 +- .../Responses/TransportResponse.cs | 2 +- src/Elastic.Transport/TransportExtensions.cs | 83 ------------------- .../DefaultCluster.cs | 4 +- .../DefaultClusterTests.cs | 4 +- .../IntegrationTestBase.cs | 4 +- .../SecurityClusterTests.cs | 6 +- .../Http/ApiCompatibilityHeaderTests.cs | 2 +- .../Http/TransferEncodingChunckedTests.cs | 4 +- .../Plumbing/AssemblyServerTestsBase.cs | 2 +- .../Plumbing/ClassServerTestsBase.cs | 2 +- .../Examples/ControllerIntegrationTests.cs | 2 +- .../Examples/EndpointIntegrationTests.cs | 2 +- .../Plumbing/Stubs/TestableHttpConnection.cs | 30 +++---- .../Plumbing/TransportTestServer.cs | 14 ++-- .../CodeStandards/NamingConventions.doc.cs | 4 +- .../Plumbing/InMemoryConnectionFactory.cs | 4 +- tests/Elastic.Transport.Tests/Test.cs | 14 ++-- 49 files changed, 337 insertions(+), 345 deletions(-) rename src/Elastic.Transport/Components/TransportClient/{HttpTransportClient.cs => HttpRequestInvoker.cs} (93%) rename src/Elastic.Transport/Components/TransportClient/{HttpWebRequestTransportClient.cs => HttpWebRequestInvoker.cs} (97%) rename src/Elastic.Transport/Components/TransportClient/{TransportClient.cs => IRequestInvoker.cs} (56%) rename src/Elastic.Transport/Components/TransportClient/{InMemoryTransportClient.cs => InMemoryRequestInvoker.cs} (74%) rename src/Elastic.Transport/{DefaultHttpTransport.cs => DistributedTransport.cs} (90%) rename src/Elastic.Transport/{HttpTransport.cs => ITransport.cs} (94%) create mode 100644 src/Elastic.Transport/ITransportExtensions.cs delete mode 100644 src/Elastic.Transport/TransportExtensions.cs diff --git a/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs b/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs index 088ae23..9355dc4 100644 --- a/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs +++ b/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs @@ -10,22 +10,22 @@ namespace Elastic.Transport.Benchmarks { public class TransportBenchmarks { - private DefaultHttpTransport _transport; + private DistributedTransport _requestHandler; [GlobalSetup] public void Setup() { - var connection = new InMemoryTransportClient(); + var connection = new InMemoryRequestInvoker(); var pool = new SingleNodePool(new Uri("http://localhost:9200")); var settings = new TransportConfiguration(pool, connection); - _transport = new DefaultHttpTransport(settings); + _requestHandler = new DistributedTransport(settings); } [Benchmark] - public void TransportSuccessfulRequestBenchmark() => _transport.Get("/"); + public void TransportSuccessfulRequestBenchmark() => _requestHandler.Get("/"); [Benchmark] - public async Task TransportSuccessfulAsyncRequestBenchmark() => await _transport.GetAsync("/"); + public async Task TransportSuccessfulAsyncRequestBenchmark() => await _requestHandler.GetAsync("/"); } } diff --git a/benchmarks/Elastic.Transport.Profiling/Program.cs b/benchmarks/Elastic.Transport.Profiling/Program.cs index 94855c8..e089a64 100644 --- a/benchmarks/Elastic.Transport.Profiling/Program.cs +++ b/benchmarks/Elastic.Transport.Profiling/Program.cs @@ -19,7 +19,7 @@ private static async Task Main() var config = new TransportConfiguration(new Uri("http://localhost:9200"), new ElasticsearchProductRegistration(typeof(ElasticsearchProductRegistration))); - var transport = new DefaultHttpTransport(config); + var transport = new DistributedTransport(config); // WARMUP for (var i = 0; i < 50; i++) _ = await transport.GetAsync("/"); diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs b/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs index 7bee834..70ca5f0 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs @@ -15,7 +15,7 @@ public ExposingPipelineFactory(TConfiguration connectionSettings, DateTimeProvid MemoryStreamFactory = TransportConfiguration.DefaultMemoryStreamFactory; Settings = connectionSettings; Pipeline = Create(Settings, DateTimeProvider, MemoryStreamFactory, new DefaultRequestParameters()); - Transport = new DefaultHttpTransport(Settings, this, DateTimeProvider, MemoryStreamFactory); + RequestHandler = new DistributedTransport(Settings, this, DateTimeProvider, MemoryStreamFactory); } // ReSharper disable once MemberCanBePrivate.Global @@ -23,7 +23,7 @@ public ExposingPipelineFactory(TConfiguration connectionSettings, DateTimeProvid private DateTimeProvider DateTimeProvider { get; } private MemoryStreamFactory MemoryStreamFactory { get; } private TConfiguration Settings { get; } - public HttpTransport Transport { get; } + public ITransport RequestHandler { get; } public override RequestPipeline Create(TConfiguration configurationValues, DateTimeProvider dateTimeProvider, MemoryStreamFactory memoryStreamFactory, RequestParameters requestParameters) => diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs b/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs index 3f20306..bf0b1c8 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs @@ -11,11 +11,11 @@ namespace Elastic.Transport.VirtualizedCluster.Components; /// /// A continuation of 's builder methods that creates /// an instance of for the cluster after which the components such as -/// and can no longer be updated. +/// and can no longer be updated. /// public sealed class SealedVirtualCluster { - private readonly TransportClient _connection; + private readonly IRequestInvoker _connection; private readonly NodePool _connectionPool; private readonly TestableDateTimeProvider _dateTimeProvider; private readonly MockProductRegistration _productRegistration; @@ -23,7 +23,7 @@ public sealed class SealedVirtualCluster internal SealedVirtualCluster(VirtualCluster cluster, NodePool pool, TestableDateTimeProvider dateTimeProvider, MockProductRegistration productRegistration) { _connectionPool = pool; - _connection = new VirtualClusterTransportClient(cluster, dateTimeProvider); + _connection = new VirtualClusterTransport(cluster, dateTimeProvider); _dateTimeProvider = dateTimeProvider; _productRegistration = productRegistration; } @@ -44,7 +44,7 @@ public VirtualizedCluster Settings(Func using the DSL provided by /// /// Provide custom configuration options - public VirtualClusterTransportClient VirtualClusterConnection(Func selector = null) => + public VirtualClusterTransport VirtualClusterConnection(Func selector = null) => new VirtualizedCluster(_dateTimeProvider, selector == null ? CreateSettings() : selector(CreateSettings())) .Connection; } diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs index 7b03547..da7bdf2 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs @@ -30,7 +30,7 @@ namespace Elastic.Transport.VirtualizedCluster.Components; /// becomes available /// /// -public class VirtualClusterTransportClient : InMemoryTransportClient +public class VirtualClusterTransport : IRequestInvoker { private static readonly object Lock = new(); @@ -41,18 +41,23 @@ public class VirtualClusterTransportClient : InMemoryTransportClient private MockProductRegistration _productRegistration; private IDictionary _calls = new Dictionary(); - internal VirtualClusterTransportClient(VirtualCluster cluster, TestableDateTimeProvider dateTimeProvider) + private readonly InMemoryRequestInvoker _inMemoryRequestInvoker; + + internal VirtualClusterTransport(VirtualCluster cluster, TestableDateTimeProvider dateTimeProvider) { UpdateCluster(cluster); _dateTimeProvider = dateTimeProvider; _productRegistration = cluster.ProductRegistration; + _inMemoryRequestInvoker = new InMemoryRequestInvoker(); } + void IDisposable.Dispose() { } + /// - /// Create a instance that always returns a successful response. + /// Create a instance that always returns a successful response. /// /// The bytes to be returned on every API call invocation - public static VirtualClusterTransportClient Success(byte[] response) => + public static VirtualClusterTransport Success(byte[] response) => Virtual.Elasticsearch .Bootstrap(1) .ClientCalls(r => r.SucceedAlways().ReturnByteResponse(response)) @@ -61,9 +66,9 @@ public static VirtualClusterTransportClient Success(byte[] response) => .Connection; /// - /// Create a instance that always returns a failed response. + /// Create a instance that always returns a failed response. /// - public static VirtualClusterTransportClient Error() => + public static VirtualClusterTransport Error() => Virtual.Elasticsearch .Bootstrap(1) .ClientCalls(r => r.FailAlways(400)) @@ -109,12 +114,14 @@ private void UpdateCluster(VirtualCluster cluster) private bool IsPingRequest(RequestData requestData) => _productRegistration.IsPingRequest(requestData); - /// > - public override Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) => + /// > + public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) + where TResponse : TransportResponse, new() => Task.FromResult(Request(requestData)); - /// > - public override TResponse Request(RequestData requestData) + /// > + public TResponse Request(RequestData requestData) + where TResponse : TransportResponse, new() { if (!_calls.ContainsKey(requestData.Uri.Port)) throw new Exception($"Expected a call to happen on port {requestData.Uri.Port} but received none"); @@ -265,7 +272,7 @@ private TResponse Fail(RequestData requestData, TRule rule, Ru return ret.Match( (e) => throw e, - (statusCode) => ReturnConnectionStatus(requestData, CallResponse(rule), + (statusCode) => _inMemoryRequestInvoker.BuildResponse(requestData, CallResponse(rule), //make sure we never return a valid status code in Fail responses because of a bad rule. statusCode >= 200 && statusCode < 300 ? 502 : statusCode, rule.ReturnContentType) ); @@ -282,7 +289,7 @@ TRule rule rule.RecordExecuted(); beforeReturn?.Invoke(rule); - return ReturnConnectionStatus(requestData, successResponse(rule), contentType: rule.ReturnContentType); + return _inMemoryRequestInvoker.BuildResponse(requestData, successResponse(rule), contentType: rule.ReturnContentType); } private static byte[] CallResponse(TRule rule) diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs index 7bd248d..92999ef 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs @@ -15,8 +15,8 @@ public class VirtualizedCluster private readonly TestableDateTimeProvider _dateTimeProvider; private readonly TransportConfiguration _settings; - private Func, Func, Task> _asyncCall; - private Func, Func, TransportResponse> _syncCall; + private Func, Func, Task> _asyncCall; + private Func, Func, TransportResponse> _syncCall; private class VirtualResponse : TransportResponse { } @@ -48,13 +48,13 @@ internal VirtualizedCluster(TestableDateTimeProvider dateTimeProvider, Transport }; } - public VirtualClusterTransportClient Connection => Transport.Settings.Connection as VirtualClusterTransportClient; - public NodePool ConnectionPool => Transport.Settings.NodePool; - public HttpTransport Transport => _exposingRequestPipeline?.Transport; + public VirtualClusterTransport Connection => RequestHandler.Configuration.Connection as VirtualClusterTransport; + public NodePool ConnectionPool => RequestHandler.Configuration.NodePool; + public ITransport RequestHandler => _exposingRequestPipeline?.RequestHandler; public VirtualizedCluster TransportProxiesTo( - Func, Func, TransportResponse> sync, - Func, Func, Task> async + Func, Func, TransportResponse> sync, + Func, Func, Task> async ) { _syncCall = sync; @@ -63,10 +63,10 @@ Func, Func requestOverrides = null) => - _syncCall(Transport, requestOverrides); + _syncCall(RequestHandler, requestOverrides); public async Task ClientCallAsync(Func requestOverrides = null) => - await _asyncCall(Transport, requestOverrides).ConfigureAwait(false); + await _asyncCall(RequestHandler, requestOverrides).ConfigureAwait(false); public void ChangeTime(Func change) => _dateTimeProvider.ChangeTime(change); diff --git a/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs b/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs index 6f6e864..b93bc7c 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs @@ -9,17 +9,17 @@ namespace Elastic.Transport.VirtualizedCluster.Products; /// -/// Makes sure is mockable by providing a different sniff response based on the current +/// Makes sure is mockable by providing a different sniff response based on the current /// public abstract class MockProductRegistration { /// - /// Information about the current product we are injecting into + /// Information about the current product we are injecting into /// public abstract ProductRegistration ProductRegistration { get; } /// - /// Return the sniff response for the product as raw bytes for to return. + /// Return the sniff response for the product as raw bytes for to return. /// /// The nodes we expect to be returned in the response /// The current version under test @@ -28,7 +28,7 @@ public abstract class MockProductRegistration public abstract byte[] CreateSniffResponseBytes(IReadOnlyList nodes, string stackVersion, string publishAddressOverride, bool returnFullyQualifiedDomainNames); /// - /// see uses this to determine if the current request is a sniff request and should follow + /// see uses this to determine if the current request is a sniff request and should follow /// the sniffing rules /// public abstract bool IsSniffRequest(RequestData requestData); diff --git a/src/Elastic.Transport/Components/NodePool/Node.cs b/src/Elastic.Transport/Components/NodePool/Node.cs index b1c1ae2..8434c47 100644 --- a/src/Elastic.Transport/Components/NodePool/Node.cs +++ b/src/Elastic.Transport/Components/NodePool/Node.cs @@ -10,7 +10,7 @@ namespace Elastic.Transport; /// -/// Represents an endpoint with additional associated metadata on which the can act. +/// Represents an endpoint with additional associated metadata on which the can act. /// public sealed class Node : IEquatable { @@ -65,7 +65,7 @@ public IReadOnlyCollection Features public Uri Uri { get; } /// - /// Indicates whether the node is alive. can take nodes out of rotation by calling + /// Indicates whether the node is alive. can take nodes out of rotation by calling /// on . /// public bool IsAlive { get; private set; } diff --git a/src/Elastic.Transport/Components/NodePool/NodePool.cs b/src/Elastic.Transport/Components/NodePool/NodePool.cs index b997602..97bcc07 100644 --- a/src/Elastic.Transport/Components/NodePool/NodePool.cs +++ b/src/Elastic.Transport/Components/NodePool/NodePool.cs @@ -11,10 +11,10 @@ namespace Elastic.Transport; /// /// A node pool is responsible for maintaining a read only collection of (s) under . /// -/// Unlike the name might suggest this component is not responsible for IO level pooling. For that we rely on abstracting away +/// Unlike the name might suggest this component is not responsible for IO level pooling. For that we rely on abstracting away /// the connection IO pooling. /// -/// This interface signals the current connection strategy to . +/// This interface signals the current connection strategy to . /// public abstract class NodePool : IDisposable { @@ -68,7 +68,7 @@ internal NodePool() { } public abstract bool UsingSsl { get; protected set; } /// - /// + /// /// public void Dispose() { @@ -77,7 +77,7 @@ public void Dispose() } /// - /// + /// /// /// protected virtual void Dispose(bool disposing) diff --git a/src/Elastic.Transport/Components/NodePool/SniffingNodePool.cs b/src/Elastic.Transport/Components/NodePool/SniffingNodePool.cs index 3c88c1c..29ebbbb 100644 --- a/src/Elastic.Transport/Components/NodePool/SniffingNodePool.cs +++ b/src/Elastic.Transport/Components/NodePool/SniffingNodePool.cs @@ -12,7 +12,7 @@ namespace Elastic.Transport; /// -/// A node pool that enables which in turn allows the to enable sniffing to +/// A node pool that enables which in turn allows the to enable sniffing to /// discover the current cluster's list of active nodes. /// public class SniffingNodePool : StaticNodePool diff --git a/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs b/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs index 9a9b73d..eba6840 100644 --- a/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs +++ b/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs @@ -12,7 +12,7 @@ namespace Elastic.Transport; /// -/// A node pool that disables which in turn disallows the to enable sniffing to +/// A node pool that disables which in turn disallows the to enable sniffing to /// discover the current cluster's list of active nodes. /// Therefore the nodes you supply are the list of known nodes throughout its lifetime, hence static /// diff --git a/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs b/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs index 40ef4ba..2a11b77 100644 --- a/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs +++ b/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs @@ -19,7 +19,7 @@ namespace Elastic.Transport; public class DefaultRequestPipeline : RequestPipeline where TConfiguration : class, ITransportConfiguration { - private readonly TransportClient _transportClient; + private readonly IRequestInvoker _requestInvoker; private readonly NodePool _nodePool; private readonly DateTimeProvider _dateTimeProvider; private readonly MemoryStreamFactory _memoryStreamFactory; @@ -29,7 +29,7 @@ public class DefaultRequestPipeline : RequestPipeline private readonly ResponseBuilder _responseBuilder; private RequestConfiguration? _pingAndSniffRequestConfiguration; - private List _auditTrail = null; + private List _auditTrail = null; /// internal DefaultRequestPipeline( @@ -41,7 +41,7 @@ RequestParameters requestParameters { _settings = configurationValues; _nodePool = _settings.NodePool; - _transportClient = _settings.Connection; + _requestInvoker = _settings.Connection; _dateTimeProvider = dateTimeProvider; _memoryStreamFactory = memoryStreamFactory; _productRegistration = configurationValues.ProductRegistration; @@ -185,9 +185,9 @@ private async ValueTask CallProductEndpointCoreAsync(bool TResponse response; if (isAsync) - response = await _transportClient.RequestAsync(requestData, cancellationToken).ConfigureAwait(false); + response = await _requestInvoker.RequestAsync(requestData, cancellationToken).ConfigureAwait(false); else - response = _transportClient.Request(requestData); + response = _requestInvoker.Request(requestData); response.ApiCallDetails.AuditTrail = AuditTrail; @@ -410,9 +410,9 @@ public async ValueTask PingCoreAsync(bool isAsync, Node node, CancellationToken try { if (isAsync) - response = await _productRegistration.PingAsync(_transportClient, pingData, cancellationToken).ConfigureAwait(false); + response = await _productRegistration.PingAsync(_requestInvoker, pingData, cancellationToken).ConfigureAwait(false); else - response = _productRegistration.Ping(_transportClient, pingData); + response = _productRegistration.Ping(_requestInvoker, pingData); ThrowBadAuthPipelineExceptionWhenNeeded(response.ApiCallDetails); @@ -459,11 +459,11 @@ public async ValueTask SniffCoreAsync(bool isAsync, CancellationToken cancellati { if (isAsync) result = await _productRegistration - .SniffAsync(_transportClient, _nodePool.UsingSsl, requestData, cancellationToken) + .SniffAsync(_requestInvoker, _nodePool.UsingSsl, requestData, cancellationToken) .ConfigureAwait(false); else result = _productRegistration - .Sniff(_transportClient, _nodePool.UsingSsl, requestData); + .Sniff(_requestInvoker, _nodePool.UsingSsl, requestData); ThrowBadAuthPipelineExceptionWhenNeeded(result.Item1.ApiCallDetails); diff --git a/src/Elastic.Transport/Components/Pipeline/PipelineException.cs b/src/Elastic.Transport/Components/Pipeline/PipelineException.cs index 568b60d..3d7044c 100644 --- a/src/Elastic.Transport/Components/Pipeline/PipelineException.cs +++ b/src/Elastic.Transport/Components/Pipeline/PipelineException.cs @@ -24,7 +24,7 @@ public PipelineException(PipelineFailure failure, Exception innerException) public PipelineFailure FailureReason { get; } /// - /// This exception is one the can handle + /// This exception is one the can handle /// /// /// diff --git a/src/Elastic.Transport/Components/Pipeline/RequestData.cs b/src/Elastic.Transport/Components/Pipeline/RequestData.cs index 800dd17..bb6e081 100644 --- a/src/Elastic.Transport/Components/Pipeline/RequestData.cs +++ b/src/Elastic.Transport/Components/Pipeline/RequestData.cs @@ -13,7 +13,7 @@ namespace Elastic.Transport; /// -/// Where and how should connect to. +/// Where and how should connect to. /// /// Represents the cumulative configuration from /// and . diff --git a/src/Elastic.Transport/Components/Serialization/Serializer.cs b/src/Elastic.Transport/Components/Serialization/Serializer.cs index fa996fc..04e3744 100644 --- a/src/Elastic.Transport/Components/Serialization/Serializer.cs +++ b/src/Elastic.Transport/Components/Serialization/Serializer.cs @@ -10,10 +10,10 @@ namespace Elastic.Transport; /// -/// When the needs to (de)serialize anything it will call into the +/// When the needs to (de)serialize anything it will call into the /// implementation of this base class. /// -/// e.g: Whenever the receives +/// e.g: Whenever the receives /// to serialize that data. /// public abstract class Serializer diff --git a/src/Elastic.Transport/Components/TransportClient/HandlerTracking/RequestDataHttpClientFactory.cs b/src/Elastic.Transport/Components/TransportClient/HandlerTracking/RequestDataHttpClientFactory.cs index 8343a3d..a2c82b8 100644 --- a/src/Elastic.Transport/Components/TransportClient/HandlerTracking/RequestDataHttpClientFactory.cs +++ b/src/Elastic.Transport/Components/TransportClient/HandlerTracking/RequestDataHttpClientFactory.cs @@ -91,7 +91,7 @@ public HttpClient CreateClient(RequestData requestData) { if (requestData == null) throw new ArgumentNullException(nameof(requestData)); - var key = HttpTransportClient.GetClientKey(requestData); + var key = HttpRequestInvoker.GetClientKey(requestData); var handler = CreateHandler(key, requestData); var client = new HttpClient(handler, disposeHandler: false) { diff --git a/src/Elastic.Transport/Components/TransportClient/HttpTransportClient.cs b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs similarity index 93% rename from src/Elastic.Transport/Components/TransportClient/HttpTransportClient.cs rename to src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs index 6fbf715..76df7b1 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpTransportClient.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs @@ -23,7 +23,7 @@ namespace Elastic.Transport; /// The default TransportClient implementation. Uses . -public class HttpTransportClient : TransportClient +public class HttpRequestInvoker : IRequestInvoker { private static readonly string MissingConnectionLimitMethodError = $"Your target platform does not support {nameof(TransportConfiguration.ConnectionLimit)}" @@ -32,8 +32,14 @@ public class HttpTransportClient : TransportClient private string _expectedCertificateFingerprint; - /// - public HttpTransportClient() => HttpClientFactory = new RequestDataHttpClientFactory(r => CreateHttpClientHandler(r)); + /// + public HttpRequestInvoker() => HttpClientFactory = new RequestDataHttpClientFactory(r => CreateHttpClientHandler(r)); + + /// + /// Allows users to inject their own HttpMessageHandler, and optionally call our default implementation + /// + public HttpRequestInvoker(Func, RequestData, HttpMessageHandler> createHttpHandler) => + HttpClientFactory = new RequestDataHttpClientFactory(r => CreateHttpClientHandler(r)); /// public int InUseHandlers => HttpClientFactory.InUseHandlers; @@ -45,11 +51,11 @@ public class HttpTransportClient : TransportClient private RequestDataHttpClientFactory HttpClientFactory { get; } - /// + /// public override TResponse Request(RequestData requestData) => RequestCoreAsync(false, requestData).EnsureCompleted(); - /// + /// public override Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) => RequestCoreAsync(true, requestData, cancellationToken).AsTask(); @@ -210,14 +216,14 @@ private static Dictionary> ParseHeaders(RequestData /// /// Creates an instance of using the . - /// This method is virtual so subclasses of can modify the instance if needed. + /// This method is virtual so subclasses of can modify the instance if needed. /// /// An instance of describing where and how to call out to /// /// Can throw if is set but the platform does /// not allow this to be set on /// - protected virtual HttpMessageHandler CreateHttpClientHandler(RequestData requestData) + protected HttpMessageHandler CreateHttpClientHandler(RequestData requestData) { var handler = new HttpClientHandler { AutomaticDecompression = requestData.HttpCompression ? GZip | Deflate : None, }; @@ -300,7 +306,7 @@ private string ComparableFingerprint(string fingerprint) /// /// Creates an instance of using the . - /// This method is virtual so subclasses of can modify the instance if needed. + /// This method is virtual so subclasses of can modify the instance if needed. /// /// An instance of describing where and how to call out to /// @@ -489,7 +495,13 @@ internal static int GetClientKey(RequestData requestData) } } + /// Allows subclasses to dispose of managed resources + public virtual void DisposeManagedResources() {} /// - protected override void DisposeManagedResources() => HttpClientFactory.Dispose(); + public void Dispose() + { + HttpClientFactory.Dispose(); + DisposeManagedResources(); + } } #endif diff --git a/src/Elastic.Transport/Components/TransportClient/HttpTransportClient-FullFramework.cs b/src/Elastic.Transport/Components/TransportClient/HttpTransportClient-FullFramework.cs index 2aeeb76..06d8344 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpTransportClient-FullFramework.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpTransportClient-FullFramework.cs @@ -8,6 +8,6 @@ namespace Elastic.Transport { /// The default TransportClient implementation. Uses on the current .NET desktop framework. - public class HttpTransportClient : HttpWebRequestTransportClient { } + public class HttpRequestInvoker : HttpWebRequestInvoker { } } #endif diff --git a/src/Elastic.Transport/Components/TransportClient/HttpWebRequestTransportClient.cs b/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs similarity index 97% rename from src/Elastic.Transport/Components/TransportClient/HttpWebRequestTransportClient.cs rename to src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs index 296a724..47bb74c 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpWebRequestTransportClient.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs @@ -20,9 +20,9 @@ namespace Elastic.Transport; /// -/// This provides an implementation that targets . +/// This provides an implementation that targets . /// -/// On .NET full framework is an alias to this. +/// On .NET full framework is an alias to this. /// /// /// Do NOT use this class directly on .NET Core. is monkey patched @@ -32,26 +32,26 @@ namespace Elastic.Transport; #if !NETFRAMEWORK [Obsolete("CoreFX HttpWebRequest uses HttpClient under the covers but does not reuse HttpClient instances, do NOT use on .NET core only used as the default on Full Framework")] #endif -public class HttpWebRequestTransportClient : TransportClient +public class HttpWebRequestInvoker : IRequestInvoker { private string _expectedCertificateFingerprint; - static HttpWebRequestTransportClient() + static HttpWebRequestInvoker() { //Not available under mono if (!IsMono) HttpWebRequest.DefaultMaximumErrorResponseLength = -1; } - /// > - public HttpWebRequestTransportClient() { } + /// > + public HttpWebRequestInvoker() { } internal static bool IsMono { get; } = Type.GetType("Mono.Runtime") != null; - /// > + /// > public override TResponse Request(RequestData requestData) => RequestCoreAsync(false, requestData).EnsureCompleted(); - /// > + /// > public override Task RequestAsync(RequestData requestData, CancellationToken cancellationToken = default) => RequestCoreAsync(true, requestData, cancellationToken).AsTask(); @@ -122,7 +122,7 @@ private async ValueTask RequestCoreAsync(bool isAsync, Req //Either the stream or the response object needs to be closed but not both although it won't //throw any errors if both are closed atleast one of them has to be Closed. //Since we expose the stream we let closing the stream determining when to close the connection - + if (requestData.TcpStats) tcpStats = TcpStats.GetStates(); @@ -450,4 +450,5 @@ private static void HandleResponse(HttpWebResponse response, out int? statusCode // if stream is null call dispose on response instead. if (responseStream == null || responseStream == Stream.Null) response.Dispose(); } + } diff --git a/src/Elastic.Transport/Components/TransportClient/TransportClient.cs b/src/Elastic.Transport/Components/TransportClient/IRequestInvoker.cs similarity index 56% rename from src/Elastic.Transport/Components/TransportClient/TransportClient.cs rename to src/Elastic.Transport/Components/TransportClient/IRequestInvoker.cs index 29528c0..2dcf160 100644 --- a/src/Elastic.Transport/Components/TransportClient/TransportClient.cs +++ b/src/Elastic.Transport/Components/TransportClient/IRequestInvoker.cs @@ -9,18 +9,13 @@ namespace Elastic.Transport; /// -/// This interface abstracts the actual IO performs. -/// holds a single instance of this class +/// This interface abstracts the actual IO performs. +/// holds a single instance of this class /// The instance to be used is provided to the constructor of implementations /// Where its exposed under /// -public abstract class TransportClient : IDisposable +public interface IRequestInvoker : IDisposable { - private bool _disposed = false; - - /// - protected TransportClient() { } - /// /// Perform a request to the endpoint described by using its associated configuration. /// @@ -28,15 +23,15 @@ protected TransportClient() { } /// /// /// An implementation of ensuring enough information is available - /// for and to determine what to + /// for and to determine what to /// do with the response /// /// /// An implementation of ensuring enough information is available - /// for and to determine what to + /// for and to determine what to /// do with the response /// - public abstract Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) + public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) where TResponse : TransportResponse, new(); /// @@ -45,45 +40,15 @@ public abstract Task RequestAsync(RequestData requestData, /// An object describing where and how to perform the IO call /// /// An implementation of ensuring enough information is available - /// for and to determine what to + /// for and to determine what to /// do with the response /// /// /// An implementation of ensuring enough information is available - /// for and to determine what to + /// for and to determine what to /// do with the response /// - public abstract TResponse Request(RequestData requestData) + public TResponse Request(RequestData requestData) where TResponse : TransportResponse, new(); - /// - /// - /// - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); - } - - /// - /// - /// - /// - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - DisposeManagedResources(); - } - - _disposed = true; - } - - /// - /// - /// - protected virtual void DisposeManagedResources() { } } diff --git a/src/Elastic.Transport/Components/TransportClient/InMemoryTransportClient.cs b/src/Elastic.Transport/Components/TransportClient/InMemoryRequestInvoker.cs similarity index 74% rename from src/Elastic.Transport/Components/TransportClient/InMemoryTransportClient.cs rename to src/Elastic.Transport/Components/TransportClient/InMemoryRequestInvoker.cs index d150aac..8a34800 100644 --- a/src/Elastic.Transport/Components/TransportClient/InMemoryTransportClient.cs +++ b/src/Elastic.Transport/Components/TransportClient/InMemoryRequestInvoker.cs @@ -13,9 +13,9 @@ namespace Elastic.Transport; /// -/// An implementation of designed to not actually do any IO and services requests from an in memory byte buffer +/// An implementation of designed to not actually do any IO and services requests from an in memory byte buffer /// -public class InMemoryTransportClient : TransportClient +public class InMemoryRequestInvoker : IRequestInvoker { private static readonly byte[] EmptyBody = Encoding.UTF8.GetBytes(""); private readonly string _contentType; @@ -28,10 +28,10 @@ public class InMemoryTransportClient : TransportClient /// Every request will succeed with this overload, note that it won't actually return mocked responses /// so using this overload might fail if you are using it to test high level bits that need to deserialize the response. /// - public InMemoryTransportClient() => _statusCode = 200; + public InMemoryRequestInvoker() => _statusCode = 200; - /// - public InMemoryTransportClient(byte[] responseBody, int statusCode = 200, Exception exception = null, string contentType = RequestData.DefaultMimeType, Dictionary> headers = null) + /// + public InMemoryRequestInvoker(byte[] responseBody, int statusCode = 200, Exception exception = null, string contentType = RequestData.DefaultMimeType, Dictionary> headers = null) { _responseBody = responseBody; _statusCode = statusCode; @@ -40,23 +40,27 @@ public InMemoryTransportClient(byte[] responseBody, int statusCode = 200, Except _headers = headers; } - /// > - public override TResponse Request(RequestData requestData) => - ReturnConnectionStatus(requestData); + void IDisposable.Dispose() { } - /// > - public override Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) => - ReturnConnectionStatusAsync(requestData, cancellationToken); + /// > + public TResponse Request(RequestData requestData) + where TResponse : TransportResponse, new() => + BuildResponse(requestData); + + /// > + public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) + where TResponse : TransportResponse, new() => + BuildResponseAsync(requestData, cancellationToken); /// - /// Allow subclasses to provide their own implementations for while reusing the more complex logic + /// Allow subclasses to provide their own implementations for while reusing the more complex logic /// to create a response /// /// An instance of describing where and how to call out to /// The bytes intended to be used as return /// The status code that the responses should return /// - internal TResponse ReturnConnectionStatus(RequestData requestData, byte[] responseBody = null, int? statusCode = null, + public TResponse BuildResponse(RequestData requestData, byte[] responseBody = null, int? statusCode = null, string contentType = null) where TResponse : TransportResponse, new() { @@ -82,8 +86,8 @@ internal TResponse ReturnConnectionStatus(RequestData requestData, by return requestData.ConnectionSettings.ProductRegistration.ResponseBuilder.ToResponse(requestData, _exception, sc, _headers, s, contentType ?? _contentType ?? RequestData.DefaultMimeType, body?.Length ?? 0, null, null); } - /// > - internal async Task ReturnConnectionStatusAsync(RequestData requestData, CancellationToken cancellationToken, + /// > + public async Task BuildResponseAsync(RequestData requestData, CancellationToken cancellationToken, byte[] responseBody = null, int? statusCode = null, string contentType = null) where TResponse : TransportResponse, new() { @@ -110,4 +114,5 @@ internal async Task ReturnConnectionStatusAsync(RequestDat .ToResponseAsync(requestData, _exception, sc, _headers, s, contentType ?? _contentType, body?.Length ?? 0, null, null, cancellationToken) .ConfigureAwait(false); } + } diff --git a/src/Elastic.Transport/Configuration/ITransportConfiguration.cs b/src/Elastic.Transport/Configuration/ITransportConfiguration.cs index 46f9881..207d810 100644 --- a/src/Elastic.Transport/Configuration/ITransportConfiguration.cs +++ b/src/Elastic.Transport/Configuration/ITransportConfiguration.cs @@ -14,8 +14,8 @@ namespace Elastic.Transport; /// -/// All the transport configuration that you as the user can use to steer the behavior of the and all the components such -/// as and . +/// All the transport configuration that you as the user can use to steer the behavior of the and all the components such +/// as and . /// public interface ITransportConfiguration : IDisposable { @@ -32,18 +32,18 @@ public interface ITransportConfiguration : IDisposable X509CertificateCollection ClientCertificates { get; } /// The connection abstraction behind which all actual IO happens - TransportClient Connection { get; } + IRequestInvoker Connection { get; } /// /// Limits the number of concurrent connections that can be opened to an endpoint. Defaults to 80 (see /// ). /// /// For Desktop CLR, this setting applies to the DefaultConnectionLimit property on the ServicePointManager object when creating - /// ServicePoint objects, affecting the default implementation. + /// ServicePoint objects, affecting the default implementation. /// /// /// For Core CLR, this setting applies to the MaxConnectionsPerServer property on the HttpClientHandler instances used by the HttpClient - /// inside the default implementation + /// inside the default implementation /// /// int ConnectionLimit { get; } @@ -296,7 +296,7 @@ public interface ITransportConfiguration : IDisposable MetaHeaderProvider MetaHeaderProvider { get; } /// - /// Disables the meta header which is included on all requests by default. This header contains lightweight information + /// Disables the meta header which is included on all requests by default. This header contains lightweight information /// about the client and runtime. /// bool DisableMetaHeader { get; } diff --git a/src/Elastic.Transport/Configuration/TransportConfiguration.cs b/src/Elastic.Transport/Configuration/TransportConfiguration.cs index af119a6..41b960c 100644 --- a/src/Elastic.Transport/Configuration/TransportConfiguration.cs +++ b/src/Elastic.Transport/Configuration/TransportConfiguration.cs @@ -22,7 +22,7 @@ namespace Elastic.Transport; /// -/// Allows you to control how behaves and where/how it connects to Elastic Stack products +/// Allows you to control how behaves and where/how it connects to Elastic Stack products /// public class TransportConfiguration : TransportConfigurationBase { @@ -99,12 +99,12 @@ public TransportConfiguration(string cloudId, Base64ApiKey credentials, ProductR /// /// - /// + /// /// /// public TransportConfiguration( NodePool nodePool, - TransportClient connection = null, + IRequestInvoker connection = null, Serializer serializer = null, ProductRegistration productRegistration = null) : base(nodePool, connection, serializer, productRegistration) { } @@ -117,7 +117,7 @@ public TransportConfiguration( public abstract class TransportConfigurationBase : ITransportConfiguration where T : TransportConfigurationBase { - private readonly TransportClient _transportClient; + private readonly IRequestInvoker _requestInvoker; private readonly NodePool _nodePool; private readonly ProductRegistration _productRegistration; private readonly NameValueCollection _headers = new NameValueCollection(); @@ -170,13 +170,13 @@ public abstract class TransportConfigurationBase : ITransportConfiguration /// /// /// - /// + /// /// /// - protected TransportConfigurationBase(NodePool nodePool, TransportClient transportClient, Serializer requestResponseSerializer, ProductRegistration productRegistration) + protected TransportConfigurationBase(NodePool nodePool, IRequestInvoker requestInvoker, Serializer requestResponseSerializer, ProductRegistration productRegistration) { _nodePool = nodePool; - _transportClient = transportClient ?? new HttpTransportClient(); + _requestInvoker = requestInvoker ?? new HttpRequestInvoker(); _productRegistration = productRegistration ?? DefaultProductRegistration.Default; UseThisRequestResponseSerializer = requestResponseSerializer ?? new LowLevelRequestResponseSerializer(); @@ -215,7 +215,7 @@ protected TransportConfigurationBase(NodePool nodePool, TransportClient transpor AuthorizationHeader ITransportConfiguration.Authentication => _authenticationHeader; SemaphoreSlim ITransportConfiguration.BootstrapLock => _semaphore; X509CertificateCollection ITransportConfiguration.ClientCertificates => _clientCertificates; - TransportClient ITransportConfiguration.Connection => _transportClient; + IRequestInvoker ITransportConfiguration.Connection => _requestInvoker; ProductRegistration ITransportConfiguration.ProductRegistration => _productRegistration; int ITransportConfiguration.ConnectionLimit => _transportClientLimit; NodePool ITransportConfiguration.NodePool => _nodePool; @@ -475,7 +475,7 @@ public T SkipDeserializationForStatusCodes(params int[] statusCodes) => protected virtual void DisposeManagedResources() { _nodePool?.Dispose(); - _transportClient?.Dispose(); + _requestInvoker?.Dispose(); _semaphore?.Dispose(); } diff --git a/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs b/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs index aacbba6..3303131 100644 --- a/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs +++ b/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs @@ -45,12 +45,12 @@ private interface IDiagnosticsKeys /// /// Provides access to the string event names related to the default - /// implementation. + /// implementation. /// public class HttpConnectionDiagnosticKeys : IDiagnosticsKeys { /// - public string SourceName { get; } = typeof(HttpTransportClient).FullName; + public string SourceName { get; } = typeof(HttpRequestInvoker).FullName; /// Start and stop event initiating the request and sending and receiving the headers public string SendAndReceiveHeaders { get; } = nameof(SendAndReceiveHeaders); diff --git a/src/Elastic.Transport/Diagnostics/HttpConnectionDiagnosticObserver.cs b/src/Elastic.Transport/Diagnostics/HttpConnectionDiagnosticObserver.cs index 9c82f4c..e12c1b5 100644 --- a/src/Elastic.Transport/Diagnostics/HttpConnectionDiagnosticObserver.cs +++ b/src/Elastic.Transport/Diagnostics/HttpConnectionDiagnosticObserver.cs @@ -7,7 +7,7 @@ namespace Elastic.Transport.Diagnostics; -/// Provides a typed listener to the events that emits +/// Provides a typed listener to the events that emits internal sealed class HttpConnectionDiagnosticObserver : TypedDiagnosticObserver { /// > diff --git a/src/Elastic.Transport/DefaultHttpTransport.cs b/src/Elastic.Transport/DistributedTransport.cs similarity index 90% rename from src/Elastic.Transport/DefaultHttpTransport.cs rename to src/Elastic.Transport/DistributedTransport.cs index 440aa52..cffa87b 100644 --- a/src/Elastic.Transport/DefaultHttpTransport.cs +++ b/src/Elastic.Transport/DistributedTransport.cs @@ -19,8 +19,8 @@ namespace Elastic.Transport; -/// -public sealed class DefaultHttpTransport : DefaultHttpTransport +/// +public sealed class DistributedTransport : DistributedTransport { /// /// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on @@ -28,7 +28,7 @@ public sealed class DefaultHttpTransport : DefaultHttpTransport /// The connection settings to use for this transport - public DefaultHttpTransport(TransportConfiguration configurationValues) : base(configurationValues) + public DistributedTransport(TransportConfiguration configurationValues) : base(configurationValues) { } @@ -40,7 +40,7 @@ public DefaultHttpTransport(TransportConfiguration configurationValues) : base(c /// The connection settings to use for this transport /// The date time proved to use, safe to pass null to use the default /// The memory stream provider to use, safe to pass null to use the default - public DefaultHttpTransport(TransportConfiguration configurationValues, + public DistributedTransport(TransportConfiguration configurationValues, DateTimeProvider dateTimeProvider = null, MemoryStreamFactory memoryStreamFactory = null ) : base(configurationValues, null, dateTimeProvider, memoryStreamFactory) @@ -56,7 +56,7 @@ public DefaultHttpTransport(TransportConfiguration configurationValues, /// In charge of create a new pipeline, safe to pass null to use the default /// The date time proved to use, safe to pass null to use the default /// The memory stream provider to use, safe to pass null to use the default - internal DefaultHttpTransport(TransportConfiguration configurationValues, + internal DistributedTransport(TransportConfiguration configurationValues, RequestPipelineFactory pipelineProvider = null, DateTimeProvider dateTimeProvider = null, MemoryStreamFactory memoryStreamFactory = null ) @@ -65,11 +65,11 @@ internal DefaultHttpTransport(TransportConfiguration configurationValues, } } -/// -public class DefaultHttpTransport : HttpTransport +/// +public class DistributedTransport : ITransport where TConfiguration : class, ITransportConfiguration { - private static readonly string TransportVersion = typeof(DefaultHttpTransport).Assembly + private static readonly string TransportVersion = typeof(DistributedTransport).Assembly .GetCustomAttribute() .InformationalVersion; @@ -81,7 +81,7 @@ public class DefaultHttpTransport : HttpTransport /// The connection settings to use for this transport - public DefaultHttpTransport(TConfiguration configurationValues) : this(configurationValues, null, null, null) + public DistributedTransport(TConfiguration configurationValues) : this(configurationValues, null, null, null) { } @@ -93,7 +93,7 @@ public DefaultHttpTransport(TConfiguration configurationValues) : this(configura /// The connection settings to use for this transport /// The date time proved to use, safe to pass null to use the default /// The memory stream provider to use, safe to pass null to use the default - public DefaultHttpTransport( + public DistributedTransport( TConfiguration configurationValues, DateTimeProvider dateTimeProvider = null, MemoryStreamFactory memoryStreamFactory = null) @@ -108,7 +108,7 @@ public DefaultHttpTransport( /// In charge of create a new pipeline, safe to pass null to use the default /// The date time proved to use, safe to pass null to use the default /// The memory stream provider to use, safe to pass null to use the default - public DefaultHttpTransport( + public DistributedTransport( TConfiguration configurationValues, RequestPipelineFactory pipelineProvider = null, DateTimeProvider dateTimeProvider = null, @@ -122,7 +122,7 @@ public DefaultHttpTransport( .RequestResponseSerializer)); _productRegistration = configurationValues.ProductRegistration; - Settings = configurationValues; + Configuration = configurationValues; PipelineProvider = pipelineProvider ?? new DefaultRequestPipelineFactory(); DateTimeProvider = dateTimeProvider ?? DefaultDateTimeProvider.Default; MemoryStreamFactory = memoryStreamFactory ?? configurationValues.MemoryStreamFactory; @@ -135,7 +135,7 @@ public DefaultHttpTransport( /// /// /// - public override TConfiguration Settings { get; } + public TConfiguration Configuration { get; } /// public override TResponse Request( @@ -155,7 +155,7 @@ public override Task RequestAsync( in OpenTelemetryData openTelemetryData, CancellationToken cancellationToken = default) => RequestCoreAsync(true, method, path, data, requestParameters, openTelemetryData, cancellationToken).AsTask(); - + private async ValueTask RequestCoreAsync( bool isAsync, HttpMethod method, @@ -174,29 +174,29 @@ private async ValueTask RequestCoreAsync( try { using var pipeline = - PipelineProvider.Create(Settings, DateTimeProvider, MemoryStreamFactory, requestParameters); + PipelineProvider.Create(Configuration, DateTimeProvider, MemoryStreamFactory, requestParameters); if (isAsync) - await pipeline.FirstPoolUsageAsync(Settings.BootstrapLock, cancellationToken).ConfigureAwait(false); + await pipeline.FirstPoolUsageAsync(Configuration.BootstrapLock, cancellationToken).ConfigureAwait(false); else - pipeline.FirstPoolUsage(Settings.BootstrapLock); + pipeline.FirstPoolUsage(Configuration.BootstrapLock); - var requestData = new RequestData(method, path, data, Settings, requestParameters, MemoryStreamFactory, openTelemetryData); - Settings.OnRequestDataCreated?.Invoke(requestData); + var requestData = new RequestData(method, path, data, Configuration, requestParameters, MemoryStreamFactory, openTelemetryData); + Configuration.OnRequestDataCreated?.Invoke(requestData); TResponse response = null; if (OpenTelemetry.ElasticTransportActivitySource.HasListeners() && activity.IsAllDataRequested) { if (activity.IsAllDataRequested) - OpenTelemetry.SetCommonAttributes(activity, openTelemetryData, Settings); + OpenTelemetry.SetCommonAttributes(activity, openTelemetryData, Configuration); - if (Settings.Authentication is BasicAuthentication basicAuthentication) + if (Configuration.Authentication is BasicAuthentication basicAuthentication) activity?.SetTag(SemanticConventions.DbUser, basicAuthentication.Username); - activity?.SetTag(OpenTelemetryAttributes.ElasticTransportProductName, Settings.ProductRegistration.Name); - activity?.SetTag(OpenTelemetryAttributes.ElasticTransportProductVersion, Settings.ProductRegistration.ProductAssemblyVersion); + activity?.SetTag(OpenTelemetryAttributes.ElasticTransportProductName, Configuration.ProductRegistration.Name); + activity?.SetTag(OpenTelemetryAttributes.ElasticTransportProductVersion, Configuration.ProductRegistration.ProductAssemblyVersion); activity?.SetTag(OpenTelemetryAttributes.ElasticTransportVersion, TransportVersion); - activity?.SetTag(SemanticConventions.UserAgentOriginal, Settings.UserAgent.ToString()); + activity?.SetTag(SemanticConventions.UserAgentOriginal, Configuration.UserAgent.ToString()); if (openTelemetryData.SpanAttributes is not null) { @@ -406,7 +406,7 @@ private void HandleTransportException(RequestData data, Exception clientExceptio #endif } - Settings.OnRequestCompleted?.Invoke(response.ApiCallDetails); + Configuration.OnRequestCompleted?.Invoke(response.ApiCallDetails); if (data != null && clientException != null && data.ThrowExceptions) throw clientException; } diff --git a/src/Elastic.Transport/HttpTransport.cs b/src/Elastic.Transport/ITransport.cs similarity index 94% rename from src/Elastic.Transport/HttpTransport.cs rename to src/Elastic.Transport/ITransport.cs index 6a4a155..3da33d1 100644 --- a/src/Elastic.Transport/HttpTransport.cs +++ b/src/Elastic.Transport/ITransport.cs @@ -9,9 +9,9 @@ namespace Elastic.Transport; /// -/// Represents a transport you can call requests, it is recommended to implement +/// Represents a transport you can call requests, it is recommended to reference /// -public abstract class HttpTransport +public interface ITransport { /// /// Orchestrate a request synchronously into a using the workflow defined in the . @@ -49,7 +49,7 @@ public TResponse Request( /// /// Data to be used to control the OpenTelemetry instrumentation. - public abstract TResponse Request( + public TResponse Request( HttpMethod method, string path, PostData? postData, @@ -97,7 +97,7 @@ public Task RequestAsync( /// /// Data to be used to control the OpenTelemetry instrumentation. - public abstract Task RequestAsync( + public Task RequestAsync( HttpMethod method, string path, PostData? postData, @@ -112,11 +112,11 @@ public abstract Task RequestAsync( /// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on /// different nodes /// -public abstract class HttpTransport : HttpTransport +public interface ITransport : ITransport where TConfiguration : class, ITransportConfiguration { /// /// The in use by this transport instance /// - public abstract TConfiguration Settings { get; } + public TConfiguration Configuration { get; } } diff --git a/src/Elastic.Transport/ITransportExtensions.cs b/src/Elastic.Transport/ITransportExtensions.cs new file mode 100644 index 0000000..16e9910 --- /dev/null +++ b/src/Elastic.Transport/ITransportExtensions.cs @@ -0,0 +1,83 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Threading; +using System.Threading.Tasks; + +namespace Elastic.Transport; + +/// +/// Extends with some convenience methods to make it easier to perform specific requests +/// +public static class ITransportExtensions +{ + /// Perform a GET request + public static TResponse Get(this ITransport requestHandler, string path, + RequestParameters parameters = null) + where TResponse : TransportResponse, new() => + requestHandler.Request(HttpMethod.GET, path, null, parameters); + + /// Perform a GET request + public static Task GetAsync(this ITransport requestHandler, string path, + RequestParameters parameters = null, CancellationToken cancellationToken = default) + where TResponse : TransportResponse, new() => + requestHandler.RequestAsync(HttpMethod.GET, path, null, parameters, cancellationToken); + + /// Perform a HEAD request + public static TResponse Head(this ITransport requestHandler, string path, + RequestParameters parameters = null) + where TResponse : TransportResponse, new() => + requestHandler.Request(HttpMethod.HEAD, path, null, parameters); + + /// Perform a HEAD request + public static Task HeadAsync(this ITransport requestHandler, string path, + RequestParameters parameters = null, CancellationToken cancellationToken = default) + where TResponse : TransportResponse, new() => + requestHandler.RequestAsync(HttpMethod.HEAD, path, null, parameters, cancellationToken); + + /// Perform a HEAD request + public static VoidResponse Head(this ITransport requestHandler, string path, RequestParameters parameters = null) => + requestHandler.Head(path, parameters); + + /// Perform a HEAD request + public static Task HeadAsync(this ITransport requestHandler, string path, + RequestParameters parameters = null, CancellationToken cancellationToken = default) => + requestHandler.HeadAsync(path, parameters, cancellationToken); + + /// Perform a POST request + public static TResponse Post(this ITransport requestHandler, string path, PostData data, + RequestParameters parameters = null) + where TResponse : TransportResponse, new() => + requestHandler.Request(HttpMethod.POST, path, data, parameters); + + /// Perform a POST request + public static Task PostAsync(this ITransport requestHandler, string path, PostData data, + RequestParameters parameters = null, CancellationToken cancellationToken = default) + where TResponse : TransportResponse, new() => + requestHandler.RequestAsync(HttpMethod.POST, path, data, parameters, cancellationToken); + + /// Perform a PUT request + public static TResponse Put(this ITransport requestHandler, string path, PostData data, + RequestParameters parameters = null) + where TResponse : TransportResponse, new() => + requestHandler.Request(HttpMethod.PUT, path, data, parameters); + + /// Perform a PUT request + public static Task PutAsync(this ITransport requestHandler, string path, PostData data, + RequestParameters parameters = null, CancellationToken cancellationToken = default) + where TResponse : TransportResponse, new() => + requestHandler.RequestAsync(HttpMethod.PUT, path, data, parameters, cancellationToken); + + /// Perform a DELETE request + public static TResponse Delete(this ITransport requestHandler, string path, PostData data = null, + RequestParameters parameters = null) + where TResponse : TransportResponse, new() => + requestHandler.Request(HttpMethod.DELETE, path, data, parameters); + + /// Perform a DELETE request + public static Task DeleteAsync(this ITransport requestHandler, string path, + PostData data = null, RequestParameters parameters = null, CancellationToken cancellationToken = default) + where TResponse : TransportResponse, new() => + requestHandler.RequestAsync(HttpMethod.DELETE, path, data, parameters, cancellationToken); +} diff --git a/src/Elastic.Transport/Products/DefaultProductRegistration.cs b/src/Elastic.Transport/Products/DefaultProductRegistration.cs index e481386..682f79c 100644 --- a/src/Elastic.Transport/Products/DefaultProductRegistration.cs +++ b/src/Elastic.Transport/Products/DefaultProductRegistration.cs @@ -25,7 +25,7 @@ public sealed class DefaultProductRegistration : ProductRegistration /// public DefaultProductRegistration() { - _metaHeaderProvider = new DefaultMetaHeaderProvider(typeof(HttpTransport), ServiceIdentifier); + _metaHeaderProvider = new DefaultMetaHeaderProvider(typeof(ITransport), ServiceIdentifier); ProductAssemblyVersion = typeof(ProductRegistration).Assembly .GetCustomAttribute() @@ -84,11 +84,11 @@ public override RequestData CreateSniffRequestData(Node node, IRequestConfigurat throw new NotImplementedException(); /// - public override Task>> SniffAsync(TransportClient transportClient, bool forceSsl, RequestData requestData, CancellationToken cancellationToken) => + public override Task>> SniffAsync(IRequestInvoker requestInvoker, bool forceSsl, RequestData requestData, CancellationToken cancellationToken) => throw new NotImplementedException(); /// - public override Tuple> Sniff(TransportClient connection, bool forceSsl, RequestData requestData) => + public override Tuple> Sniff(IRequestInvoker connection, bool forceSsl, RequestData requestData) => throw new NotImplementedException(); /// @@ -96,11 +96,11 @@ public override RequestData CreatePingRequestData(Node node, RequestConfiguratio throw new NotImplementedException(); /// - public override Task PingAsync(TransportClient connection, RequestData pingData, CancellationToken cancellationToken) => + public override Task PingAsync(IRequestInvoker connection, RequestData pingData, CancellationToken cancellationToken) => throw new NotImplementedException(); /// - public override TransportResponse Ping(TransportClient connection, RequestData pingData) => + public override TransportResponse Ping(IRequestInvoker connection, RequestData pingData) => throw new NotImplementedException(); /// diff --git a/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs b/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs index d2a451b..cacd4e3 100644 --- a/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs +++ b/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs @@ -17,7 +17,7 @@ namespace Elastic.Transport.Products.Elasticsearch; /// /// An implementation of that fills in the bespoke implementations /// for Elasticsearch so that knows how to ping and sniff if we setup -/// to talk to Elasticsearch +/// to talk to Elasticsearch /// public class ElasticsearchProductRegistration : ProductRegistration { @@ -136,10 +136,10 @@ MemoryStreamFactory memoryStreamFactory } /// - public override async Task>> SniffAsync(TransportClient transportClient, + public override async Task>> SniffAsync(IRequestInvoker requestInvoker, bool forceSsl, RequestData requestData, CancellationToken cancellationToken) { - var response = await transportClient.RequestAsync(requestData, cancellationToken) + var response = await requestInvoker.RequestAsync(requestData, cancellationToken) .ConfigureAwait(false); var nodes = response.ToNodes(forceSsl); return Tuple.Create>(response, @@ -147,10 +147,10 @@ public override async Task>> } /// - public override Tuple> Sniff(TransportClient transportClient, bool forceSsl, + public override Tuple> Sniff(IRequestInvoker requestInvoker, bool forceSsl, RequestData requestData) { - var response = transportClient.Request(requestData); + var response = requestInvoker.Request(requestData); var nodes = response.ToNodes(forceSsl); return Tuple.Create>(response, new ReadOnlyCollection(nodes.ToArray())); @@ -176,15 +176,15 @@ MemoryStreamFactory memoryStreamFactory } /// - public override async Task PingAsync(TransportClient transportClient, RequestData pingData, + public override async Task PingAsync(IRequestInvoker requestInvoker, RequestData pingData, CancellationToken cancellationToken) { - var response = await transportClient.RequestAsync(pingData, cancellationToken).ConfigureAwait(false); + var response = await requestInvoker.RequestAsync(pingData, cancellationToken).ConfigureAwait(false); return response; } /// - public override TransportResponse Ping(TransportClient connection, RequestData pingData) + public override TransportResponse Ping(IRequestInvoker connection, RequestData pingData) { var response = connection.Request(pingData); return response; diff --git a/src/Elastic.Transport/Products/ProductRegistration.cs b/src/Elastic.Transport/Products/ProductRegistration.cs index 32c511b..1109e7a 100644 --- a/src/Elastic.Transport/Products/ProductRegistration.cs +++ b/src/Elastic.Transport/Products/ProductRegistration.cs @@ -13,11 +13,11 @@ namespace Elastic.Transport.Products; /// When a request interfaces with a product, some parts are /// bespoke for each product. This interface defines the contract products will have to implement in order to fill /// in these bespoke parts. -/// The expectation is that unless you instantiate +/// The expectation is that unless you instantiate /// directly clients that utilize transport will fill in this dependency /// /// -/// If you do want to use a bare-bones you can use +/// If you do want to use a bare-bones you can use /// /// /// @@ -29,7 +29,7 @@ public abstract class ProductRegistration public abstract string DefaultMimeType { get; } /// - /// The name of the current product utilizing + /// The name of the current product utilizing /// This name makes its way into the transport diagnostics sources and the default user agent string /// public abstract string Name { get; } @@ -40,12 +40,12 @@ public abstract class ProductRegistration public abstract string? ServiceIdentifier { get; } /// - /// Whether the product will call out to supports ping endpoints + /// Whether the product will call out to supports ping endpoints /// public abstract bool SupportsPing { get; } /// - /// Whether the product will call out to supports sniff endpoints that return + /// Whether the product will call out to supports sniff endpoints that return /// information about available nodes /// public abstract bool SupportsSniff { get; } @@ -62,16 +62,16 @@ public abstract class ProductRegistration public abstract RequestData CreatePingRequestData(Node node, RequestConfiguration requestConfiguration, ITransportConfiguration global, MemoryStreamFactory memoryStreamFactory); /// - /// Provide an implementation that performs the ping directly using and the + /// Provide an implementation that performs the ping directly using and the /// return by /// - public abstract Task PingAsync(TransportClient connection, RequestData pingData, CancellationToken cancellationToken); + public abstract Task PingAsync(IRequestInvoker connection, RequestData pingData, CancellationToken cancellationToken); /// - /// Provide an implementation that performs the ping directly using and the + /// Provide an implementation that performs the ping directly using and the /// return by /// - public abstract TransportResponse Ping(TransportClient connection, RequestData pingData); + public abstract TransportResponse Ping(IRequestInvoker connection, RequestData pingData); /// /// Create an instance of that describes where and how to sniff the cluster using @@ -81,16 +81,16 @@ public abstract RequestData CreateSniffRequestData(Node node, IRequestConfigurat MemoryStreamFactory memoryStreamFactory); /// - /// Provide an implementation that performs the sniff directly using and the + /// Provide an implementation that performs the sniff directly using and the /// return by /// - public abstract Task>> SniffAsync(TransportClient connection, bool forceSsl, RequestData requestData, CancellationToken cancellationToken); + public abstract Task>> SniffAsync(IRequestInvoker connection, bool forceSsl, RequestData requestData, CancellationToken cancellationToken); /// - /// Provide an implementation that performs the sniff directly using and the + /// Provide an implementation that performs the sniff directly using and the /// return by /// - public abstract Tuple> Sniff(TransportClient connection, bool forceSsl, RequestData requestData); + public abstract Tuple> Sniff(IRequestInvoker connection, bool forceSsl, RequestData requestData); /// Allows certain nodes to be queried first to obtain sniffing information public abstract int SniffOrder(Node node); diff --git a/src/Elastic.Transport/Requests/MetaData/MetaDataHeader.cs b/src/Elastic.Transport/Requests/MetaData/MetaDataHeader.cs index d1d3e6b..bfc3efe 100644 --- a/src/Elastic.Transport/Requests/MetaData/MetaDataHeader.cs +++ b/src/Elastic.Transport/Requests/MetaData/MetaDataHeader.cs @@ -24,7 +24,7 @@ public sealed class MetaDataHeader public MetaDataHeader(VersionInfo version, string serviceIdentifier, bool isAsync) { if (serviceIdentifier != "et") - TransportVersion = ReflectionVersionInfo.Create().ToString(); + TransportVersion = ReflectionVersionInfo.Create().ToString(); ClientVersion = version.ToString(); RuntimeVersion = new RuntimeVersionInfo().ToString(); diff --git a/src/Elastic.Transport/Responses/TransportResponse.cs b/src/Elastic.Transport/Responses/TransportResponse.cs index 3f27ecc..e74cece 100644 --- a/src/Elastic.Transport/Responses/TransportResponse.cs +++ b/src/Elastic.Transport/Responses/TransportResponse.cs @@ -19,7 +19,7 @@ public abstract class TransportResponse : TransportResponse } /// -/// A response as returned by including details about the request/response life cycle. +/// A response as returned by including details about the request/response life cycle. /// public abstract class TransportResponse { diff --git a/src/Elastic.Transport/TransportExtensions.cs b/src/Elastic.Transport/TransportExtensions.cs deleted file mode 100644 index 3c14e21..0000000 --- a/src/Elastic.Transport/TransportExtensions.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using System.Threading; -using System.Threading.Tasks; - -namespace Elastic.Transport; - -/// -/// Extends with some convenience methods to make it easier to perform specific requests -/// -public static class TransportExtensions -{ - /// Perform a GET request - public static TResponse Get(this HttpTransport transport, string path, - RequestParameters parameters = null) - where TResponse : TransportResponse, new() => - transport.Request(HttpMethod.GET, path, null, parameters); - - /// Perform a GET request - public static Task GetAsync(this HttpTransport transport, string path, - RequestParameters parameters = null, CancellationToken cancellationToken = default) - where TResponse : TransportResponse, new() => - transport.RequestAsync(HttpMethod.GET, path, null, parameters, cancellationToken); - - /// Perform a HEAD request - public static TResponse Head(this HttpTransport transport, string path, - RequestParameters parameters = null) - where TResponse : TransportResponse, new() => - transport.Request(HttpMethod.HEAD, path, null, parameters); - - /// Perform a HEAD request - public static Task HeadAsync(this HttpTransport transport, string path, - RequestParameters parameters = null, CancellationToken cancellationToken = default) - where TResponse : TransportResponse, new() => - transport.RequestAsync(HttpMethod.HEAD, path, null, parameters, cancellationToken); - - /// Perform a HEAD request - public static VoidResponse Head(this HttpTransport transport, string path, RequestParameters parameters = null) => - transport.Head(path, parameters); - - /// Perform a HEAD request - public static Task HeadAsync(this HttpTransport transport, string path, - RequestParameters parameters = null, CancellationToken cancellationToken = default) => - transport.HeadAsync(path, parameters, cancellationToken); - - /// Perform a POST request - public static TResponse Post(this HttpTransport transport, string path, PostData data, - RequestParameters parameters = null) - where TResponse : TransportResponse, new() => - transport.Request(HttpMethod.POST, path, data, parameters); - - /// Perform a POST request - public static Task PostAsync(this HttpTransport transport, string path, PostData data, - RequestParameters parameters = null, CancellationToken cancellationToken = default) - where TResponse : TransportResponse, new() => - transport.RequestAsync(HttpMethod.POST, path, data, parameters, cancellationToken); - - /// Perform a PUT request - public static TResponse Put(this HttpTransport transport, string path, PostData data, - RequestParameters parameters = null) - where TResponse : TransportResponse, new() => - transport.Request(HttpMethod.PUT, path, data, parameters); - - /// Perform a PUT request - public static Task PutAsync(this HttpTransport transport, string path, PostData data, - RequestParameters parameters = null, CancellationToken cancellationToken = default) - where TResponse : TransportResponse, new() => - transport.RequestAsync(HttpMethod.PUT, path, data, parameters, cancellationToken); - - /// Perform a DELETE request - public static TResponse Delete(this HttpTransport transport, string path, PostData data = null, - RequestParameters parameters = null) - where TResponse : TransportResponse, new() => - transport.Request(HttpMethod.DELETE, path, data, parameters); - - /// Perform a DELETE request - public static Task DeleteAsync(this HttpTransport transport, string path, - PostData data = null, RequestParameters parameters = null, CancellationToken cancellationToken = default) - where TResponse : TransportResponse, new() => - transport.RequestAsync(HttpMethod.DELETE, path, data, parameters, cancellationToken); -} diff --git a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs index 529d09e..9c0ee51 100644 --- a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs +++ b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs @@ -24,7 +24,7 @@ public DefaultCluster() : this(new XunitClusterConfiguration(Version) { Starting public DefaultCluster(XunitClusterConfiguration xunitClusterConfiguration) : base(xunitClusterConfiguration) { } - public DefaultHttpTransport CreateClient(ITestOutputHelper output) => + public DistributedTransport CreateClient(ITestOutputHelper output) => this.GetOrAddClient(cluster => { var nodes = NodesUris(); @@ -50,7 +50,7 @@ public DefaultHttpTransport CreateClient(ITestOutputHelper output) => if (ClusterConfiguration.Features.HasFlag(ClusterFeatures.SSL)) settings = settings.ServerCertificateValidationCallback(CertificateValidations.AllowAll); - return new DefaultHttpTransport(settings); + return new DistributedTransport(settings); }); } diff --git a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultClusterTests.cs b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultClusterTests.cs index 8aaf145..42c42ba 100644 --- a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultClusterTests.cs +++ b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultClusterTests.cs @@ -17,7 +17,7 @@ public DefaultClusterTests(DefaultCluster cluster, ITestOutputHelper output) : b [Fact] public async Task AsyncRequestDoesNotThrow() { - var response = await Transport.RequestAsync(GET, "/"); + var response = await RequestHandler.RequestAsync(GET, "/"); response.ApiCallDetails.Should().NotBeNull(); response.ApiCallDetails.HasSuccessfulStatusCode.Should().BeTrue(); } @@ -25,7 +25,7 @@ public async Task AsyncRequestDoesNotThrow() [Fact] public void SyncRequestDoesNotThrow() { - var response = Transport.Request(GET, "/"); + var response = RequestHandler.Request(GET, "/"); response.ApiCallDetails.Should().NotBeNull(); response.ApiCallDetails.HasSuccessfulStatusCode.Should().BeTrue(); } diff --git a/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs b/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs index e416633..7ef3295 100644 --- a/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs +++ b/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs @@ -16,12 +16,12 @@ public abstract class IntegrationTestBase : IClusterFixture where TCluster : DefaultCluster, new() { protected TCluster Cluster { get; } - protected DefaultHttpTransport Transport { get; } + protected DistributedTransport RequestHandler { get; } protected IntegrationTestBase(TCluster cluster, ITestOutputHelper output) { Cluster = cluster; - Transport = cluster.CreateClient(output); + RequestHandler = cluster.CreateClient(output); } } diff --git a/tests/Elastic.Elasticsearch.IntegrationTests/SecurityClusterTests.cs b/tests/Elastic.Elasticsearch.IntegrationTests/SecurityClusterTests.cs index 3a27b4e..a6e04e4 100644 --- a/tests/Elastic.Elasticsearch.IntegrationTests/SecurityClusterTests.cs +++ b/tests/Elastic.Elasticsearch.IntegrationTests/SecurityClusterTests.cs @@ -17,7 +17,7 @@ public SecurityClusterTests(SecurityCluster cluster, ITestOutputHelper output) : [Fact] public async Task AsyncRequestDoesNotThrow() { - var response = await Transport.RequestAsync(GET, "/"); + var response = await RequestHandler.RequestAsync(GET, "/"); response.ApiCallDetails.Should().NotBeNull(); response.ApiCallDetails.HasSuccessfulStatusCode.Should().BeTrue(); } @@ -25,7 +25,7 @@ public async Task AsyncRequestDoesNotThrow() [Fact] public void SyncRequestDoesNotThrow() { - var response = Transport.Request(GET, "/"); + var response = RequestHandler.Request(GET, "/"); response.ApiCallDetails.Should().NotBeNull(); response.ApiCallDetails.HasSuccessfulStatusCode.Should().BeTrue(); } @@ -33,7 +33,7 @@ public void SyncRequestDoesNotThrow() [Fact] public void SyncRequestDoesNotThrowOnBadAuth() { - var response = Transport.Request(GET, "/", null, new DefaultRequestParameters + var response = RequestHandler.Request(GET, "/", null, new DefaultRequestParameters { RequestConfiguration = new RequestConfiguration { diff --git a/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs b/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs index d6671bd..54ca749 100644 --- a/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs @@ -36,7 +36,7 @@ public async Task AddsExpectedVendorInformationForRestApiCompaitbility() var connectionPool = new SingleNodePool(Server.Uri); var config = new TransportConfiguration(connectionPool, connection, productRegistration: new ElasticsearchProductRegistration(typeof(Clients.Elasticsearch.ElasticsearchClient))); - var transport = new DefaultHttpTransport(config); + var transport = new DistributedTransport(config); var response = await transport.PostAsync("/metaheader", PostData.String("{}")); } diff --git a/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs b/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs index 5e5699e..66166eb 100644 --- a/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs @@ -30,7 +30,7 @@ public TransferEncodingChunkedTests(TransportTestServer instance) : base(instanc private static readonly PostData Body = PostData.String(BodyString); private const string Path = "/chunked"; - private HttpTransport Setup( + private ITransport Setup( TestableHttpConnection connection, Uri proxyAddress = null, bool? disableAutomaticProxyDetection = null, @@ -47,7 +47,7 @@ private HttpTransport Setup( //make sure we the requests in debugging proxy : TransportTestServer.RerouteToProxyIfNeeded(config); - return new DefaultHttpTransport(config); + return new DistributedTransport(config); } /// diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/AssemblyServerTestsBase.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/AssemblyServerTestsBase.cs index 3efa2a1..e3efa68 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/AssemblyServerTestsBase.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/AssemblyServerTestsBase.cs @@ -12,7 +12,7 @@ public class AssemblyServerTestsBase : IAssemblyFixture where protected TServer Server { get; } - protected HttpTransport Transport => Server.DefaultTransport; + protected ITransport RequestHandler => Server.DefaultRequestHandler; } public class AssemblyServerTestsBase : AssemblyServerTestsBase diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/ClassServerTestsBase.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/ClassServerTestsBase.cs index 7285160..b736b39 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/ClassServerTestsBase.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/ClassServerTestsBase.cs @@ -12,6 +12,6 @@ public class ClassServerTestsBase : IClassFixture where TServe protected TServer Server { get; } - protected HttpTransport Transport => Server.DefaultTransport; + protected ITransport RequestHandler => Server.DefaultRequestHandler; } } diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/ControllerIntegrationTests.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/ControllerIntegrationTests.cs index 22b37bf..de8b77c 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/ControllerIntegrationTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/ControllerIntegrationTests.cs @@ -26,7 +26,7 @@ public ControllerIntegrationTests(TransportTestServer instance) : base(instance) [Fact] public async Task CanCallIntoController() { - var response = await Transport.GetAsync("/dummy/20"); + var response = await RequestHandler.GetAsync("/dummy/20"); response.ApiCallDetails.HasSuccessfulStatusCode.Should().BeTrue("{0}", response.ApiCallDetails.DebugInformation); } } diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/EndpointIntegrationTests.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/EndpointIntegrationTests.cs index ce6859b..17ff5c6 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/EndpointIntegrationTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/Examples/EndpointIntegrationTests.cs @@ -24,7 +24,7 @@ public EndpointIntegrationTests(TransportTestServer instance) : ba [Fact] public async Task CanCallIntoEndpoint() { - var response = await Transport.GetAsync(DummyStartup.Endpoint); + var response = await RequestHandler.GetAsync(DummyStartup.Endpoint); response.ApiCallDetails.HasSuccessfulStatusCode.Should().BeTrue("{0}", response.ApiCallDetails.DebugInformation); } } diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs index b0bb063..d79d37d 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs @@ -9,39 +9,41 @@ namespace Elastic.Transport.IntegrationTests.Plumbing.Stubs { - public class TestableHttpConnection : HttpTransportClient + public class TestableHttpConnection : IRequestInvoker { private readonly Action _response; private TestableClientHandler _handler; public int CallCount { get; private set; } public HttpClientHandler LastHttpClientHandler => (HttpClientHandler)_handler.InnerHandler; + private readonly HttpRequestInvoker _requestInvoker; public TestableHttpConnection(Action response) => _response = response; - public TestableHttpConnection() { } + public TestableHttpConnection() => + _requestInvoker = new HttpRequestInvoker(((defaultHandler, data) => + { + _handler = new TestableClientHandler(defaultHandler(data), _response); + return _handler; + })); - public override TResponse Request(RequestData requestData) + public TResponse Request(RequestData requestData) + where TResponse : TransportResponse, new() { CallCount++; - return base.Request(requestData); + return _requestInvoker.Request(requestData); } - public override Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) + public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) + where TResponse : TransportResponse, new() { CallCount++; - return base.RequestAsync(requestData, cancellationToken); + return _requestInvoker.RequestAsync(requestData, cancellationToken); } - protected override HttpMessageHandler CreateHttpClientHandler(RequestData requestData) - { - _handler = new TestableClientHandler(base.CreateHttpClientHandler(requestData), _response); - return _handler; - } - - protected override void DisposeManagedResources() + public void Dispose() { _handler?.Dispose(); - base.DisposeManagedResources(); + _requestInvoker?.Dispose(); } } } diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/TransportTestServer.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/TransportTestServer.cs index 0b45362..382421b 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/TransportTestServer.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/TransportTestServer.cs @@ -21,7 +21,7 @@ public interface HttpTransportTestServer { Uri Uri { get; } - HttpTransport DefaultTransport { get; } + ITransport DefaultRequestHandler { get; } } public class TransportTestServer : TransportTestServer @@ -44,7 +44,7 @@ public class TransportTestServer : HttpTransportTestServer, IDisposabl { private readonly IWebHost _host; private Uri _uri; - private HttpTransport _defaultTransport; + private ITransport _defaultRequestHandler; public TransportTestServer() { @@ -69,10 +69,10 @@ public Uri Uri private set => _uri = value; } - public HttpTransport DefaultTransport + public ITransport DefaultRequestHandler { - get => _defaultTransport ?? throw new Exception($"{nameof(DefaultTransport)} is not available until {nameof(StartAsync)} is called"); - private set => _defaultTransport = value; + get => _defaultRequestHandler ?? throw new Exception($"{nameof(DefaultRequestHandler)} is not available until {nameof(StartAsync)} is called"); + private set => _defaultRequestHandler = value; } public async Task> StartAsync(CancellationToken token = default) @@ -81,11 +81,11 @@ public async Task> StartAsync(CancellationToken to var port = _host.GetServerPort(); var url = $"http://{TransportTestServer.LocalOrProxyHost}:{port}"; Uri = new Uri(url); - DefaultTransport = CreateTransport(c => new DefaultHttpTransport(c)); + DefaultRequestHandler = CreateTransport(c => new DistributedTransport(c)); return this; } - public HttpTransport CreateTransport(Func create) => + public ITransport CreateTransport(Func create) => create(TransportTestServer.RerouteToProxyIfNeeded(new TransportConfiguration(Uri))); public void Dispose() => _host?.Dispose(); diff --git a/tests/Elastic.Transport.Tests/CodeStandards/NamingConventions.doc.cs b/tests/Elastic.Transport.Tests/CodeStandards/NamingConventions.doc.cs index 6a145ad..505c952 100644 --- a/tests/Elastic.Transport.Tests/CodeStandards/NamingConventions.doc.cs +++ b/tests/Elastic.Transport.Tests/CodeStandards/NamingConventions.doc.cs @@ -24,7 +24,7 @@ [Fact] public void ClassNameContainsBaseShouldBeAbstract() { var exceptions = new Type[] { }; - var baseClassesNotAbstract = typeof(HttpTransport<>).Assembly.GetTypes() + var baseClassesNotAbstract = typeof(ITransport<>).Assembly.GetTypes() .Where(t => t.IsClass && !exceptions.Contains(t)) .Where(t => t.Name.Split('`')[0].EndsWith("Base")) .Where(t => !t.IsAbstract) @@ -36,7 +36,7 @@ [Fact] public void ClassNameContainsBaseShouldBeAbstract() private List Scan() { - var assembly = typeof(HttpTransport<>).Assembly; + var assembly = typeof(ITransport<>).Assembly; var exceptions = new List { diff --git a/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs b/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs index 0d5bc8c..1257ebf 100644 --- a/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs +++ b/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs @@ -10,9 +10,9 @@ public static class InMemoryConnectionFactory { public static TransportConfiguration Create() { - var connection = new InMemoryTransportClient(); + var invoker = new InMemoryRequestInvoker(); var pool = new SingleNodePool(new Uri("http://localhost:9200")); - var settings = new TransportConfiguration(pool, connection); + var settings = new TransportConfiguration(pool, transport); return settings; } } diff --git a/tests/Elastic.Transport.Tests/Test.cs b/tests/Elastic.Transport.Tests/Test.cs index 2e0d3be..43a9023 100644 --- a/tests/Elastic.Transport.Tests/Test.cs +++ b/tests/Elastic.Transport.Tests/Test.cs @@ -16,12 +16,12 @@ public class Test public void Usage() { var pool = new StaticNodePool(new[] {new Node(new Uri("http://localhost:9200"))}); - var connection = new HttpTransportClient(); + var connection = new HttpRequestInvoker(); var serializer = LowLevelRequestResponseSerializer.Instance; var product = ElasticsearchProductRegistration.Default; var settings = new TransportConfiguration(pool, connection, serializer, product); - var transport = new DefaultHttpTransport(settings); + var transport = new DistributedTransport(settings); var response = transport.Request(HttpMethod.GET, "/"); } @@ -29,7 +29,7 @@ public void Usage() public void MinimalUsage() { var settings = new TransportConfiguration(new Uri("http://localhost:9200")); - var transport = new DefaultHttpTransport(settings); + var transport = new DistributedTransport(settings); var response = transport.Get("/"); @@ -40,7 +40,7 @@ public void MinimalElasticsearch() { var uri = new Uri("http://localhost:9200"); var settings = new TransportConfiguration(uri, ElasticsearchProductRegistration.Default); - var transport = new DefaultHttpTransport(settings); + var transport = new DistributedTransport(settings); var response = transport.Get("/"); @@ -50,7 +50,7 @@ public void MinimalElasticsearch() public void MinimalUsageWithRequestParameters() { var settings = new TransportConfiguration(new Uri("http://localhost:9200")); - var transport = new DefaultHttpTransport(settings); + var transport = new DistributedTransport(settings); var response = transport.Get("/", new DefaultRequestParameters()); @@ -61,7 +61,7 @@ public class MyClientConfiguration : TransportConfigurationBase(clientConfiguration); + var transport = new DistributedTransport(clientConfiguration); } } } From 77b57f5b8a85aa50ec7f2b39a8f70f32480edf81 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 30 Aug 2023 14:10:29 +0200 Subject: [PATCH 2/9] update argument name to transport configuration --- .../Configuration/TransportConfiguration.cs | 6 +++--- .../Plumbing/InMemoryConnectionFactory.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Elastic.Transport/Configuration/TransportConfiguration.cs b/src/Elastic.Transport/Configuration/TransportConfiguration.cs index 41b960c..ae342e4 100644 --- a/src/Elastic.Transport/Configuration/TransportConfiguration.cs +++ b/src/Elastic.Transport/Configuration/TransportConfiguration.cs @@ -99,15 +99,15 @@ public TransportConfiguration(string cloudId, Base64ApiKey credentials, ProductR /// /// - /// + /// /// /// public TransportConfiguration( NodePool nodePool, - IRequestInvoker connection = null, + IRequestInvoker invoker = null, Serializer serializer = null, ProductRegistration productRegistration = null) - : base(nodePool, connection, serializer, productRegistration) { } + : base(nodePool, invoker, serializer, productRegistration) { } } diff --git a/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs b/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs index 1257ebf..c38bb05 100644 --- a/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs +++ b/tests/Elastic.Transport.Tests/Plumbing/InMemoryConnectionFactory.cs @@ -12,7 +12,7 @@ public static TransportConfiguration Create() { var invoker = new InMemoryRequestInvoker(); var pool = new SingleNodePool(new Uri("http://localhost:9200")); - var settings = new TransportConfiguration(pool, transport); + var settings = new TransportConfiguration(pool, invoker); return settings; } } From d49735b256da846c31d201bd2bb02e78f7c343a6 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 30 Aug 2023 14:49:11 +0200 Subject: [PATCH 3/9] fix testablehttpconnection --- .../TransportClient/HttpRequestInvoker.cs | 8 ++- .../Diagnostics/DiagnosticSources.cs | 3 +- .../Plumbing/Stubs/TestableHttpConnection.cs | 67 +++++++++---------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs index 76df7b1..2ffde9b 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs @@ -38,8 +38,12 @@ public class HttpRequestInvoker : IRequestInvoker /// /// Allows users to inject their own HttpMessageHandler, and optionally call our default implementation /// - public HttpRequestInvoker(Func, RequestData, HttpMessageHandler> createHttpHandler) => - HttpClientFactory = new RequestDataHttpClientFactory(r => CreateHttpClientHandler(r)); + public HttpRequestInvoker(Func wrappingHandler) => + HttpClientFactory = new RequestDataHttpClientFactory(r => + { + var defaultHandler = CreateHttpClientHandler(r); + return wrappingHandler(defaultHandler, r) ?? defaultHandler; + }); /// public int InUseHandlers => HttpClientFactory.InUseHandlers; diff --git a/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs b/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs index 3303131..618f1e4 100644 --- a/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs +++ b/src/Elastic.Transport/Diagnostics/DiagnosticSources.cs @@ -49,8 +49,9 @@ private interface IDiagnosticsKeys /// public class HttpConnectionDiagnosticKeys : IDiagnosticsKeys { + /// TODO investigate if we can update our source name /// - public string SourceName { get; } = typeof(HttpRequestInvoker).FullName; + public string SourceName { get; } = "Elastic.Transport.HttpTransportClient"; /// Start and stop event initiating the request and sending and receiving the headers public string SendAndReceiveHeaders { get; } = nameof(SendAndReceiveHeaders); diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs index d79d37d..8118d0d 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs @@ -7,43 +7,42 @@ using System.Threading; using System.Threading.Tasks; -namespace Elastic.Transport.IntegrationTests.Plumbing.Stubs +namespace Elastic.Transport.IntegrationTests.Plumbing.Stubs; + +public class TestableHttpConnection : IRequestInvoker { - public class TestableHttpConnection : IRequestInvoker - { - private readonly Action _response; - private TestableClientHandler _handler; - public int CallCount { get; private set; } - public HttpClientHandler LastHttpClientHandler => (HttpClientHandler)_handler.InnerHandler; - private readonly HttpRequestInvoker _requestInvoker; - - public TestableHttpConnection(Action response) => _response = response; - - public TestableHttpConnection() => - _requestInvoker = new HttpRequestInvoker(((defaultHandler, data) => - { - _handler = new TestableClientHandler(defaultHandler(data), _response); - return _handler; - })); - - public TResponse Request(RequestData requestData) - where TResponse : TransportResponse, new() - { - CallCount++; - return _requestInvoker.Request(requestData); - } + private readonly Action _response; + private TestableClientHandler _handler; + public int CallCount { get; private set; } + public HttpClientHandler LastHttpClientHandler => (HttpClientHandler)_handler.InnerHandler; + private readonly HttpRequestInvoker _requestInvoker; - public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) - where TResponse : TransportResponse, new() - { - CallCount++; - return _requestInvoker.RequestAsync(requestData, cancellationToken); - } + public TestableHttpConnection(Action response) : this() => _response = response; - public void Dispose() + public TestableHttpConnection() => + _requestInvoker = new HttpRequestInvoker((defaultHandler, _) => { - _handler?.Dispose(); - _requestInvoker?.Dispose(); - } + _handler = new TestableClientHandler(defaultHandler, _response); + return _handler; + }); + + public TResponse Request(RequestData requestData) + where TResponse : TransportResponse, new() + { + CallCount++; + return _requestInvoker.Request(requestData); + } + + public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) + where TResponse : TransportResponse, new() + { + CallCount++; + return _requestInvoker.RequestAsync(requestData, cancellationToken); + } + + public void Dispose() + { + _handler?.Dispose(); + _requestInvoker?.Dispose(); } } From 918a58c9ff8b39ed209b9210a5a927a68b380cec Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 13 Sep 2023 12:10:55 +0200 Subject: [PATCH 4/9] move to ITRansport and use new SemverInfo --- .../TransportBenchmarks.cs | 2 +- .../Components/Pipeline/RequestData.cs | 1 + .../TransportClient/HttpRequestInvoker.cs | 39 ++---- .../TransportClient/HttpWebRequestInvoker.cs | 8 +- .../TransportClient/InMemoryRequestInvoker.cs | 4 +- src/Elastic.Transport/DistributedTransport.cs | 129 ++++++------------ src/Elastic.Transport/ITransport.cs | 125 +++++++++-------- ...s.cs => ITransportHttpMethodExtensions.cs} | 28 ++-- .../MetaData/ReflectionVersionInfo.cs | 2 + .../DefaultCluster.cs | 2 +- .../IntegrationTestBase.cs | 2 +- .../OpenTelemetry/OpenTelemetryTests.cs | 6 +- .../OpenTelemetryTests.cs | 8 +- 13 files changed, 160 insertions(+), 196 deletions(-) rename src/Elastic.Transport/{ITransportExtensions.cs => ITransportHttpMethodExtensions.cs} (80%) diff --git a/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs b/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs index 9355dc4..0ef7d9a 100644 --- a/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs +++ b/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs @@ -10,7 +10,7 @@ namespace Elastic.Transport.Benchmarks { public class TransportBenchmarks { - private DistributedTransport _requestHandler; + private ITransport _requestHandler; [GlobalSetup] public void Setup() diff --git a/src/Elastic.Transport/Components/Pipeline/RequestData.cs b/src/Elastic.Transport/Components/Pipeline/RequestData.cs index bb6e081..93ccf91 100644 --- a/src/Elastic.Transport/Components/Pipeline/RequestData.cs +++ b/src/Elastic.Transport/Components/Pipeline/RequestData.cs @@ -194,6 +194,7 @@ public Uri Uri public IReadOnlyDictionary RequestMetaData { get; } public bool IsAsync { get; internal set; } + internal OpenTelemetryData OpenTelemetryData { get; } public override string ToString() => $"{Method.GetStringValue()} {_path}"; diff --git a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs index 2ffde9b..36f3b84 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs @@ -56,11 +56,13 @@ public HttpRequestInvoker(Func - public override TResponse Request(RequestData requestData) => + public TResponse Request(RequestData requestData) + where TResponse : TransportResponse, new() => RequestCoreAsync(false, requestData).EnsureCompleted(); /// - public override Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) => + public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) + where TResponse : TransportResponse, new() => RequestCoreAsync(true, requestData, cancellationToken).AsTask(); private async ValueTask RequestCoreAsync(bool isAsync, RequestData requestData, CancellationToken cancellationToken = default) @@ -121,7 +123,7 @@ private async ValueTask RequestCoreAsync(bool isAsync, Req requestData.MadeItToResponse = true; mimeType = responseMessage.Content.Headers.ContentType?.ToString(); - responseHeaders = ParseHeaders(requestData, responseMessage, responseHeaders); + responseHeaders = ParseHeaders(requestData, responseMessage); if (responseMessage.Content != null) { @@ -163,55 +165,44 @@ private async ValueTask RequestCoreAsync(bool isAsync, Req response = requestData.ConnectionSettings.ProductRegistration.ResponseBuilder.ToResponse (requestData, ex, statusCode, responseHeaders, responseStream, mimeType, contentLength, threadPoolStats, tcpStats); - if (OpenTelemetry.CurrentSpanIsElasticTransportOwnedAndHasListeners && (Activity.Current?.IsAllDataRequested ?? false)) - { - var attributes = requestData.ConnectionSettings.ProductRegistration.ParseOpenTelemetryAttributesFromApiCallDetails(response.ApiCallDetails); + if (!OpenTelemetry.CurrentSpanIsElasticTransportOwnedAndHasListeners || (!(Activity.Current?.IsAllDataRequested ?? false))) + return response; - if (attributes is not null) - { - foreach (var attribute in attributes) - { - Activity.Current?.SetTag(attribute.Key, attribute.Value); - } - } - } + var attributes = requestData.ConnectionSettings.ProductRegistration.ParseOpenTelemetryAttributesFromApiCallDetails(response.ApiCallDetails); + + if (attributes is null) return response; + + foreach (var attribute in attributes) + Activity.Current?.SetTag(attribute.Key, attribute.Value); return response; } } - private static Dictionary> ParseHeaders(RequestData requestData, - HttpResponseMessage responseMessage, Dictionary> responseHeaders) + private static Dictionary>? ParseHeaders(RequestData requestData, HttpResponseMessage responseMessage) { + Dictionary>? responseHeaders = null; var defaultHeadersForProduct = requestData.ConnectionSettings.ProductRegistration.DefaultHeadersToParse(); foreach (var headerToParse in defaultHeadersForProduct) - { if (responseMessage.Headers.TryGetValues(headerToParse, out var values)) { responseHeaders ??= new Dictionary>(); responseHeaders.Add(headerToParse, values); } - } if (requestData.ParseAllHeaders) - { foreach (var header in responseMessage.Headers) { responseHeaders ??= new Dictionary>(); responseHeaders.Add(header.Key, header.Value); } - } else if (requestData.ResponseHeadersToParse.Count > 0) - { foreach (var headerToParse in requestData.ResponseHeadersToParse) - { if (responseMessage.Headers.TryGetValues(headerToParse, out var values)) { responseHeaders ??= new Dictionary>(); responseHeaders.Add(headerToParse, values); } - } - } return responseHeaders; } diff --git a/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs index 47bb74c..55ee3ef 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs @@ -47,12 +47,16 @@ public HttpWebRequestInvoker() { } internal static bool IsMono { get; } = Type.GetType("Mono.Runtime") != null; + void IDisposable.Dispose() {} + /// > - public override TResponse Request(RequestData requestData) => + public TResponse Request(RequestData requestData) + where TResponse : TransportResponse, new() => RequestCoreAsync(false, requestData).EnsureCompleted(); /// > - public override Task RequestAsync(RequestData requestData, CancellationToken cancellationToken = default) => + public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken = default) + where TResponse : TransportResponse, new() => RequestCoreAsync(true, requestData, cancellationToken).AsTask(); private async ValueTask RequestCoreAsync(bool isAsync, RequestData requestData, CancellationToken cancellationToken = default) diff --git a/src/Elastic.Transport/Components/TransportClient/InMemoryRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/InMemoryRequestInvoker.cs index 8a34800..12e1f9b 100644 --- a/src/Elastic.Transport/Components/TransportClient/InMemoryRequestInvoker.cs +++ b/src/Elastic.Transport/Components/TransportClient/InMemoryRequestInvoker.cs @@ -19,7 +19,7 @@ public class InMemoryRequestInvoker : IRequestInvoker { private static readonly byte[] EmptyBody = Encoding.UTF8.GetBytes(""); private readonly string _contentType; - private readonly Exception _exception; + private readonly Exception? _exception; private readonly byte[] _responseBody; private readonly int _statusCode; private readonly Dictionary> _headers; @@ -31,7 +31,7 @@ public class InMemoryRequestInvoker : IRequestInvoker public InMemoryRequestInvoker() => _statusCode = 200; /// - public InMemoryRequestInvoker(byte[] responseBody, int statusCode = 200, Exception exception = null, string contentType = RequestData.DefaultMimeType, Dictionary> headers = null) + public InMemoryRequestInvoker(byte[] responseBody, int statusCode = 200, Exception? exception = null, string contentType = RequestData.DefaultMimeType, Dictionary> headers = null) { _responseBody = responseBody; _statusCode = statusCode; diff --git a/src/Elastic.Transport/DistributedTransport.cs b/src/Elastic.Transport/DistributedTransport.cs index cffa87b..a911584 100644 --- a/src/Elastic.Transport/DistributedTransport.cs +++ b/src/Elastic.Transport/DistributedTransport.cs @@ -28,24 +28,7 @@ public sealed class DistributedTransport : DistributedTransport /// The connection settings to use for this transport - public DistributedTransport(TransportConfiguration configurationValues) : base(configurationValues) - { - } - - /// - /// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on - /// different - /// nodes - /// - /// The connection settings to use for this transport - /// The date time proved to use, safe to pass null to use the default - /// The memory stream provider to use, safe to pass null to use the default - public DistributedTransport(TransportConfiguration configurationValues, - DateTimeProvider dateTimeProvider = null, MemoryStreamFactory memoryStreamFactory = null - ) - : base(configurationValues, null, dateTimeProvider, memoryStreamFactory) - { - } + public DistributedTransport(TransportConfiguration configurationValues) : base(configurationValues, null, null) { } /// /// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on @@ -56,49 +39,21 @@ public DistributedTransport(TransportConfiguration configurationValues, /// In charge of create a new pipeline, safe to pass null to use the default /// The date time proved to use, safe to pass null to use the default /// The memory stream provider to use, safe to pass null to use the default - internal DistributedTransport(TransportConfiguration configurationValues, - RequestPipelineFactory pipelineProvider = null, - DateTimeProvider dateTimeProvider = null, MemoryStreamFactory memoryStreamFactory = null + internal DistributedTransport( + TransportConfiguration configurationValues, + RequestPipelineFactory? pipelineProvider = null, + DateTimeProvider? dateTimeProvider = null, + MemoryStreamFactory? memoryStreamFactory = null ) - : base(configurationValues, pipelineProvider, dateTimeProvider, memoryStreamFactory) - { - } + : base(configurationValues, pipelineProvider, dateTimeProvider, memoryStreamFactory) { } } /// public class DistributedTransport : ITransport where TConfiguration : class, ITransportConfiguration { - private static readonly string TransportVersion = typeof(DistributedTransport).Assembly - .GetCustomAttribute() - .InformationalVersion; - private readonly ProductRegistration _productRegistration; - /// - /// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on - /// different - /// nodes - /// - /// The connection settings to use for this transport - public DistributedTransport(TConfiguration configurationValues) : this(configurationValues, null, null, null) - { - } - - /// - /// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on - /// different - /// nodes - /// - /// The connection settings to use for this transport - /// The date time proved to use, safe to pass null to use the default - /// The memory stream provider to use, safe to pass null to use the default - public DistributedTransport( - TConfiguration configurationValues, - DateTimeProvider dateTimeProvider = null, - MemoryStreamFactory memoryStreamFactory = null) - : this(configurationValues, null, dateTimeProvider, memoryStreamFactory) { } - /// /// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on /// different @@ -110,9 +65,9 @@ public DistributedTransport( /// The memory stream provider to use, safe to pass null to use the default public DistributedTransport( TConfiguration configurationValues, - RequestPipelineFactory pipelineProvider = null, - DateTimeProvider dateTimeProvider = null, - MemoryStreamFactory memoryStreamFactory = null + RequestPipelineFactory? pipelineProvider = null, + DateTimeProvider? dateTimeProvider = null, + MemoryStreamFactory? memoryStreamFactory = null ) { configurationValues.ThrowIfNull(nameof(configurationValues)); @@ -132,29 +87,31 @@ public DistributedTransport( private MemoryStreamFactory MemoryStreamFactory { get; } private RequestPipelineFactory PipelineProvider { get; } - /// - /// - /// + /// public TConfiguration Configuration { get; } - /// - public override TResponse Request( + /// + public TResponse Request( HttpMethod method, string path, PostData? data, RequestParameters? requestParameters, - in OpenTelemetryData openTelemetryData) - => RequestCoreAsync(false, method, path, data, requestParameters, openTelemetryData).EnsureCompleted(); + in OpenTelemetryData openTelemetryData + ) + where TResponse : TransportResponse, new() => + RequestCoreAsync(false, method, path, data, requestParameters, openTelemetryData).EnsureCompleted(); - /// - public override Task RequestAsync( + /// + public Task RequestAsync( HttpMethod method, string path, PostData? data, RequestParameters? requestParameters, in OpenTelemetryData openTelemetryData, - CancellationToken cancellationToken = default) - => RequestCoreAsync(true, method, path, data, requestParameters, openTelemetryData, cancellationToken).AsTask(); + CancellationToken cancellationToken = default + ) + where TResponse : TransportResponse, new() => + RequestCoreAsync(true, method, path, data, requestParameters, openTelemetryData, cancellationToken).AsTask(); private async ValueTask RequestCoreAsync( bool isAsync, @@ -163,13 +120,15 @@ private async ValueTask RequestCoreAsync( PostData? data, RequestParameters? requestParameters, OpenTelemetryData openTelemetryData, - CancellationToken cancellationToken = default) - where TResponse : TransportResponse, new() + CancellationToken cancellationToken = default + ) + where TResponse : TransportResponse, new() { Activity activity = null; if (OpenTelemetry.ElasticTransportActivitySource.HasListeners()) - activity = OpenTelemetry.ElasticTransportActivitySource.StartActivity(openTelemetryData.SpanName ?? method.GetStringValue(), ActivityKind.Client); + activity = OpenTelemetry.ElasticTransportActivitySource.StartActivity(openTelemetryData.SpanName ?? method.GetStringValue(), + ActivityKind.Client); try { @@ -185,28 +144,24 @@ private async ValueTask RequestCoreAsync( Configuration.OnRequestDataCreated?.Invoke(requestData); TResponse response = null; - if (OpenTelemetry.ElasticTransportActivitySource.HasListeners() && activity.IsAllDataRequested) + if (OpenTelemetry.ElasticTransportActivitySource.HasListeners() && activity is { IsAllDataRequested: true }) { if (activity.IsAllDataRequested) OpenTelemetry.SetCommonAttributes(activity, openTelemetryData, Configuration); if (Configuration.Authentication is BasicAuthentication basicAuthentication) - activity?.SetTag(SemanticConventions.DbUser, basicAuthentication.Username); + activity.SetTag(SemanticConventions.DbUser, basicAuthentication.Username); - activity?.SetTag(OpenTelemetryAttributes.ElasticTransportProductName, Configuration.ProductRegistration.Name); - activity?.SetTag(OpenTelemetryAttributes.ElasticTransportProductVersion, Configuration.ProductRegistration.ProductAssemblyVersion); - activity?.SetTag(OpenTelemetryAttributes.ElasticTransportVersion, TransportVersion); - activity?.SetTag(SemanticConventions.UserAgentOriginal, Configuration.UserAgent.ToString()); + activity.SetTag(OpenTelemetryAttributes.ElasticTransportProductName, Configuration.ProductRegistration.Name); + activity.SetTag(OpenTelemetryAttributes.ElasticTransportProductVersion, Configuration.ProductRegistration.ProductAssemblyVersion); + activity.SetTag(OpenTelemetryAttributes.ElasticTransportVersion, ReflectionVersionInfo.TransportVersion); + activity.SetTag(SemanticConventions.UserAgentOriginal, Configuration.UserAgent.ToString()); - if (openTelemetryData.SpanAttributes is not null) - { + if (requestData.OpenTelemetryData.SpanAttributes is not null) foreach (var attribute in requestData.OpenTelemetryData.SpanAttributes) - { - activity?.SetTag(attribute.Key, attribute.Value); - } - } + activity.SetTag(attribute.Key, attribute.Value); - activity?.SetTag(SemanticConventions.HttpRequestMethod, requestData.Method.GetStringValue()); + activity.SetTag(SemanticConventions.HttpRequestMethod, requestData.Method.GetStringValue()); } List? seenExceptions = null; @@ -306,9 +261,7 @@ private async ValueTask RequestCoreAsync( throw new UnexpectedTransportException(killerException, seenExceptions) { - Request = requestData, - ApiCallDetails = response?.ApiCallDetails, - AuditTrail = pipeline.AuditTrail + Request = requestData, ApiCallDetails = response?.ApiCallDetails, AuditTrail = pipeline.AuditTrail }; } @@ -380,10 +333,12 @@ private TResponse FinalizeResponse(RequestData requestData, RequestPi } private static ApiCallDetails? GetMostRecentCallDetails(TResponse? response, - IEnumerable? seenExceptions) + IEnumerable? seenExceptions + ) where TResponse : TransportResponse, new() { - var callDetails = response?.ApiCallDetails ?? seenExceptions?.LastOrDefault(e => e.Response?.ApiCallDetails != null)?.Response?.ApiCallDetails; + var callDetails = response?.ApiCallDetails + ?? seenExceptions?.LastOrDefault(e => e.Response?.ApiCallDetails != null)?.Response?.ApiCallDetails; return callDetails; } diff --git a/src/Elastic.Transport/ITransport.cs b/src/Elastic.Transport/ITransport.cs index 3da33d1..c4db867 100644 --- a/src/Elastic.Transport/ITransport.cs +++ b/src/Elastic.Transport/ITransport.cs @@ -20,35 +20,10 @@ public interface ITransport /// The type to deserialize the response body into. /// The for the HTTP request. /// The path of the request. - /// The deserialized . - public TResponse Request( - HttpMethod method, - string path) - where TResponse : TransportResponse, new() - => Request(method, path, null, null, default); - -#pragma warning disable 1573 - /// /// The data to be included as the body of the HTTP request. - public TResponse Request( - HttpMethod method, - string path, - PostData? postData) - where TResponse : TransportResponse, new() - => Request(method, path, postData, null, default); - - /// /// The parameters for the request. - public TResponse Request( - HttpMethod method, - string path, - PostData? postData, - RequestParameters? requestParameters) - where TResponse : TransportResponse, new() - => Request(method, path, postData, requestParameters, default); - - /// /// Data to be used to control the OpenTelemetry instrumentation. + /// The deserialized . public TResponse Request( HttpMethod method, string path, @@ -56,7 +31,7 @@ public TResponse Request( RequestParameters? requestParameters, in OpenTelemetryData openTelemetryData) where TResponse : TransportResponse, new(); -#pragma warning restore 1573 + /// /// Orchestrate a request asynchronously into a using the workflow defined in the . @@ -64,59 +39,95 @@ public TResponse Request( /// The type to deserialize the response body into. /// The for the HTTP request. /// The path of the request. + /// The data to be included as the body of the HTTP request. + /// The parameters for the request. /// The cancellation token to use. + /// Data to be used to control the OpenTelemetry instrumentation. /// The deserialized . public Task RequestAsync( HttpMethod method, string path, + PostData? postData, + RequestParameters? requestParameters, + in OpenTelemetryData openTelemetryData, CancellationToken cancellationToken = default) + where TResponse : TransportResponse, new(); +} + +/// +/// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on +/// different nodes +/// +public interface ITransport : ITransport + where TConfiguration : class, ITransportConfiguration +{ + /// + /// The in use by this transport instance + /// + public TConfiguration Configuration { get; } +} + +/// +/// Add request extension overloads so callees do not have to always pass all the parameters. +/// +public static class TransportExtensions +{ + + /// > + public static TResponse Request( + this ITransport transport, + HttpMethod method, + string path) where TResponse : TransportResponse, new() - => RequestAsync(method, path, null, null, default, cancellationToken); + => transport.Request(method, path, null, null, default); -#pragma warning disable 1573 - /// - /// The data to be included as the body of the HTTP request. - public Task RequestAsync( + /// > + public static TResponse Request( + this ITransport transport, + HttpMethod method, + string path, + PostData? postData) + where TResponse : TransportResponse, new() + => transport.Request(method, path, postData, null, default); + + /// > + public static TResponse Request( + this ITransport transport, HttpMethod method, string path, PostData? postData, + RequestParameters? requestParameters) + where TResponse : TransportResponse, new() + => transport.Request(method, path, postData, requestParameters, default); + + + /// > + public static Task RequestAsync( + this ITransport transport, + HttpMethod method, + string path, CancellationToken cancellationToken = default) where TResponse : TransportResponse, new() - => RequestAsync(method, path, postData, null, default, cancellationToken); + => transport.RequestAsync(method, path, null, null, default, cancellationToken); - /// - /// The parameters for the request. - public Task RequestAsync( + /// > + public static Task RequestAsync( + this ITransport transport, HttpMethod method, string path, PostData? postData, - RequestParameters? requestParameters, CancellationToken cancellationToken = default) where TResponse : TransportResponse, new() - => RequestAsync(method, path, postData, requestParameters, default, cancellationToken); + => transport.RequestAsync(method, path, postData, null, default, cancellationToken); - /// - /// Data to be used to control the OpenTelemetry instrumentation. - public Task RequestAsync( + /// > + public static Task RequestAsync( + this ITransport transport, HttpMethod method, string path, PostData? postData, RequestParameters? requestParameters, - in OpenTelemetryData openTelemetryData, CancellationToken cancellationToken = default) - where TResponse : TransportResponse, new(); -#pragma warning restore 1573 -} - -/// -/// Transport coordinates the client requests over the node pool nodes and is in charge of falling over on -/// different nodes -/// -public interface ITransport : ITransport - where TConfiguration : class, ITransportConfiguration -{ - /// - /// The in use by this transport instance - /// - public TConfiguration Configuration { get; } + where TResponse : TransportResponse, new() + => transport.RequestAsync(method, path, postData, requestParameters, default, cancellationToken); } diff --git a/src/Elastic.Transport/ITransportExtensions.cs b/src/Elastic.Transport/ITransportHttpMethodExtensions.cs similarity index 80% rename from src/Elastic.Transport/ITransportExtensions.cs rename to src/Elastic.Transport/ITransportHttpMethodExtensions.cs index 16e9910..c156ff1 100644 --- a/src/Elastic.Transport/ITransportExtensions.cs +++ b/src/Elastic.Transport/ITransportHttpMethodExtensions.cs @@ -10,74 +10,74 @@ namespace Elastic.Transport; /// /// Extends with some convenience methods to make it easier to perform specific requests /// -public static class ITransportExtensions +public static class TransportHttpMethodExtensions { /// Perform a GET request public static TResponse Get(this ITransport requestHandler, string path, - RequestParameters parameters = null) + RequestParameters? parameters = null) where TResponse : TransportResponse, new() => requestHandler.Request(HttpMethod.GET, path, null, parameters); /// Perform a GET request public static Task GetAsync(this ITransport requestHandler, string path, - RequestParameters parameters = null, CancellationToken cancellationToken = default) + RequestParameters? parameters = null, CancellationToken cancellationToken = default) where TResponse : TransportResponse, new() => requestHandler.RequestAsync(HttpMethod.GET, path, null, parameters, cancellationToken); /// Perform a HEAD request public static TResponse Head(this ITransport requestHandler, string path, - RequestParameters parameters = null) + RequestParameters? parameters = null) where TResponse : TransportResponse, new() => requestHandler.Request(HttpMethod.HEAD, path, null, parameters); /// Perform a HEAD request public static Task HeadAsync(this ITransport requestHandler, string path, - RequestParameters parameters = null, CancellationToken cancellationToken = default) + RequestParameters? parameters = null, CancellationToken cancellationToken = default) where TResponse : TransportResponse, new() => requestHandler.RequestAsync(HttpMethod.HEAD, path, null, parameters, cancellationToken); /// Perform a HEAD request - public static VoidResponse Head(this ITransport requestHandler, string path, RequestParameters parameters = null) => + public static VoidResponse Head(this ITransport requestHandler, string path, RequestParameters? parameters = null) => requestHandler.Head(path, parameters); /// Perform a HEAD request public static Task HeadAsync(this ITransport requestHandler, string path, - RequestParameters parameters = null, CancellationToken cancellationToken = default) => + RequestParameters? parameters = null, CancellationToken cancellationToken = default) => requestHandler.HeadAsync(path, parameters, cancellationToken); /// Perform a POST request public static TResponse Post(this ITransport requestHandler, string path, PostData data, - RequestParameters parameters = null) + RequestParameters? parameters = null) where TResponse : TransportResponse, new() => requestHandler.Request(HttpMethod.POST, path, data, parameters); /// Perform a POST request public static Task PostAsync(this ITransport requestHandler, string path, PostData data, - RequestParameters parameters = null, CancellationToken cancellationToken = default) + RequestParameters? parameters = null, CancellationToken cancellationToken = default) where TResponse : TransportResponse, new() => requestHandler.RequestAsync(HttpMethod.POST, path, data, parameters, cancellationToken); /// Perform a PUT request public static TResponse Put(this ITransport requestHandler, string path, PostData data, - RequestParameters parameters = null) + RequestParameters? parameters = null) where TResponse : TransportResponse, new() => requestHandler.Request(HttpMethod.PUT, path, data, parameters); /// Perform a PUT request public static Task PutAsync(this ITransport requestHandler, string path, PostData data, - RequestParameters parameters = null, CancellationToken cancellationToken = default) + RequestParameters? parameters = null, CancellationToken cancellationToken = default) where TResponse : TransportResponse, new() => requestHandler.RequestAsync(HttpMethod.PUT, path, data, parameters, cancellationToken); /// Perform a DELETE request - public static TResponse Delete(this ITransport requestHandler, string path, PostData data = null, - RequestParameters parameters = null) + public static TResponse Delete(this ITransport requestHandler, string path, PostData? data = null, + RequestParameters? parameters = null) where TResponse : TransportResponse, new() => requestHandler.Request(HttpMethod.DELETE, path, data, parameters); /// Perform a DELETE request public static Task DeleteAsync(this ITransport requestHandler, string path, - PostData data = null, RequestParameters parameters = null, CancellationToken cancellationToken = default) + PostData? data = null, RequestParameters? parameters = null, CancellationToken cancellationToken = default) where TResponse : TransportResponse, new() => requestHandler.RequestAsync(HttpMethod.DELETE, path, data, parameters, cancellationToken); } diff --git a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs index a8db8f6..c7d01dd 100644 --- a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs +++ b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs @@ -15,6 +15,8 @@ internal sealed class ReflectionVersionInfo : VersionInfo { private static readonly SemVersion Empty = new(0, 0, 0); + public static readonly string TransportVersion = Create().ToString(); + private ReflectionVersionInfo(SemVersion version) : base((int)version.Major, (int)version.Minor, (int)version.Patch, version.Prerelease, version.Metadata) { diff --git a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs index 9c0ee51..3bb5ec0 100644 --- a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs +++ b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs @@ -24,7 +24,7 @@ public DefaultCluster() : this(new XunitClusterConfiguration(Version) { Starting public DefaultCluster(XunitClusterConfiguration xunitClusterConfiguration) : base(xunitClusterConfiguration) { } - public DistributedTransport CreateClient(ITestOutputHelper output) => + public ITransport CreateClient(ITestOutputHelper output) => this.GetOrAddClient(cluster => { var nodes = NodesUris(); diff --git a/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs b/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs index 7ef3295..e1c0e0f 100644 --- a/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs +++ b/tests/Elastic.Elasticsearch.IntegrationTests/IntegrationTestBase.cs @@ -16,7 +16,7 @@ public abstract class IntegrationTestBase : IClusterFixture where TCluster : DefaultCluster, new() { protected TCluster Cluster { get; } - protected DistributedTransport RequestHandler { get; } + protected ITransport RequestHandler { get; } protected IntegrationTestBase(TCluster cluster, ITestOutputHelper output) diff --git a/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs b/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs index 1289e27..29cc079 100644 --- a/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs @@ -33,7 +33,7 @@ public async Task ElasticsearchTagsShouldBeSet_WhenUsingTheElasticsearchRegistra var connection = new TestableHttpConnection(); var connectionPool = new SingleNodePool(Server.Uri); var config = new TransportConfiguration(connectionPool, connection, productRegistration: new ElasticsearchProductRegistration(typeof(Clients.Elasticsearch.ElasticsearchClient))); - var transport = new DefaultHttpTransport(config); + var transport = new DistributedTransport(config); var mre = new ManualResetEvent(false); @@ -65,7 +65,7 @@ static void Assertions(Activity activity) var informationalVersion = (typeof(Clients.Elasticsearch.ElasticsearchClient) .Assembly .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) - as AssemblyInformationalVersionAttribute[]).FirstOrDefault()?.InformationalVersion; + as AssemblyInformationalVersionAttribute[])?.FirstOrDefault()?.InformationalVersion; activity.TagObjects.Should().Contain(t => t.Key == OpenTelemetryAttributes.DbElasticsearchClusterName) .Subject.Value.Should().BeOfType() @@ -100,4 +100,4 @@ public Task Get() } [CollectionDefinition(nameof(NonParallelCollection), DisableParallelization = true)] -public class NonParallelCollection { } \ No newline at end of file +public class NonParallelCollection { } diff --git a/tests/Elastic.Transport.Tests/OpenTelemetryTests.cs b/tests/Elastic.Transport.Tests/OpenTelemetryTests.cs index 2e7052e..993cce1 100644 --- a/tests/Elastic.Transport.Tests/OpenTelemetryTests.cs +++ b/tests/Elastic.Transport.Tests/OpenTelemetryTests.cs @@ -27,10 +27,10 @@ public async Task DefaultTagsShouldBeSet() static void Assertions(Activity activity) { - var informationalVersion = (typeof(HttpTransport) + var informationalVersion = (typeof(DistributedTransport) .Assembly .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) - as AssemblyInformationalVersionAttribute[]).FirstOrDefault()?.InformationalVersion; + as AssemblyInformationalVersionAttribute[])?.FirstOrDefault()?.InformationalVersion; activity.Should().NotBeNull(); activity.Kind.Should().Be(ActivityKind.Client); @@ -124,7 +124,7 @@ static void Assertions(Activity activity) private Task TestCoreAsync(Action assertion) => TestCoreAsync(assertion, default); - private async Task TestCoreAsync(Action assertions, OpenTelemetryData openTelemetryData, HttpTransport transport = null) + private async Task TestCoreAsync(Action assertions, OpenTelemetryData openTelemetryData, ITransport transport = null) { var mre = new ManualResetEvent(false); @@ -147,7 +147,7 @@ private async Task TestCoreAsync(Action assertions, OpenTelemetryData }; ActivitySource.AddActivityListener(listener); - transport ??= new DefaultHttpTransport(InMemoryConnectionFactory.Create()); + transport ??= new DistributedTransport(InMemoryConnectionFactory.Create()); _ = await transport.RequestAsync(HttpMethod.GET, "/", null, null, openTelemetryData); From 196a4d002b17aad4331b8181e382db75b34db937 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 13 Sep 2023 12:50:06 +0200 Subject: [PATCH 5/9] Introduce `ToSemverString` for now --- .../Requests/MetaData/ReflectionVersionInfo.cs | 4 ++-- .../Requests/MetaData/VersionInfo.cs | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs index c7d01dd..4366ff0 100644 --- a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs +++ b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs @@ -15,10 +15,10 @@ internal sealed class ReflectionVersionInfo : VersionInfo { private static readonly SemVersion Empty = new(0, 0, 0); - public static readonly string TransportVersion = Create().ToString(); + public static readonly string TransportVersion = Create().ToSemverString(); private ReflectionVersionInfo(SemVersion version) : - base((int)version.Major, (int)version.Minor, (int)version.Patch, version.Prerelease, version.Metadata) + base(version.Major, version.Minor, version.Patch, version.Prerelease, version.Metadata) { } diff --git a/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs b/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs index 46fa0c3..b8d2209 100644 --- a/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs +++ b/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs @@ -56,10 +56,20 @@ protected VersionInfo(int major, int minor, int patch, string? prerelease, strin Metadata = metadata; } - /// - /// - /// - /// + /// Returns the full version as a semantic version number + public string ToSemverString() + { + var prefix = $"{Major}.{Minor}.{Patch}"; + return (Prerelease, Metadata) switch + { + (null, null) => prefix, + (not null, null) => $"{prefix}-{Prerelease}", + (not null, not null) => $"{prefix}-{Prerelease}+{Metadata}", + (null, not null) => $"{prefix}+{Metadata}" + }; + } + + /// Returns the version in a way that safe to emit as telemetry public override string ToString() { var prefix = $"{Major}.{Minor}.{Patch}"; From 3adb302d0467230982a8a6c8f8addebfe57e4057 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 13 Sep 2023 12:51:35 +0200 Subject: [PATCH 6/9] rename --- .../Requests/MetaData/ReflectionVersionInfo.cs | 2 +- src/Elastic.Transport/Requests/MetaData/RuntimeVersionInfo.cs | 2 +- src/Elastic.Transport/Requests/MetaData/VersionInfo.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs index 4366ff0..a38ed5d 100644 --- a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs +++ b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs @@ -15,7 +15,7 @@ internal sealed class ReflectionVersionInfo : VersionInfo { private static readonly SemVersion Empty = new(0, 0, 0); - public static readonly string TransportVersion = Create().ToSemverString(); + public static readonly string TransportVersion = Create().ToFullString(); private ReflectionVersionInfo(SemVersion version) : base(version.Major, version.Minor, version.Patch, version.Prerelease, version.Metadata) diff --git a/src/Elastic.Transport/Requests/MetaData/RuntimeVersionInfo.cs b/src/Elastic.Transport/Requests/MetaData/RuntimeVersionInfo.cs index be87789..d0de175 100644 --- a/src/Elastic.Transport/Requests/MetaData/RuntimeVersionInfo.cs +++ b/src/Elastic.Transport/Requests/MetaData/RuntimeVersionInfo.cs @@ -59,7 +59,7 @@ public RuntimeVersionInfo() : this(GetRuntimeVersion()) private RuntimeVersionInfo(SemVersion version) : // We don't care about metadata - base((int)version.Major, (int)version.Minor, (int)version.Patch, version.Prerelease, null) + base(version.Major, version.Minor, version.Patch, version.Prerelease, null) { } diff --git a/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs b/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs index b8d2209..83b6f09 100644 --- a/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs +++ b/src/Elastic.Transport/Requests/MetaData/VersionInfo.cs @@ -57,7 +57,7 @@ protected VersionInfo(int major, int minor, int patch, string? prerelease, strin } /// Returns the full version as a semantic version number - public string ToSemverString() + public string ToFullString() { var prefix = $"{Major}.{Minor}.{Patch}"; return (Prerelease, Metadata) switch From 59f2fd88e5e6b1c9b44c2b306232fc35c0a4597d Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 13 Sep 2023 14:05:33 +0200 Subject: [PATCH 7/9] update connection args to requestInvoker --- .../TransportBenchmarks.cs | 12 +++---- .../Components/ExposingPipelineFactory.cs | 12 +++---- .../Components/SealedVirtualCluster.cs | 12 +++---- .../Components/VirtualClusterConnection.cs | 14 ++++---- .../Components/VirtualizedCluster.cs | 2 +- .../Products/MockProductRegistration.cs | 4 +-- .../Components/NodePool/StaticNodePool.cs | 2 +- .../TransportClient/HttpRequestInvoker.cs | 2 +- .../Configuration/TransportConfiguration.cs | 10 +++--- src/Elastic.Transport/DistributedTransport.cs | 6 ++-- .../Products/DefaultProductRegistration.cs | 6 ++-- .../ElasticsearchProductRegistration.cs | 4 +-- .../Products/ProductRegistration.cs | 8 ++--- .../DefaultCluster.cs | 4 +-- .../Http/ApiCompatibilityHeaderTests.cs | 6 ++-- .../Http/TransferEncodingChunckedTests.cs | 34 +++++++++---------- .../OpenTelemetry/OpenTelemetryTests.cs | 6 ++-- ...onnection.cs => TrackingRequestInvoker.cs} | 6 ++-- tests/Elastic.Transport.Tests/Test.cs | 4 +-- 19 files changed, 77 insertions(+), 77 deletions(-) rename tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/{TestableHttpConnection.cs => TrackingRequestInvoker.cs} (90%) diff --git a/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs b/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs index 0ef7d9a..4cf1b21 100644 --- a/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs +++ b/benchmarks/Elastic.Transport.Benchmarks/TransportBenchmarks.cs @@ -10,22 +10,22 @@ namespace Elastic.Transport.Benchmarks { public class TransportBenchmarks { - private ITransport _requestHandler; + private ITransport _transport; [GlobalSetup] public void Setup() { - var connection = new InMemoryRequestInvoker(); + var requestInvoker = new InMemoryRequestInvoker(); var pool = new SingleNodePool(new Uri("http://localhost:9200")); - var settings = new TransportConfiguration(pool, connection); + var settings = new TransportConfiguration(pool, requestInvoker); - _requestHandler = new DistributedTransport(settings); + _transport = new DistributedTransport(settings); } [Benchmark] - public void TransportSuccessfulRequestBenchmark() => _requestHandler.Get("/"); + public void TransportSuccessfulRequestBenchmark() => _transport.Get("/"); [Benchmark] - public async Task TransportSuccessfulAsyncRequestBenchmark() => await _requestHandler.GetAsync("/"); + public async Task TransportSuccessfulAsyncRequestBenchmark() => await _transport.GetAsync("/"); } } diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs b/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs index 70ca5f0..5882b5c 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs @@ -9,23 +9,23 @@ namespace Elastic.Transport.VirtualizedCluster.Components; /// public sealed class ExposingPipelineFactory : RequestPipelineFactory where TConfiguration : class, ITransportConfiguration { - public ExposingPipelineFactory(TConfiguration connectionSettings, DateTimeProvider dateTimeProvider) + public ExposingPipelineFactory(TConfiguration configuration, DateTimeProvider dateTimeProvider) { DateTimeProvider = dateTimeProvider; MemoryStreamFactory = TransportConfiguration.DefaultMemoryStreamFactory; - Settings = connectionSettings; - Pipeline = Create(Settings, DateTimeProvider, MemoryStreamFactory, new DefaultRequestParameters()); - RequestHandler = new DistributedTransport(Settings, this, DateTimeProvider, MemoryStreamFactory); + Configuration = configuration; + Pipeline = Create(Configuration, DateTimeProvider, MemoryStreamFactory, new DefaultRequestParameters()); + RequestHandler = new DistributedTransport(Configuration, this, DateTimeProvider, MemoryStreamFactory); } // ReSharper disable once MemberCanBePrivate.Global public RequestPipeline Pipeline { get; } private DateTimeProvider DateTimeProvider { get; } private MemoryStreamFactory MemoryStreamFactory { get; } - private TConfiguration Settings { get; } + private TConfiguration Configuration { get; } public ITransport RequestHandler { get; } public override RequestPipeline Create(TConfiguration configurationValues, DateTimeProvider dateTimeProvider, MemoryStreamFactory memoryStreamFactory, RequestParameters requestParameters) => - new DefaultRequestPipeline(Settings, DateTimeProvider, MemoryStreamFactory, requestParameters ?? new DefaultRequestParameters()); + new DefaultRequestPipeline(Configuration, DateTimeProvider, MemoryStreamFactory, requestParameters ?? new DefaultRequestParameters()); } diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs b/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs index bf0b1c8..f479f92 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs @@ -15,21 +15,21 @@ namespace Elastic.Transport.VirtualizedCluster.Components; /// public sealed class SealedVirtualCluster { - private readonly IRequestInvoker _connection; - private readonly NodePool _connectionPool; + private readonly IRequestInvoker _requestInvoker; + private readonly NodePool _nodePool; private readonly TestableDateTimeProvider _dateTimeProvider; private readonly MockProductRegistration _productRegistration; internal SealedVirtualCluster(VirtualCluster cluster, NodePool pool, TestableDateTimeProvider dateTimeProvider, MockProductRegistration productRegistration) { - _connectionPool = pool; - _connection = new VirtualClusterTransport(cluster, dateTimeProvider); + _nodePool = pool; + _requestInvoker = new VirtualClusterRequestInvoker(cluster, dateTimeProvider); _dateTimeProvider = dateTimeProvider; _productRegistration = productRegistration; } private TransportConfiguration CreateSettings() => - new(_connectionPool, _connection, serializer: null, _productRegistration.ProductRegistration); + new(_nodePool, _requestInvoker, serializer: null, _productRegistration.ProductRegistration); /// Create the cluster using all defaults on public VirtualizedCluster AllDefaults() => @@ -44,7 +44,7 @@ public VirtualizedCluster Settings(Func using the DSL provided by /// /// Provide custom configuration options - public VirtualClusterTransport VirtualClusterConnection(Func selector = null) => + public VirtualClusterRequestInvoker VirtualClusterConnection(Func selector = null) => new VirtualizedCluster(_dateTimeProvider, selector == null ? CreateSettings() : selector(CreateSettings())) .Connection; } diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs index da7bdf2..e357c1f 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualClusterConnection.cs @@ -21,7 +21,7 @@ namespace Elastic.Transport.VirtualizedCluster.Components; /// -/// An in memory connection that uses a rule engine to return different responses for sniffs/pings and API calls. +/// An in memory requestInvoker that uses a rule engine to return different responses for sniffs/pings and API calls. ///
 /// Either instantiate through the static  or  for the simplest use-cases
 /// 
@@ -30,7 +30,7 @@ namespace Elastic.Transport.VirtualizedCluster.Components; /// becomes available /// ///
-public class VirtualClusterTransport : IRequestInvoker +public class VirtualClusterRequestInvoker : IRequestInvoker { private static readonly object Lock = new(); @@ -43,7 +43,7 @@ public class VirtualClusterTransport : IRequestInvoker private readonly InMemoryRequestInvoker _inMemoryRequestInvoker; - internal VirtualClusterTransport(VirtualCluster cluster, TestableDateTimeProvider dateTimeProvider) + internal VirtualClusterRequestInvoker(VirtualCluster cluster, TestableDateTimeProvider dateTimeProvider) { UpdateCluster(cluster); _dateTimeProvider = dateTimeProvider; @@ -54,10 +54,10 @@ internal VirtualClusterTransport(VirtualCluster cluster, TestableDateTimeProvide void IDisposable.Dispose() { } /// - /// Create a instance that always returns a successful response. + /// Create a instance that always returns a successful response. /// /// The bytes to be returned on every API call invocation - public static VirtualClusterTransport Success(byte[] response) => + public static VirtualClusterRequestInvoker Success(byte[] response) => Virtual.Elasticsearch .Bootstrap(1) .ClientCalls(r => r.SucceedAlways().ReturnByteResponse(response)) @@ -66,9 +66,9 @@ public static VirtualClusterTransport Success(byte[] response) => .Connection; /// - /// Create a instance that always returns a failed response. + /// Create a instance that always returns a failed response. /// - public static VirtualClusterTransport Error() => + public static VirtualClusterRequestInvoker Error() => Virtual.Elasticsearch .Bootstrap(1) .ClientCalls(r => r.FailAlways(400)) diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs index 92999ef..bbb6ed2 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs @@ -48,7 +48,7 @@ internal VirtualizedCluster(TestableDateTimeProvider dateTimeProvider, Transport }; } - public VirtualClusterTransport Connection => RequestHandler.Configuration.Connection as VirtualClusterTransport; + public VirtualClusterRequestInvoker Connection => RequestHandler.Configuration.Connection as VirtualClusterRequestInvoker; public NodePool ConnectionPool => RequestHandler.Configuration.NodePool; public ITransport RequestHandler => _exposingRequestPipeline?.RequestHandler; diff --git a/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs b/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs index b93bc7c..63df510 100644 --- a/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs +++ b/src/Elastic.Transport.VirtualizedCluster/Products/MockProductRegistration.cs @@ -9,7 +9,7 @@ namespace Elastic.Transport.VirtualizedCluster.Products; /// -/// Makes sure is mockable by providing a different sniff response based on the current +/// Makes sure is mockable by providing a different sniff response based on the current /// public abstract class MockProductRegistration { @@ -28,7 +28,7 @@ public abstract class MockProductRegistration public abstract byte[] CreateSniffResponseBytes(IReadOnlyList nodes, string stackVersion, string publishAddressOverride, bool returnFullyQualifiedDomainNames); /// - /// see uses this to determine if the current request is a sniff request and should follow + /// see uses this to determine if the current request is a sniff request and should follow /// the sniffing rules /// public abstract bool IsSniffRequest(RequestData requestData); diff --git a/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs b/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs index eba6840..560fbbf 100644 --- a/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs +++ b/src/Elastic.Transport/Components/NodePool/StaticNodePool.cs @@ -70,7 +70,7 @@ private void Initialize(IEnumerable nodes, DateTimeProvider dateTimeProvid } else if (scheme != node.Uri.Scheme) // TODO - Diagnostic event here - throw new ArgumentException("Trying to instantiate a connection pool with mixed URI Schemes"); + throw new ArgumentException("Trying to instantiate a node pool with mixed URI Schemes"); } InternalNodes = SortNodes(nodesProvided) diff --git a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs index 36f3b84..c6b798b 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs @@ -27,7 +27,7 @@ public class HttpRequestInvoker : IRequestInvoker { private static readonly string MissingConnectionLimitMethodError = $"Your target platform does not support {nameof(TransportConfiguration.ConnectionLimit)}" - + $" please set {nameof(TransportConfiguration.ConnectionLimit)} to -1 on your connection configuration/settings." + + $" please set {nameof(TransportConfiguration.ConnectionLimit)} to -1 on your configuration." + $" this will cause the {nameof(HttpClientHandler.MaxConnectionsPerServer)} not to be set on {nameof(HttpClientHandler)}"; private string _expectedCertificateFingerprint; diff --git a/src/Elastic.Transport/Configuration/TransportConfiguration.cs b/src/Elastic.Transport/Configuration/TransportConfiguration.cs index ae342e4..a0fb696 100644 --- a/src/Elastic.Transport/Configuration/TransportConfiguration.cs +++ b/src/Elastic.Transport/Configuration/TransportConfiguration.cs @@ -104,9 +104,9 @@ public TransportConfiguration(string cloudId, Base64ApiKey credentials, ProductR /// public TransportConfiguration( NodePool nodePool, - IRequestInvoker invoker = null, - Serializer serializer = null, - ProductRegistration productRegistration = null) + IRequestInvoker? invoker = null, + Serializer? serializer = null, + ProductRegistration? productRegistration = null) : base(nodePool, invoker, serializer, productRegistration) { } } @@ -162,7 +162,7 @@ public abstract class TransportConfigurationBase : ITransportConfiguration private UserAgent _userAgent; private string _certificateFingerprint; private bool _disableMetaHeader; - private readonly MetaHeaderProvider _metaHeaderProvider; + private readonly MetaHeaderProvider? _metaHeaderProvider; private readonly Func _statusCodeToResponseSuccess; @@ -173,7 +173,7 @@ public abstract class TransportConfigurationBase : ITransportConfiguration /// /// /// - protected TransportConfigurationBase(NodePool nodePool, IRequestInvoker requestInvoker, Serializer requestResponseSerializer, ProductRegistration productRegistration) + protected TransportConfigurationBase(NodePool nodePool, IRequestInvoker? requestInvoker, Serializer? requestResponseSerializer, ProductRegistration? productRegistration) { _nodePool = nodePool; _requestInvoker = requestInvoker ?? new HttpRequestInvoker(); diff --git a/src/Elastic.Transport/DistributedTransport.cs b/src/Elastic.Transport/DistributedTransport.cs index a911584..3aea1ef 100644 --- a/src/Elastic.Transport/DistributedTransport.cs +++ b/src/Elastic.Transport/DistributedTransport.cs @@ -27,7 +27,7 @@ public sealed class DistributedTransport : DistributedTransport - /// The connection settings to use for this transport + /// The configuration to use for this transport public DistributedTransport(TransportConfiguration configurationValues) : base(configurationValues, null, null) { } /// @@ -35,7 +35,7 @@ public DistributedTransport(TransportConfiguration configurationValues) : base(c /// different /// nodes /// - /// The connection settings to use for this transport + /// The configuration to use for this transport /// In charge of create a new pipeline, safe to pass null to use the default /// The date time proved to use, safe to pass null to use the default /// The memory stream provider to use, safe to pass null to use the default @@ -59,7 +59,7 @@ public class DistributedTransport : ITransport /// different /// nodes ///
- /// The connection settings to use for this transport + /// The configuration to use for this transport /// In charge of create a new pipeline, safe to pass null to use the default /// The date time proved to use, safe to pass null to use the default /// The memory stream provider to use, safe to pass null to use the default diff --git a/src/Elastic.Transport/Products/DefaultProductRegistration.cs b/src/Elastic.Transport/Products/DefaultProductRegistration.cs index 682f79c..03d2b17 100644 --- a/src/Elastic.Transport/Products/DefaultProductRegistration.cs +++ b/src/Elastic.Transport/Products/DefaultProductRegistration.cs @@ -88,7 +88,7 @@ public override Task>> SniffA throw new NotImplementedException(); /// - public override Tuple> Sniff(IRequestInvoker connection, bool forceSsl, RequestData requestData) => + public override Tuple> Sniff(IRequestInvoker requestInvoker, bool forceSsl, RequestData requestData) => throw new NotImplementedException(); /// @@ -96,11 +96,11 @@ public override RequestData CreatePingRequestData(Node node, RequestConfiguratio throw new NotImplementedException(); /// - public override Task PingAsync(IRequestInvoker connection, RequestData pingData, CancellationToken cancellationToken) => + public override Task PingAsync(IRequestInvoker requestInvoker, RequestData pingData, CancellationToken cancellationToken) => throw new NotImplementedException(); /// - public override TransportResponse Ping(IRequestInvoker connection, RequestData pingData) => + public override TransportResponse Ping(IRequestInvoker requestInvoker, RequestData pingData) => throw new NotImplementedException(); /// diff --git a/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs b/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs index cacd4e3..e233c23 100644 --- a/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs +++ b/src/Elastic.Transport/Products/Elasticsearch/ElasticsearchProductRegistration.cs @@ -184,9 +184,9 @@ public override async Task PingAsync(IRequestInvoker requestI } /// - public override TransportResponse Ping(IRequestInvoker connection, RequestData pingData) + public override TransportResponse Ping(IRequestInvoker requestInvoker, RequestData pingData) { - var response = connection.Request(pingData); + var response = requestInvoker.Request(pingData); return response; } diff --git a/src/Elastic.Transport/Products/ProductRegistration.cs b/src/Elastic.Transport/Products/ProductRegistration.cs index 1109e7a..da2c949 100644 --- a/src/Elastic.Transport/Products/ProductRegistration.cs +++ b/src/Elastic.Transport/Products/ProductRegistration.cs @@ -65,13 +65,13 @@ public abstract class ProductRegistration /// Provide an implementation that performs the ping directly using and the /// return by ///
- public abstract Task PingAsync(IRequestInvoker connection, RequestData pingData, CancellationToken cancellationToken); + public abstract Task PingAsync(IRequestInvoker requestInvoker, RequestData pingData, CancellationToken cancellationToken); /// /// Provide an implementation that performs the ping directly using and the /// return by /// - public abstract TransportResponse Ping(IRequestInvoker connection, RequestData pingData); + public abstract TransportResponse Ping(IRequestInvoker requestInvoker, RequestData pingData); /// /// Create an instance of that describes where and how to sniff the cluster using @@ -84,13 +84,13 @@ public abstract RequestData CreateSniffRequestData(Node node, IRequestConfigurat /// Provide an implementation that performs the sniff directly using and the /// return by /// - public abstract Task>> SniffAsync(IRequestInvoker connection, bool forceSsl, RequestData requestData, CancellationToken cancellationToken); + public abstract Task>> SniffAsync(IRequestInvoker requestInvoker, bool forceSsl, RequestData requestData, CancellationToken cancellationToken); /// /// Provide an implementation that performs the sniff directly using and the /// return by /// - public abstract Tuple> Sniff(IRequestInvoker connection, bool forceSsl, RequestData requestData); + public abstract Tuple> Sniff(IRequestInvoker requestInvoker, bool forceSsl, RequestData requestData); /// Allows certain nodes to be queried first to obtain sniffing information public abstract int SniffOrder(Node node); diff --git a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs index 3bb5ec0..d6b4e3e 100644 --- a/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs +++ b/tests/Elastic.Elasticsearch.IntegrationTests/DefaultCluster.cs @@ -28,8 +28,8 @@ public ITransport CreateClient(ITestOutputHelper output) => this.GetOrAddClient(cluster => { var nodes = NodesUris(); - var connectionPool = new StaticNodePool(nodes); - var settings = new TransportConfiguration(connectionPool, productRegistration: ElasticsearchProductRegistration.Default) + var nodePool = new StaticNodePool(nodes); + var settings = new TransportConfiguration(nodePool, productRegistration: ElasticsearchProductRegistration.Default) .RequestTimeout(TimeSpan.FromSeconds(5)) .OnRequestCompleted(d => { diff --git a/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs b/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs index 54ca749..fd8c162 100644 --- a/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/Http/ApiCompatibilityHeaderTests.cs @@ -20,7 +20,7 @@ public ApiCompatibilityHeaderTests(TransportTestServer instance) : base(instance [Fact] public async Task AddsExpectedVendorInformationForRestApiCompaitbility() { - var connection = new TestableHttpConnection(responseMessage => + var requestInvoker = new TrackingRequestInvoker(responseMessage => { responseMessage.RequestMessage.Content.Headers.ContentType.MediaType.Should().Be("application/vnd.elasticsearch+json"); var parameter = responseMessage.RequestMessage.Content.Headers.ContentType.Parameters.Single(); @@ -34,8 +34,8 @@ public async Task AddsExpectedVendorInformationForRestApiCompaitbility() contentTypeValues.Single().Replace(" ", "").Should().Be("application/vnd.elasticsearch+json;compatible-with=8"); }); - var connectionPool = new SingleNodePool(Server.Uri); - var config = new TransportConfiguration(connectionPool, connection, productRegistration: new ElasticsearchProductRegistration(typeof(Clients.Elasticsearch.ElasticsearchClient))); + var nodePool = new SingleNodePool(Server.Uri); + var config = new TransportConfiguration(nodePool, requestInvoker, productRegistration: new ElasticsearchProductRegistration(typeof(Clients.Elasticsearch.ElasticsearchClient))); var transport = new DistributedTransport(config); var response = await transport.PostAsync("/metaheader", PostData.String("{}")); diff --git a/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs b/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs index 66166eb..ba80aec 100644 --- a/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/Http/TransferEncodingChunckedTests.cs @@ -31,15 +31,15 @@ public TransferEncodingChunkedTests(TransportTestServer instance) : base(instanc private const string Path = "/chunked"; private ITransport Setup( - TestableHttpConnection connection, + TrackingRequestInvoker requestInvoker, Uri proxyAddress = null, bool? disableAutomaticProxyDetection = null, bool httpCompression = false, bool transferEncodingChunked = false ) { - var connectionPool = new SingleNodePool(Server.Uri); - var config = new TransportConfiguration(connectionPool, connection) + var nodePool = new SingleNodePool(Server.Uri); + var config = new TransportConfiguration(nodePool, requestInvoker) .TransferEncodingChunked(transferEncodingChunked) .EnableHttpCompression(httpCompression); config = disableAutomaticProxyDetection.HasValue @@ -56,36 +56,36 @@ private ITransport Setup( /// [Fact] public async Task HttpClientUseProxyShouldBeFalseWhenDisabledAutoProxyDetection() { - var connection = new TestableHttpConnection(); - var transport = Setup(connection, disableAutomaticProxyDetection: true); + var requestInvoker = new TrackingRequestInvoker(); + var transport = Setup(requestInvoker, disableAutomaticProxyDetection: true); var r = transport.Post(Path, Body); - connection.LastHttpClientHandler.UseProxy.Should().BeFalse(); + requestInvoker.LastHttpClientHandler.UseProxy.Should().BeFalse(); r.Body.Should().Be(BodyString); r = await transport.PostAsync(Path, Body, null, CancellationToken.None).ConfigureAwait(false); - connection.LastHttpClientHandler.UseProxy.Should().BeFalse(); + requestInvoker.LastHttpClientHandler.UseProxy.Should().BeFalse(); r.Body.Should().Be(BodyString); } [Fact] public async Task HttpClientUseProxyShouldBeTrueWhenEnabledAutoProxyDetection() { - var connection = new TestableHttpConnection(); - var transport = Setup(connection); + var requestInvoker = new TrackingRequestInvoker(); + var transport = Setup(requestInvoker); transport.Post(Path, Body); - connection.LastHttpClientHandler.UseProxy.Should().BeTrue(); + requestInvoker.LastHttpClientHandler.UseProxy.Should().BeTrue(); await transport.PostAsync(Path, Body, null, CancellationToken.None).ConfigureAwait(false); - connection.LastHttpClientHandler.UseProxy.Should().BeTrue(); + requestInvoker.LastHttpClientHandler.UseProxy.Should().BeTrue(); } [Fact] public async Task HttpClientUseTransferEncodingChunkedWhenTransferEncodingChunkedTrue() { - var connection = new TestableHttpConnection(responseMessage => + var requestInvoker = new TrackingRequestInvoker(responseMessage => { responseMessage.RequestMessage.Content.Headers.ContentLength.Should().BeNull(); }); - var transport = Setup(connection, transferEncodingChunked: true); + var transport = Setup(requestInvoker, transferEncodingChunked: true); transport.Post(Path, Body); await transport.PostAsync(Path, Body, null, CancellationToken.None).ConfigureAwait(false); @@ -93,11 +93,11 @@ [Fact] public async Task HttpClientUseTransferEncodingChunkedWhenTransferEncodin [Fact] public async Task HttpClientSetsContentLengthWhenTransferEncodingChunkedFalse() { - var connection = new TestableHttpConnection(responseMessage => + var trackingRequestInvoker = new TrackingRequestInvoker(responseMessage => { responseMessage.RequestMessage.Content.Headers.ContentLength.Should().HaveValue(); }); - var transport = Setup(connection, transferEncodingChunked: false); + var transport = Setup(trackingRequestInvoker, transferEncodingChunked: false); transport.Post(Path, Body); await transport.PostAsync(Path, Body, null, CancellationToken.None).ConfigureAwait(false); @@ -105,11 +105,11 @@ [Fact] public async Task HttpClientSetsContentLengthWhenTransferEncodingChunkedF [Fact] public async Task HttpClientSetsContentLengthWhenTransferEncodingChunkedHttpCompression() { - var connection = new TestableHttpConnection(responseMessage => + var trackingRequestInvoker = new TrackingRequestInvoker(responseMessage => { responseMessage.RequestMessage.Content.Headers.ContentLength.Should().HaveValue(); }); - var transport = Setup(connection, transferEncodingChunked: false, httpCompression: true); + var transport = Setup(trackingRequestInvoker, transferEncodingChunked: false, httpCompression: true); transport.Post(Path, Body); await transport.PostAsync(Path, Body, null, CancellationToken.None).ConfigureAwait(false); diff --git a/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs b/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs index 29cc079..da87aaa 100644 --- a/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs +++ b/tests/Elastic.Transport.IntegrationTests/OpenTelemetry/OpenTelemetryTests.cs @@ -30,9 +30,9 @@ public OpenTelemetryTests(TransportTestServer instance) : base(instance) { } [Fact] public async Task ElasticsearchTagsShouldBeSet_WhenUsingTheElasticsearchRegistration() { - var connection = new TestableHttpConnection(); - var connectionPool = new SingleNodePool(Server.Uri); - var config = new TransportConfiguration(connectionPool, connection, productRegistration: new ElasticsearchProductRegistration(typeof(Clients.Elasticsearch.ElasticsearchClient))); + var requestInvoker = new TrackingRequestInvoker(); + var nodePool = new SingleNodePool(Server.Uri); + var config = new TransportConfiguration(nodePool, requestInvoker, productRegistration: new ElasticsearchProductRegistration(typeof(Clients.Elasticsearch.ElasticsearchClient))); var transport = new DistributedTransport(config); var mre = new ManualResetEvent(false); diff --git a/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs b/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TrackingRequestInvoker.cs similarity index 90% rename from tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs rename to tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TrackingRequestInvoker.cs index 8118d0d..fce599b 100644 --- a/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TestableHttpConnection.cs +++ b/tests/Elastic.Transport.IntegrationTests/Plumbing/Stubs/TrackingRequestInvoker.cs @@ -9,7 +9,7 @@ namespace Elastic.Transport.IntegrationTests.Plumbing.Stubs; -public class TestableHttpConnection : IRequestInvoker +public class TrackingRequestInvoker : IRequestInvoker { private readonly Action _response; private TestableClientHandler _handler; @@ -17,9 +17,9 @@ public class TestableHttpConnection : IRequestInvoker public HttpClientHandler LastHttpClientHandler => (HttpClientHandler)_handler.InnerHandler; private readonly HttpRequestInvoker _requestInvoker; - public TestableHttpConnection(Action response) : this() => _response = response; + public TrackingRequestInvoker(Action response) : this() => _response = response; - public TestableHttpConnection() => + public TrackingRequestInvoker() => _requestInvoker = new HttpRequestInvoker((defaultHandler, _) => { _handler = new TestableClientHandler(defaultHandler, _response); diff --git a/tests/Elastic.Transport.Tests/Test.cs b/tests/Elastic.Transport.Tests/Test.cs index 43a9023..86ce4a7 100644 --- a/tests/Elastic.Transport.Tests/Test.cs +++ b/tests/Elastic.Transport.Tests/Test.cs @@ -16,11 +16,11 @@ public class Test public void Usage() { var pool = new StaticNodePool(new[] {new Node(new Uri("http://localhost:9200"))}); - var connection = new HttpRequestInvoker(); + var requestInvoker = new HttpRequestInvoker(); var serializer = LowLevelRequestResponseSerializer.Instance; var product = ElasticsearchProductRegistration.Default; - var settings = new TransportConfiguration(pool, connection, serializer, product); + var settings = new TransportConfiguration(pool, requestInvoker, serializer, product); var transport = new DistributedTransport(settings); var response = transport.Request(HttpMethod.GET, "/"); From 27eafdcb2e317ff3486db44a38447d2999a1d394 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Fri, 9 Feb 2024 15:55:17 +0100 Subject: [PATCH 8/9] address a few nullable violations --- .../Pipeline/DefaultResponseBuilder.cs | 25 +++++++++++-------- .../LowLevelRequestResponseSerializer.cs | 14 +++++------ .../TransportSerializerExtensions.cs | 20 ++++++--------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs b/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs index 6459fb1..3768370 100644 --- a/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs +++ b/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs @@ -14,9 +14,21 @@ using System.Threading.Tasks; using Elastic.Transport.Diagnostics; using Elastic.Transport.Extensions; +using static Elastic.Transport.ResponseBuilderDefaults; namespace Elastic.Transport; +internal static class ResponseBuilderDefaults +{ + public const int BufferSize = 81920; + + public static readonly Type[] SpecialTypes = + { + typeof(StringResponse), typeof(BytesResponse), typeof(VoidResponse), typeof(DynamicResponse) + }; + +} + /// /// A helper class that deals with handling how a is transformed to the requested /// implementation. This includes handling optionally buffering based on @@ -25,17 +37,10 @@ namespace Elastic.Transport; /// internal class DefaultResponseBuilder : ResponseBuilder where TError : ErrorResponse, new() { - private const int BufferSize = 81920; - private readonly bool _isEmptyError; public DefaultResponseBuilder() => _isEmptyError = typeof(TError) == typeof(EmptyError); - private static readonly Type[] SpecialTypes = - { - typeof(StringResponse), typeof(BytesResponse), typeof(VoidResponse), typeof(DynamicResponse) - }; - /// /// Create an instance of from /// @@ -150,7 +155,7 @@ private static ApiCallDetails Initialize(RequestData requestData, Exception exce } /// - /// + /// /// /// /// @@ -158,7 +163,7 @@ private static ApiCallDetails Initialize(RequestData requestData, Exception exce protected virtual bool RequiresErrorDeserialization(ApiCallDetails details, RequestData requestData) => false; /// - /// + /// /// /// /// @@ -179,7 +184,7 @@ protected virtual bool TryGetError(ApiCallDetails apiCallDetails, RequestData re } /// - /// + /// /// /// /// diff --git a/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs b/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs index 82f897b..36602fc 100644 --- a/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs +++ b/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs @@ -33,10 +33,10 @@ internal sealed class LowLevelRequestResponseSerializer : Serializer private IList BakedInConverters { get; } = new List { - { new ExceptionConverter() }, - { new ErrorCauseConverter() }, - { new ErrorConverter() }, - { new DynamicDictionaryConverter() } + new ExceptionConverter(), + new ErrorCauseConverter(), + new ErrorConverter(), + new DynamicDictionaryConverter() }; /// > @@ -46,7 +46,7 @@ public LowLevelRequestResponseSerializer() : this(null) { } /// > /// /// Add more default converters onto being used - public LowLevelRequestResponseSerializer(IEnumerable converters) + public LowLevelRequestResponseSerializer(IEnumerable? converters) { AdditionalConverters = converters != null ? new ReadOnlyCollection(converters.ToList()) @@ -75,7 +75,7 @@ public JsonSerializerOptions CreateSerializerOptions(SerializationFormatting for } - private static bool TryReturnDefault(Stream stream, out T deserialize) + private static bool TryReturnDefault(Stream? stream, out T deserialize) { deserialize = default; return stream == null || stream == Stream.Null || (stream.CanSeek && stream.Length == 0); @@ -88,7 +88,7 @@ public override object Deserialize(Type type, Stream stream) { if (TryReturnDefault(stream, out object deserialize)) return deserialize; - return JsonSerializer.Deserialize(stream, type, _none.Value); + return JsonSerializer.Deserialize(stream, type, _none.Value)!; } /// > diff --git a/src/Elastic.Transport/Components/Serialization/TransportSerializerExtensions.cs b/src/Elastic.Transport/Components/Serialization/TransportSerializerExtensions.cs index d3b215d..68c0c8e 100644 --- a/src/Elastic.Transport/Components/Serialization/TransportSerializerExtensions.cs +++ b/src/Elastic.Transport/Components/Serialization/TransportSerializerExtensions.cs @@ -31,16 +31,14 @@ public static byte[] SerializeToBytes( public static byte[] SerializeToBytes( this Serializer serializer, T data, - MemoryStreamFactory memoryStreamFactory, + MemoryStreamFactory? memoryStreamFactory = null, SerializationFormatting formatting = SerializationFormatting.None ) { memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory; - using (var ms = memoryStreamFactory.Create()) - { - serializer.Serialize(data, ms, formatting); - return ms.ToArray(); - } + using var ms = memoryStreamFactory.Create(); + serializer.Serialize(data, ms, formatting); + return ms.ToArray(); } /// @@ -65,15 +63,13 @@ public static string SerializeToString( public static string SerializeToString( this Serializer serializer, T data, - MemoryStreamFactory memoryStreamFactory, + MemoryStreamFactory? memoryStreamFactory = null, SerializationFormatting formatting = SerializationFormatting.None ) { memoryStreamFactory ??= TransportConfiguration.DefaultMemoryStreamFactory; - using (var ms = memoryStreamFactory.Create()) - { - serializer.Serialize(data, ms, formatting); - return ms.Utf8String(); - } + using var ms = memoryStreamFactory.Create(); + serializer.Serialize(data, ms, formatting); + return ms.Utf8String(); } } From 6cadc6cd0c892ee386f1cb12f936d0c2864b545f Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Fri, 9 Feb 2024 16:02:23 +0100 Subject: [PATCH 9/9] xmldocs fixes --- .../Components/TransportClient/HttpRequestInvoker.cs | 4 ++-- .../Requests/MetaData/ReflectionVersionInfo.cs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs index f8055d9..4e563d6 100644 --- a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs +++ b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs @@ -55,12 +55,12 @@ public HttpRequestInvoker(Func + /// public TResponse Request(RequestData requestData) where TResponse : TransportResponse, new() => RequestCoreAsync(false, requestData).EnsureCompleted(); - /// + /// public Task RequestAsync(RequestData requestData, CancellationToken cancellationToken) where TResponse : TransportResponse, new() => RequestCoreAsync(true, requestData, cancellationToken).AsTask(); diff --git a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs index f74b1b8..2ff9448 100644 --- a/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs +++ b/src/Elastic.Transport/Requests/MetaData/ReflectionVersionInfo.cs @@ -12,12 +12,13 @@ namespace Elastic.Transport; /// -/// +/// /// public sealed class ReflectionVersionInfo : VersionInfo { private static readonly SemVersion Empty = new(0, 0, 0); + /// The version of Elastic.Transport itself public static readonly string TransportVersion = Create().ToFullString(); private ReflectionVersionInfo(SemVersion version) : @@ -26,7 +27,7 @@ private ReflectionVersionInfo(SemVersion version) : } /// - /// + /// /// /// /// @@ -38,7 +39,7 @@ public static ReflectionVersionInfo Create() } /// - /// + /// /// /// ///