using System; using Svrnty.CQRS.Events.Abstractions.EventStore; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Svrnty.CQRS.Events.Abstractions.Models; namespace Svrnty.CQRS.Events.Abstractions.EventStore; /// /// Storage abstraction for event streams with message queue semantics. /// Supports both ephemeral (queue) and persistent (log) stream types. /// /// /// /// Ephemeral Streams (Phase 1): /// Events are enqueued and dequeued like a message queue. Events are deleted after acknowledgment. /// Supports multiple consumers with visibility tracking. /// /// /// Persistent Streams (Phase 2+): /// Events are appended to an append-only log. Events are never deleted (except by retention policy). /// Consumers track their position (offset) in the stream. /// /// public interface IEventStreamStore { // ======================================================================== // EPHEMERAL STREAM OPERATIONS (Message Queue Semantics) // ======================================================================== /// /// Enqueue an event to an ephemeral stream. /// /// The name of the stream. /// The event to enqueue. /// Cancellation token. /// A task representing the async operation. /// /// For ephemeral streams, this adds the event to a queue. /// The event will be delivered to consumers and then deleted after acknowledgment. /// Task EnqueueAsync( string streamName, ICorrelatedEvent @event, CancellationToken cancellationToken = default); /// /// Enqueue multiple events to an ephemeral stream in a batch. /// /// The name of the stream. /// The events to enqueue. /// Cancellation token. /// A task representing the async operation. Task EnqueueBatchAsync( string streamName, IEnumerable events, CancellationToken cancellationToken = default); /// /// Dequeue the next available event from an ephemeral stream for a specific consumer. /// /// The name of the stream. /// The consumer ID requesting the event. /// How long the event should be invisible to other consumers while processing. /// Cancellation token. /// The next event, or null if the queue is empty. /// /// /// The event becomes invisible to other consumers for the duration of the visibility timeout. /// The consumer must call to permanently remove the event, /// or to make it visible again (for retry). /// /// /// If the visibility timeout expires without acknowledgment, the event automatically becomes /// visible again for other consumers to process. /// /// Task DequeueAsync( string streamName, string consumerId, TimeSpan visibilityTimeout, CancellationToken cancellationToken = default); /// /// Acknowledge successful processing of an event, permanently removing it from the queue. /// /// The name of the stream. /// The event ID to acknowledge. /// The consumer ID acknowledging the event. /// Cancellation token. /// True if the event was acknowledged, false if not found or already acknowledged. /// /// After acknowledgment, the event is permanently deleted from the ephemeral stream. /// Task AcknowledgeAsync( string streamName, string eventId, string consumerId, CancellationToken cancellationToken = default); /// /// Negative acknowledge (NACK) an event, making it visible again for reprocessing. /// /// The name of the stream. /// The event ID to NACK. /// The consumer ID nacking the event. /// If true, make the event immediately available. If false, send to dead letter queue. /// Cancellation token. /// True if the event was nacked, false if not found. /// /// /// Use NACK when processing fails and the event should be retried. /// The event becomes immediately visible to other consumers if is true. /// /// /// If is false, the event is moved to a dead letter queue /// for manual inspection (useful after max retry attempts). /// /// Task NackAsync( string streamName, string eventId, string consumerId, bool requeue = true, CancellationToken cancellationToken = default); /// /// Get the approximate count of pending events in an ephemeral stream. /// /// The name of the stream. /// Cancellation token. /// The approximate number of events waiting to be processed. /// /// This count is approximate and may not reflect in-flight events being processed. /// Use for monitoring and metrics, not for critical business logic. /// Task GetPendingCountAsync( string streamName, CancellationToken cancellationToken = default); // ======================================================================== // PERSISTENT STREAM OPERATIONS (Event Log Semantics) - Phase 2+ // ======================================================================== /// /// Append an event to a persistent stream (append-only log). /// /// The name of the stream. /// The event to append. /// Cancellation token. /// The offset (position) assigned to this event in the stream. /// /// Phase 2 feature. For persistent streams, events are never deleted (except by retention policies). /// Events are assigned sequential offsets starting from 0. /// Task AppendAsync( string streamName, ICorrelatedEvent @event, CancellationToken cancellationToken = default); /// /// Read events from a persistent stream starting at a specific offset. /// /// The name of the stream. /// The offset to start reading from (inclusive). /// Maximum number of events to return. /// Cancellation token. /// List of events starting from the specified offset. /// /// Phase 2 feature. Used for catch-up subscriptions and event replay. /// Task> ReadStreamAsync( string streamName, long fromOffset, int maxCount, CancellationToken cancellationToken = default); /// /// Get the current length (number of events) in a persistent stream. /// /// The name of the stream. /// Cancellation token. /// The total number of events in the stream. /// /// Phase 2 feature. Used for monitoring and to detect consumer lag. /// Task GetStreamLengthAsync( string streamName, CancellationToken cancellationToken = default); /// /// Get metadata about a persistent stream. /// /// The name of the stream. /// Cancellation token. /// Stream metadata including length, retention info, and event timestamps. /// /// Phase 2 feature. Provides comprehensive information about stream state for monitoring, /// consumer lag detection, and retention policy verification. /// Task GetStreamMetadataAsync( string streamName, CancellationToken cancellationToken = default); // ======================================================================== // CONSUMER OFFSET TRACKING - Phase 6 (Monitoring & Health Checks) // ======================================================================== /// /// Get the current offset (position) of a consumer in a persistent stream. /// /// The name of the stream. /// The consumer ID. /// Cancellation token. /// The consumer's current offset, or 0 if no offset is stored. /// /// Phase 6 feature. Used for health checks to detect consumer lag and stalled consumers. /// Task GetConsumerOffsetAsync( string streamName, string consumerId, CancellationToken cancellationToken = default); /// /// Get the last time a consumer updated its offset in a persistent stream. /// /// The name of the stream. /// The consumer ID. /// Cancellation token. /// The last update time, or DateTimeOffset.MinValue if no offset is stored. /// /// Phase 6 feature. Used for health checks to detect stalled consumers (no progress for extended time). /// Task GetConsumerLastUpdateTimeAsync( string streamName, string consumerId, CancellationToken cancellationToken = default); /// /// Update a consumer's offset manually (for management operations). /// /// The name of the stream. /// The consumer ID. /// The new offset to set. /// Cancellation token. /// A task representing the async operation. /// /// Phase 6 feature. Used by management API to reset consumer positions. /// Use with caution as this can cause events to be reprocessed or skipped. /// Task UpdateConsumerOffsetAsync( string streamName, string consumerId, long newOffset, CancellationToken cancellationToken = default); }