dotnet-cqrs/Svrnty.CQRS.Events.Abstractions/Sagas/ISagaStateStore.cs

121 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Svrnty.CQRS.Events.Abstractions.Sagas;
/// <summary>
/// Persistent storage for saga state.
/// </summary>
public interface ISagaStateStore
{
/// <summary>
/// Save saga state.
/// </summary>
/// <param name="state">The saga state to save.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task SaveStateAsync(SagaStateSnapshot state, CancellationToken cancellationToken = default);
/// <summary>
/// Load saga state.
/// </summary>
/// <param name="sagaId">The saga ID.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The saga state, or null if not found.</returns>
Task<SagaStateSnapshot?> LoadStateAsync(string sagaId, CancellationToken cancellationToken = default);
/// <summary>
/// Get all sagas for a correlation ID.
/// </summary>
/// <param name="correlationId">The correlation ID.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>List of saga states.</returns>
Task<List<SagaStateSnapshot>> GetByCorrelationIdAsync(
string correlationId,
CancellationToken cancellationToken = default);
/// <summary>
/// Get sagas by state.
/// </summary>
/// <param name="state">The saga state to filter by.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>List of saga states.</returns>
Task<List<SagaStateSnapshot>> GetByStateAsync(
SagaState state,
CancellationToken cancellationToken = default);
/// <summary>
/// Delete saga state.
/// </summary>
/// <param name="sagaId">The saga ID to delete.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task DeleteStateAsync(string sagaId, CancellationToken cancellationToken = default);
}
/// <summary>
/// Snapshot of saga state for persistence.
/// </summary>
public sealed record SagaStateSnapshot
{
/// <summary>
/// Saga instance ID.
/// </summary>
public required string SagaId { get; init; }
/// <summary>
/// Correlation ID.
/// </summary>
public required string CorrelationId { get; init; }
/// <summary>
/// Saga type name.
/// </summary>
public required string SagaName { get; init; }
/// <summary>
/// Current state.
/// </summary>
public SagaState State { get; init; }
/// <summary>
/// Current step index.
/// </summary>
public int CurrentStep { get; init; }
/// <summary>
/// Total number of steps.
/// </summary>
public int TotalSteps { get; init; }
/// <summary>
/// Completed steps (for compensation tracking).
/// </summary>
public List<string> CompletedSteps { get; init; } = new();
/// <summary>
/// When the saga started.
/// </summary>
public DateTimeOffset StartedAt { get; init; }
/// <summary>
/// When the saga was last updated.
/// </summary>
public DateTimeOffset LastUpdated { get; init; }
/// <summary>
/// When the saga completed (if completed).
/// </summary>
public DateTimeOffset? CompletedAt { get; init; }
/// <summary>
/// Error message (if failed).
/// </summary>
public string? ErrorMessage { get; init; }
/// <summary>
/// Saga data (serialized as JSON or similar).
/// </summary>
public Dictionary<string, object> Data { get; init; } = new();
}