dotnet-cqrs/Svrnty.CQRS.Events.Abstractions/Storage/IIdempotencyStore.cs

69 lines
2.8 KiB
C#

using System;
using Svrnty.CQRS.Events.Abstractions.Storage;
using System.Threading;
using System.Threading.Tasks;
namespace Svrnty.CQRS.Events.Abstractions.Storage;
/// <summary>
/// Store for tracking processed events to prevent duplicate processing (exactly-once delivery semantics).
/// </summary>
public interface IIdempotencyStore
{
/// <summary>
/// Check if an event has already been processed by a specific consumer.
/// </summary>
/// <param name="consumerId">Unique identifier for the consumer</param>
/// <param name="eventId">Unique identifier for the event</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>True if the event was already processed, false otherwise</returns>
Task<bool> WasProcessedAsync(
string consumerId,
string eventId,
CancellationToken cancellationToken = default);
/// <summary>
/// Mark an event as processed by a specific consumer.
/// </summary>
/// <param name="consumerId">Unique identifier for the consumer</param>
/// <param name="eventId">Unique identifier for the event</param>
/// <param name="processedAt">Timestamp when the event was processed</param>
/// <param name="cancellationToken">Cancellation token</param>
Task MarkProcessedAsync(
string consumerId,
string eventId,
DateTimeOffset processedAt,
CancellationToken cancellationToken = default);
/// <summary>
/// Try to acquire an idempotency lock to prevent concurrent processing of the same event.
/// </summary>
/// <param name="idempotencyKey">Unique key for the operation (typically consumerId:eventId)</param>
/// <param name="lockDuration">How long the lock should be held</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>True if the lock was acquired, false if another process holds the lock</returns>
Task<bool> TryAcquireIdempotencyLockAsync(
string idempotencyKey,
TimeSpan lockDuration,
CancellationToken cancellationToken = default);
/// <summary>
/// Release an acquired idempotency lock.
/// </summary>
/// <param name="idempotencyKey">Unique key for the operation</param>
/// <param name="cancellationToken">Cancellation token</param>
Task ReleaseIdempotencyLockAsync(
string idempotencyKey,
CancellationToken cancellationToken = default);
/// <summary>
/// Clean up old processed event records to prevent unbounded growth.
/// </summary>
/// <param name="olderThan">Remove records processed before this timestamp</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Number of records removed</returns>
Task<int> CleanupAsync(
DateTimeOffset olderThan,
CancellationToken cancellationToken = default);
}