using System; using Svrnty.CQRS.Events.Abstractions.Schema; using Svrnty.CQRS.Events.Abstractions.Models; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Svrnty.CQRS.Events.Abstractions; namespace Svrnty.CQRS.Events.InMemory; /// /// In-memory implementation of for testing and development. /// /// /// This implementation stores schemas in memory and is suitable for: /// - Unit tests /// - Integration tests /// - Development environments /// - Single-instance deployments (no distributed systems) /// public sealed class InMemorySchemaStore : ISchemaStore { private readonly ConcurrentDictionary _schemas = new(); public Task StoreSchemaAsync( SchemaInfo schema, CancellationToken cancellationToken = default) { schema.Validate(); var key = GetKey(schema.EventType, schema.Version); if (!_schemas.TryAdd(key, schema)) { throw new InvalidOperationException( $"Schema for {schema.EventType} v{schema.Version} already exists"); } return Task.CompletedTask; } public Task GetSchemaAsync( string eventType, int version, CancellationToken cancellationToken = default) { var key = GetKey(eventType, version); _schemas.TryGetValue(key, out var schema); return Task.FromResult(schema); } public Task> GetSchemaHistoryAsync( string eventType, CancellationToken cancellationToken = default) { var schemas = _schemas.Values .Where(s => s.EventType == eventType) .OrderBy(s => s.Version) .ToList(); return Task.FromResult>(schemas); } public Task GetLatestVersionAsync( string eventType, CancellationToken cancellationToken = default) { var latestVersion = _schemas.Values .Where(s => s.EventType == eventType) .Select(s => (int?)s.Version) .DefaultIfEmpty(null) .Max(); return Task.FromResult(latestVersion); } public Task> GetAllEventTypesAsync( CancellationToken cancellationToken = default) { var eventTypes = _schemas.Values .Select(s => s.EventType) .Distinct() .OrderBy(x => x) .ToList(); return Task.FromResult>(eventTypes); } public Task SchemaExistsAsync( string eventType, int version, CancellationToken cancellationToken = default) { var key = GetKey(eventType, version); return Task.FromResult(_schemas.ContainsKey(key)); } /// /// Clears all schemas (for testing). /// public void Clear() { _schemas.Clear(); } private static string GetKey(string eventType, int version) => $"{eventType}:v{version}"; }