using System;
using Svrnty.CQRS.Events.Abstractions.Subscriptions;
using System.Collections.Generic;
using Svrnty.CQRS.Events.Abstractions;
namespace Svrnty.CQRS.Events.Subscriptions;
///
/// Default implementation of .
/// Represents a subscription configuration for consuming events from a stream.
///
public class Subscription : ISubscription
{
///
/// Initializes a new instance of the class.
///
/// Unique subscription identifier.
/// Name of the stream to subscribe to.
/// Subscription mode (Broadcast, Exclusive, etc.).
public Subscription(string subscriptionId, string streamName, SubscriptionMode mode = SubscriptionMode.Broadcast)
{
if (string.IsNullOrWhiteSpace(subscriptionId))
throw new ArgumentException("Subscription ID cannot be null or whitespace.", nameof(subscriptionId));
if (string.IsNullOrWhiteSpace(streamName))
throw new ArgumentException("Stream name cannot be null or whitespace.", nameof(streamName));
SubscriptionId = subscriptionId;
StreamName = streamName;
Mode = mode;
CreatedAt = DateTimeOffset.UtcNow;
IsActive = true;
VisibilityTimeout = TimeSpan.FromSeconds(30); // Default 30 seconds
}
///
public string SubscriptionId { get; }
///
public string StreamName { get; }
///
public SubscriptionMode Mode { get; set; }
///
public HashSet? EventTypeFilter { get; set; }
///
public bool IsActive { get; set; }
///
public DateTimeOffset CreatedAt { get; }
///
public string? Description { get; set; }
///
public int? MaxConcurrentConsumers { get; set; }
///
public TimeSpan VisibilityTimeout { get; set; }
///
public IReadOnlyDictionary? Metadata { get; set; }
// ========================================================================
// Phase 5: Schema Evolution Support
// ========================================================================
///
public bool EnableUpcasting { get; set; }
///
public int? TargetEventVersion { get; set; }
///
/// Validates the subscription configuration.
///
/// Thrown if configuration is invalid.
public void Validate()
{
if (string.IsNullOrWhiteSpace(SubscriptionId))
throw new InvalidOperationException("Subscription ID cannot be null or whitespace.");
if (string.IsNullOrWhiteSpace(StreamName))
throw new InvalidOperationException("Stream name cannot be null or whitespace.");
if (VisibilityTimeout <= TimeSpan.Zero)
throw new InvalidOperationException($"Visibility timeout must be positive. Got: {VisibilityTimeout}");
if (MaxConcurrentConsumers.HasValue && MaxConcurrentConsumers.Value <= 0)
throw new InvalidOperationException($"MaxConcurrentConsumers must be positive if set. Got: {MaxConcurrentConsumers}");
// Validate mode-specific constraints
if (Mode == SubscriptionMode.ConsumerGroup && MaxConcurrentConsumers.HasValue && MaxConcurrentConsumers.Value == 1)
{
throw new InvalidOperationException(
"ConsumerGroup mode with MaxConcurrentConsumers=1 is inefficient. Use Exclusive mode instead.");
}
}
}