using System;
using Svrnty.CQRS.Events.Abstractions.Subscriptions;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Svrnty.CQRS.Events.Abstractions.Subscriptions;
///
/// Registry for tracking active consumers subscribed to event streams.
///
///
///
/// The consumer registry tracks which consumers are actively listening to which subscriptions.
/// This is different from which tracks subscription configurations.
///
///
/// Usage:
/// - A subscription defines WHAT to listen to (e.g., "user-events with filter X")
/// - A consumer is WHO is listening (e.g., "analytics-service-instance-1")
/// - Multiple consumers can listen to the same subscription (broadcast or consumer group)
///
///
public interface IConsumerRegistry
{
///
/// Register a consumer for a subscription.
///
/// The subscription ID.
/// The consumer ID.
/// Optional metadata about the consumer (e.g., hostname, version).
/// Cancellation token.
/// A task representing the async operation.
///
/// Registers the consumer as actively listening to the subscription.
/// If the consumer is already registered, updates the last heartbeat timestamp.
///
Task RegisterConsumerAsync(
string subscriptionId,
string consumerId,
Dictionary? metadata = null,
CancellationToken cancellationToken = default);
///
/// Unregister a consumer from a subscription.
///
/// The subscription ID.
/// The consumer ID.
/// Cancellation token.
/// True if the consumer was unregistered, false if not found.
///
/// Removes the consumer from the active consumer list.
/// Should be called when a consumer disconnects or stops listening.
///
Task UnregisterConsumerAsync(
string subscriptionId,
string consumerId,
CancellationToken cancellationToken = default);
///
/// Get all active consumers for a subscription.
///
/// The subscription ID.
/// Cancellation token.
/// List of active consumer IDs.
///
/// Returns consumers that are currently registered and have recent heartbeats.
/// Stale consumers (no heartbeat for timeout period) are automatically excluded.
///
Task> GetConsumersAsync(
string subscriptionId,
CancellationToken cancellationToken = default);
///
/// Get detailed information about all active consumers for a subscription.
///
/// The subscription ID.
/// Cancellation token.
/// List of consumer information including metadata and timestamps.
Task> GetConsumerInfoAsync(
string subscriptionId,
CancellationToken cancellationToken = default);
///
/// Update the heartbeat timestamp for a consumer.
///
/// The subscription ID.
/// The consumer ID.
/// Cancellation token.
/// True if the heartbeat was updated, false if consumer not found.
///
/// Consumers should send heartbeats periodically to indicate they're still active.
/// Consumers without recent heartbeats are considered stale and automatically removed.
///
Task HeartbeatAsync(
string subscriptionId,
string consumerId,
CancellationToken cancellationToken = default);
///
/// Check if a specific consumer is currently registered.
///
/// The subscription ID.
/// The consumer ID.
/// Cancellation token.
/// True if the consumer is active, false otherwise.
Task IsConsumerActiveAsync(
string subscriptionId,
string consumerId,
CancellationToken cancellationToken = default);
///
/// Remove stale consumers that haven't sent heartbeats within the timeout period.
///
/// Consider consumers stale if no heartbeat for this duration.
/// Cancellation token.
/// Number of stale consumers removed.
///
/// This should be called periodically by a background service to clean up disconnected consumers.
///
Task RemoveStaleConsumersAsync(
TimeSpan timeout,
CancellationToken cancellationToken = default);
}
///
/// Information about a registered consumer.
///
public sealed record ConsumerInfo
{
///
/// The consumer ID.
///
public required string ConsumerId { get; init; }
///
/// The subscription ID this consumer is subscribed to.
///
public required string SubscriptionId { get; init; }
///
/// When the consumer was first registered.
///
public required DateTimeOffset RegisteredAt { get; init; }
///
/// When the consumer last sent a heartbeat.
///
public required DateTimeOffset LastHeartbeat { get; init; }
///
/// Optional metadata about the consumer (e.g., hostname, version, process ID).
///
public IReadOnlyDictionary? Metadata { get; init; }
}