using System; using SubscriptionStatusEnum = Svrnty.CQRS.Events.Abstractions.Subscriptions.SubscriptionStatus; using Svrnty.CQRS.Events.Abstractions.Subscriptions; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Svrnty.CQRS.Events.Abstractions; using Svrnty.CQRS.Events.Abstractions.Models; namespace Svrnty.CQRS.Events.Storage; /// /// In-memory implementation of ISubscriptionStore for testing and development. /// Thread-safe but data is lost on application restart. /// public sealed class InMemorySubscriptionStore : ISubscriptionStore { private readonly ConcurrentDictionary _subscriptions = new(); public Task CreateAsync(EventSubscription subscription, CancellationToken cancellationToken = default) { _subscriptions.TryAdd(subscription.SubscriptionId, subscription); return Task.CompletedTask; } public Task GetByIdAsync(string subscriptionId, CancellationToken cancellationToken = default) { _subscriptions.TryGetValue(subscriptionId, out var subscription); return Task.FromResult(subscription); } public Task> GetBySubscriberIdAsync(string subscriberId, CancellationToken cancellationToken = default) { var result = _subscriptions.Values .Where(s => s.SubscriberId == subscriberId) .ToList(); return Task.FromResult(result); } public Task> FindByCorrelationIdAsync(string correlationId, CancellationToken cancellationToken = default) { var result = _subscriptions.Values .Where(s => s.CorrelationId == correlationId) .Where(s => s.Status == SubscriptionStatus.Active && !s.IsExpired) .ToList(); return Task.FromResult(result); } public Task UpdateAsync(EventSubscription subscription, CancellationToken cancellationToken = default) { // In-memory store: the object is already updated by reference // Just ensure it's in the dictionary _subscriptions.TryAdd(subscription.SubscriptionId, subscription); return Task.CompletedTask; } public Task DeleteAsync(string subscriptionId, CancellationToken cancellationToken = default) { _subscriptions.TryRemove(subscriptionId, out _); return Task.CompletedTask; } public Task DeleteOldSubscriptionsAsync(DateTimeOffset olderThan, CancellationToken cancellationToken = default) { var toDelete = _subscriptions.Values .Where(s => s.CompletedAt.HasValue && s.CompletedAt.Value < olderThan) .Where(s => s.Status != SubscriptionStatus.Active) .Select(s => s.SubscriptionId) .ToList(); int deletedCount = 0; foreach (var subscriptionId in toDelete) { if (_subscriptions.TryRemove(subscriptionId, out _)) { deletedCount++; } } return Task.FromResult(deletedCount); } }