using System; using Svrnty.CQRS.Events.Abstractions.EventStore; using Svrnty.CQRS.Events.Abstractions.Models; using Svrnty.CQRS.Events.Abstractions.Storage; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Svrnty.CQRS.Events.Abstractions.Subscriptions; /// /// Client interface for subscribing to event streams and consuming events. /// /// /// /// This is the primary interface consumers use to receive events from subscriptions. /// Supports async enumeration (IAsyncEnumerable) for streaming consumption. /// /// /// Usage Pattern: /// /// await foreach (var @event in client.SubscribeAsync("my-subscription", "consumer-1", ct)) /// { /// // Process event /// await ProcessEventAsync(@event); /// /// // Event is automatically acknowledged after successful processing /// // (unless manual acknowledgment mode is enabled) /// } /// /// /// public interface IEventSubscriptionClient { /// /// Subscribe to a subscription and receive events as an async stream. /// /// The subscription ID to consume from. /// Unique identifier for this consumer instance. /// Cancellation token to stop consuming. /// Async enumerable stream of events. /// /// /// Events are automatically acknowledged after being yielded, unless manual acknowledgment is enabled. /// The consumer is automatically registered when enumeration starts and unregistered when it stops. /// /// /// Subscription Modes: /// - Broadcast: Each consumer gets all events /// - Exclusive: Only one consumer gets each event (load balanced) /// - ConsumerGroup: Load balanced across group members /// - ReadReceipt: Requires explicit MarkAsRead call /// /// IAsyncEnumerable SubscribeAsync( string subscriptionId, string consumerId, CancellationToken cancellationToken = default); /// /// Subscribe with consumer metadata (hostname, version, etc.). /// /// The subscription ID to consume from. /// Unique identifier for this consumer instance. /// Optional metadata about this consumer. /// Cancellation token to stop consuming. /// Async enumerable stream of events. IAsyncEnumerable SubscribeAsync( string subscriptionId, string consumerId, Dictionary metadata, CancellationToken cancellationToken = default); /// /// Manually acknowledge an event (only needed if manual acknowledgment mode is enabled). /// /// The subscription ID. /// The event ID to acknowledge. /// The consumer ID acknowledging the event. /// Cancellation token. /// True if acknowledged, false if event not found or already acknowledged. Task AcknowledgeAsync( string subscriptionId, string eventId, string consumerId, CancellationToken cancellationToken = default); /// /// Negative acknowledge an event (NACK), marking it for redelivery or dead letter. /// /// The subscription ID. /// The event ID to NACK. /// The consumer ID nacking the event. /// If true, requeue for retry. If false, move to dead letter queue. /// Cancellation token. /// True if nacked, false if event not found. Task NackAsync( string subscriptionId, string eventId, string consumerId, bool requeue = true, CancellationToken cancellationToken = default); /// /// Get subscription details. /// /// The subscription ID. /// Cancellation token. /// The subscription configuration, or null if not found. Task GetSubscriptionAsync( string subscriptionId, CancellationToken cancellationToken = default); /// /// Get all active consumers for a subscription. /// /// The subscription ID. /// Cancellation token. /// List of active consumer information. Task> GetActiveConsumersAsync( string subscriptionId, CancellationToken cancellationToken = default); /// /// Unsubscribe a consumer from a subscription. /// /// The subscription ID. /// The consumer ID to unregister. /// Cancellation token. /// True if unregistered, false if not found. Task UnsubscribeAsync( string subscriptionId, string consumerId, CancellationToken cancellationToken = default); // ======================================================================== // Phase 3: Read Receipt API (Consumer Progress Tracking) // ======================================================================== /// /// Records a read receipt for an event, tracking consumer progress. /// /// The stream name. /// The consumer identifier. /// The event ID being acknowledged. /// The event's offset/position in the stream. /// Cancellation token. /// /// /// Read receipts differ from acknowledgments: /// - Acknowledgments are for subscription delivery tracking /// - Read receipts are for consumer progress/offset tracking /// /// /// Use this to track which events a consumer has successfully processed, /// allowing resume from last position and monitoring consumer lag. /// /// Task RecordReadReceiptAsync( string streamName, string consumerId, string eventId, long offset, CancellationToken cancellationToken = default); /// /// Gets the last acknowledged offset for a consumer on a stream. /// /// The stream name. /// The consumer identifier. /// Cancellation token. /// The last acknowledged offset, or null if no receipts exist. Task GetLastReadOffsetAsync( string streamName, string consumerId, CancellationToken cancellationToken = default); /// /// Gets consumer progress statistics for a stream. /// /// The stream name. /// The consumer identifier. /// Cancellation token. /// Consumer progress information, or null if no receipts exist. Task GetConsumerProgressAsync( string streamName, string consumerId, CancellationToken cancellationToken = default); /// /// Gets all consumers tracking a specific stream. /// /// The stream name. /// Cancellation token. /// List of consumer IDs tracking this stream. Task> GetStreamConsumersAsync( string streamName, CancellationToken cancellationToken = default); }