dotnet-cqrs/Svrnty.CQRS.Events/Storage/InMemorySubscriptionStore.cs

87 lines
3.1 KiB
C#

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;
/// <summary>
/// In-memory implementation of ISubscriptionStore for testing and development.
/// Thread-safe but data is lost on application restart.
/// </summary>
public sealed class InMemorySubscriptionStore : ISubscriptionStore
{
private readonly ConcurrentDictionary<string, EventSubscription> _subscriptions = new();
public Task CreateAsync(EventSubscription subscription, CancellationToken cancellationToken = default)
{
_subscriptions.TryAdd(subscription.SubscriptionId, subscription);
return Task.CompletedTask;
}
public Task<EventSubscription?> GetByIdAsync(string subscriptionId, CancellationToken cancellationToken = default)
{
_subscriptions.TryGetValue(subscriptionId, out var subscription);
return Task.FromResult(subscription);
}
public Task<List<EventSubscription>> GetBySubscriberIdAsync(string subscriberId, CancellationToken cancellationToken = default)
{
var result = _subscriptions.Values
.Where(s => s.SubscriberId == subscriberId)
.ToList();
return Task.FromResult(result);
}
public Task<List<EventSubscription>> 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<int> 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);
}
}