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;
///
/// Extensions for adding saga support to the CQRS pipeline.
///
public static class CqrsBuilderExtensions
{
///
/// Adds saga orchestration support to the CQRS pipeline.
///
/// The CQRS builder.
/// Optional configuration action.
/// The CQRS builder for chaining.
public static CqrsBuilder AddSagas(this CqrsBuilder builder, Action? configure = null)
{
var options = new SagaOptions();
configure?.Invoke(options);
builder.Services.Configure(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();
// Register default in-memory state store if not already registered
builder.Services.TryAddSingleton();
return builder;
}
///
/// Registers a saga type with the CQRS pipeline.
///
/// The saga type.
/// The saga data type.
/// The CQRS builder.
/// The CQRS builder for chaining.
public static CqrsBuilder AddSaga(this CqrsBuilder builder)
where TSaga : class, ISaga
where TData : class, ISagaData, new()
{
builder.Services.AddTransient();
builder.Services.AddTransient, TSaga>();
return builder;
}
///
/// Uses a custom saga state store implementation.
///
/// The state store implementation type.
/// The CQRS builder.
/// The CQRS builder for chaining.
public static CqrsBuilder UseSagaStateStore(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;
}
}