dotnet-cqrs/Svrnty.CQRS.Sagas/CqrsBuilderExtensions.cs

83 lines
3.1 KiB
C#

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Svrnty.CQRS.Configuration;
using Svrnty.CQRS.Sagas.Abstractions;
using Svrnty.CQRS.Sagas.Abstractions.Persistence;
using Svrnty.CQRS.Sagas.Configuration;
using Svrnty.CQRS.Sagas.Persistence;
namespace Svrnty.CQRS.Sagas;
/// <summary>
/// Extensions for adding saga support to the CQRS pipeline.
/// </summary>
public static class CqrsBuilderExtensions
{
/// <summary>
/// Adds saga orchestration support to the CQRS pipeline.
/// </summary>
/// <param name="builder">The CQRS builder.</param>
/// <param name="configure">Optional configuration action.</param>
/// <returns>The CQRS builder for chaining.</returns>
public static CqrsBuilder AddSagas(this CqrsBuilder builder, Action<SagaOptions>? configure = null)
{
var options = new SagaOptions();
configure?.Invoke(options);
builder.Services.Configure<SagaOptions>(opt =>
{
opt.DefaultStepTimeout = options.DefaultStepTimeout;
opt.DefaultMaxRetries = options.DefaultMaxRetries;
opt.DefaultRetryDelay = options.DefaultRetryDelay;
opt.AutoCompensateOnFailure = options.AutoCompensateOnFailure;
opt.StalledSagaCheckInterval = options.StalledSagaCheckInterval;
opt.StepStalledTimeout = options.StepStalledTimeout;
});
// Store configuration
builder.Configuration.SetConfiguration(options);
// Register core saga services
builder.Services.TryAddSingleton<ISagaOrchestrator, SagaOrchestrator>();
// Register default in-memory state store if not already registered
builder.Services.TryAddSingleton<ISagaStateStore, InMemorySagaStateStore>();
return builder;
}
/// <summary>
/// Registers a saga type with the CQRS pipeline.
/// </summary>
/// <typeparam name="TSaga">The saga type.</typeparam>
/// <typeparam name="TData">The saga data type.</typeparam>
/// <param name="builder">The CQRS builder.</param>
/// <returns>The CQRS builder for chaining.</returns>
public static CqrsBuilder AddSaga<TSaga, TData>(this CqrsBuilder builder)
where TSaga : class, ISaga<TData>
where TData : class, ISagaData, new()
{
builder.Services.AddTransient<TSaga>();
builder.Services.AddTransient<ISaga<TData>, TSaga>();
return builder;
}
/// <summary>
/// Uses a custom saga state store implementation.
/// </summary>
/// <typeparam name="TStore">The state store implementation type.</typeparam>
/// <param name="builder">The CQRS builder.</param>
/// <returns>The CQRS builder for chaining.</returns>
public static CqrsBuilder UseSagaStateStore<TStore>(this CqrsBuilder builder)
where TStore : class, ISagaStateStore
{
// Remove existing registration
var descriptor = new ServiceDescriptor(typeof(ISagaStateStore), typeof(TStore), ServiceLifetime.Singleton);
builder.Services.Replace(descriptor);
return builder;
}
}