using System; using Svrnty.CQRS.Events.Abstractions.Storage; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Svrnty.CQRS.Events.Abstractions.Storage; /// /// Store for tracking read receipts (consumer acknowledgments of processed events). /// /// /// /// Purpose: /// Read receipts provide visibility into consumer progress through event streams. /// Unlike idempotency (which prevents duplicates), read receipts track progress. /// /// /// Use Cases: /// - Dashboard showing consumer lag/progress /// - Resuming from last processed position /// - Monitoring consumer health /// - Detecting stuck consumers /// /// public interface IReadReceiptStore { /// /// Records that a consumer has successfully processed an event. /// /// The consumer identifier. /// The name of the event stream. /// The unique event identifier. /// The event's offset/position in the stream. /// When the event was acknowledged. /// Cancellation token. Task AcknowledgeEventAsync( string consumerId, string streamName, string eventId, long offset, DateTimeOffset acknowledgedAt, CancellationToken cancellationToken = default); /// /// Gets the last acknowledged offset for a consumer on a specific stream. /// /// The consumer identifier. /// The name of the event stream. /// Cancellation token. /// The last acknowledged offset, or null if no receipts exist. Task GetLastAcknowledgedOffsetAsync( string consumerId, string streamName, CancellationToken cancellationToken = default); /// /// Gets statistics about a consumer's progress on a stream. /// /// The consumer identifier. /// The name of the event stream. /// Cancellation token. /// Consumer progress statistics. Task GetConsumerProgressAsync( string consumerId, string streamName, CancellationToken cancellationToken = default); /// /// Gets all consumers that are tracking a specific stream. /// /// The name of the event stream. /// Cancellation token. /// List of consumer IDs tracking this stream. Task> GetConsumersForStreamAsync( string streamName, CancellationToken cancellationToken = default); /// /// Cleans up old read receipts. /// /// Delete receipts older than this timestamp. /// Cancellation token. /// Number of receipts deleted. Task CleanupAsync( DateTimeOffset olderThan, CancellationToken cancellationToken = default); } /// /// Represents a consumer's progress on a specific stream. /// public sealed class ConsumerProgress { /// /// The consumer identifier. /// public required string ConsumerId { get; init; } /// /// The stream name. /// public required string StreamName { get; init; } /// /// The last acknowledged offset. /// public required long LastOffset { get; init; } /// /// When the last event was acknowledged. /// public required DateTimeOffset LastAcknowledgedAt { get; init; } /// /// Total number of events acknowledged. /// public required long TotalAcknowledged { get; init; } /// /// When the consumer first started tracking this stream. /// public DateTimeOffset? FirstAcknowledgedAt { get; init; } }