using Elsa.Expressions.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Services; using Elsa.Resilience.Endpoints.SimulateResponse; using Elsa.Resilience.Entities; using Elsa.Resilience.Modifiers; using Elsa.Resilience.Options; using Elsa.Resilience.Recorders; using Elsa.Resilience.Serialization; using Elsa.Resilience.StrategySources; using Elsa.Workflows; using Elsa.Workflows.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Elsa.Common.Serialization; namespace Elsa.Resilience.Features; public class ResilienceFeature(IModule module) : FeatureBase(module) { private Func _retryAttemptRecorder = sp => sp.GetRequiredService(); private Func _retryAttemptReader = sp => sp.GetRequiredService(); public ResilienceFeature AddResilienceStrategyType() where T : IResilienceStrategy { return AddResilienceStrategyType(typeof(T)); } public ResilienceFeature AddResilienceStrategyType(Type strategyType) { Services.Configure(options => options.StrategyTypes.Add(strategyType)); return this; } public ResilienceFeature WithActivityExecutionContextRetryAttemptRecorder() { return WithRetryAttemptRecorder() .WithRetryAttemptReader(); } public ResilienceFeature WithVoidRetryAttemptRecorder() { return WithRetryAttemptRecorder() .WithRetryAttemptReader(); } public ResilienceFeature WithRetryAttemptRecorder() => WithRetryAttemptRecorder(sp => (IRetryAttemptRecorder)ActivatorUtilities.CreateInstance(sp)!); public ResilienceFeature WithRetryAttemptReader() => WithRetryAttemptReader(sp => (IRetryAttemptReader)ActivatorUtilities.CreateInstance(sp)!); public ResilienceFeature WithRetryAttemptRecorder(Func recorder) { _retryAttemptRecorder = recorder; return this; } public ResilienceFeature WithRetryAttemptReader(Func reader) { _retryAttemptReader = reader; return this; } public override void Configure() { Module.AddFastEndpointsAssembly(); Services.Configure(options => { options.AddTypeAlias>("RetryAttemptRecordList"); }); Services.Configure(options => { options.RegisterTypeAlias(typeof(List), "RetryAttemptRecordList"); }); } public override void Apply() { Services.AddOptions(); Services.AddOptions(); Services.TryAddSingleton(TimeProvider.System); Services .AddSingleton() .AddSingleton() .AddSingleton() .AddScoped() .AddScoped() .AddScoped() .AddScoped() .AddSingleton(VoidRetryAttemptRecorder.Instance) .AddSingleton(VoidRetryAttemptReader.Instance) .AddScoped() .AddScoped() .AddScoped(_retryAttemptRecorder) .AddScoped(_retryAttemptReader) .AddHandlersFrom(); // Register transient exception detection infrastructure Services .AddSingleton() .AddSingleton(); } }