From c97282f7d533e94f48467dd833b33b8fbd6e70de Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 9 Dec 2023 20:44:11 +0100 Subject: [PATCH] Remove ApiHttpMessageHandler and update ElsaClient configuration The ApiHttpMessageHandler and the related configuration in ElsaClientOptions have been removed. The configuration for creating Api clients in DependencyInjectionExtensions has been updated to handle these changes. This includes the addition of a retry policy in case of transient HTTP error and changing the way clients are created to use the HttpClientFactory directly. --- .../Elsa.Api.Client/Elsa.Api.Client.csproj | 27 ++++++++++------- .../DependencyInjectionExtensions.cs | 30 +++++++++---------- .../ApiHttpMessageHandler.cs | 19 ------------ .../Options/ElsaClientOptions.cs | 8 ----- .../Services/ElsaClientFactory.cs | 19 ------------ 5 files changed, 30 insertions(+), 73 deletions(-) delete mode 100644 src/clients/Elsa.Api.Client/HttpMessageHandlers/ApiHttpMessageHandler.cs delete mode 100644 src/clients/Elsa.Api.Client/Services/ElsaClientFactory.cs diff --git a/src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj b/src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj index a4030f0fa..aaaec27c0 100644 --- a/src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj +++ b/src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj @@ -1,10 +1,10 @@ - - - + + + + - netstandard2.1 Provides HTTP clients for the Elsa Workflows REST API. @@ -12,17 +12,22 @@ - + + + - + + + - + - - - + + + + - + diff --git a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs index 5c58a6565..d3864079a 100644 --- a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs +++ b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs @@ -2,9 +2,8 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Api.Client.Contracts; using Elsa.Api.Client.Converters; -using Elsa.Api.Client.HttpMessageHandlers; using Elsa.Api.Client.Options; -using Elsa.Api.Client.Resources.ActivityDescriptorOptions.Contracts; +using Elsa.Api.Client.Resources.ActivityDescriptorOptions.Contracts; using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; using Elsa.Api.Client.Resources.ActivityExecutions.Contracts; using Elsa.Api.Client.Resources.Features.Contracts; @@ -21,6 +20,7 @@ using Elsa.Api.Client.Services; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Polly; using Refit; namespace Elsa.Api.Client.Extensions; @@ -38,11 +38,9 @@ public static class DependencyInjectionExtensions { var builderOptions = new ElsaClientBuilderOptions(); configureBuilderOptions?.Invoke(builderOptions); - - services.Configure(configureOptions ?? (_ => { })); - services.AddScoped(); - services.AddScoped(); + services.Configure(configureOptions ?? (_ => { })); + services.AddScoped(); services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); @@ -68,18 +66,22 @@ public static class DependencyInjectionExtensions /// The type representing the API. public static void AddApi(this IServiceCollection services, ElsaClientBuilderOptions? httpClientBuilderOptions = default) where T : class { - var builder = services.AddRefitClient(CreateRefitSettings).ConfigureHttpClient(ConfigureElsaApiHttpClient); + var builder = services.AddRefitClient(CreateRefitSettings, typeof(T).Name).ConfigureHttpClient(ConfigureElsaApiHttpClient); httpClientBuilderOptions?.ConfigureHttpClientBuilder?.Invoke(builder); + builder.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)))); } - + /// /// Creates an API client for the specified API type. /// public static T CreateApi(this IServiceProvider serviceProvider, Uri baseAddress) where T : class { - return RestService.For(baseAddress.ToString(), CreateRefitSettings(serviceProvider)); + var httpClientFactory = serviceProvider.GetRequiredService(); + var httpClient = httpClientFactory.CreateClient(typeof(T).Name); + httpClient.BaseAddress = baseAddress; + return CreateApi(serviceProvider, httpClient); } - + /// /// Creates an API client for the specified API type. /// @@ -105,18 +107,14 @@ public static class DependencyInjectionExtensions PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }; - var elsaClientOptions = serviceProvider.GetRequiredService>().Value; - serializerOptions.Converters.Add(new JsonStringEnumConverter()); serializerOptions.Converters.Add(new VersionOptionsJsonConverter()); var settings = new RefitSettings { ContentSerializer = new SystemTextJsonContentSerializer(serializerOptions), - HttpMessageHandlerFactory = () => elsaClientOptions.HttpMessageHandlerFactory(serviceProvider) - }; - + }; + return settings; } - } \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/HttpMessageHandlers/ApiHttpMessageHandler.cs b/src/clients/Elsa.Api.Client/HttpMessageHandlers/ApiHttpMessageHandler.cs deleted file mode 100644 index 84bc5fd03..000000000 --- a/src/clients/Elsa.Api.Client/HttpMessageHandlers/ApiHttpMessageHandler.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Elsa.Api.Client.Contracts; -using Microsoft.Extensions.DependencyInjection; - -namespace Elsa.Api.Client.HttpMessageHandlers; - -/// -/// An HTTP message handler that delegates its processing to another instance provided by an . -/// -public class ApiHttpMessageHandler : DelegatingHandler -{ - /// - public ApiHttpMessageHandler(IServiceProvider serviceProvider) - { - var provider = serviceProvider.GetService(); - - if (provider != null) - InnerHandler = provider.GetHandler(); - } -} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Options/ElsaClientOptions.cs b/src/clients/Elsa.Api.Client/Options/ElsaClientOptions.cs index afea1c581..6ed518720 100644 --- a/src/clients/Elsa.Api.Client/Options/ElsaClientOptions.cs +++ b/src/clients/Elsa.Api.Client/Options/ElsaClientOptions.cs @@ -1,6 +1,3 @@ -using Elsa.Api.Client.HttpMessageHandlers; -using Microsoft.Extensions.DependencyInjection; - namespace Elsa.Api.Client.Options; /// @@ -22,9 +19,4 @@ public class ElsaClientOptions /// Gets or sets a delegate that can be used to configure the HTTP client. /// public Action? ConfigureHttpClient { get; set; } - - /// - /// Gets or sets a delegate that can be used to configure the HTTP client message handler. - /// - public Func HttpMessageHandlerFactory { get; set; } = sp => sp.GetRequiredService(); } \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Services/ElsaClientFactory.cs b/src/clients/Elsa.Api.Client/Services/ElsaClientFactory.cs deleted file mode 100644 index 70af8a786..000000000 --- a/src/clients/Elsa.Api.Client/Services/ElsaClientFactory.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Elsa.Api.Client.Contracts; -using Elsa.Api.Client.Extensions; -using Elsa.Api.Client.Options; -using JetBrains.Annotations; -using Microsoft.Extensions.DependencyInjection; - -namespace Elsa.Api.Client.Services; - -/// -[PublicAPI] -public class ElsaClientFactory : IElsaClientFactory -{ - /// - public IElsaClient CreateClient(Action configureOptions, Action? configureHttpClientBuilder = default) - { - var services = new ServiceCollection().AddElsaClient(configureOptions, configureHttpClientBuilder).BuildServiceProvider(); - return services.GetRequiredService(); - } -} \ No newline at end of file