dotnet-cqrs/Svrnty.CQRS.Events/InMemory/InMemorySchemaStore.cs

110 lines
3.1 KiB
C#

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;
/// <summary>
/// In-memory implementation of <see cref="ISchemaStore"/> for testing and development.
/// </summary>
/// <remarks>
/// This implementation stores schemas in memory and is suitable for:
/// - Unit tests
/// - Integration tests
/// - Development environments
/// - Single-instance deployments (no distributed systems)
/// </remarks>
public sealed class InMemorySchemaStore : ISchemaStore
{
private readonly ConcurrentDictionary<string, SchemaInfo> _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<SchemaInfo?> 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<IReadOnlyList<SchemaInfo>> GetSchemaHistoryAsync(
string eventType,
CancellationToken cancellationToken = default)
{
var schemas = _schemas.Values
.Where(s => s.EventType == eventType)
.OrderBy(s => s.Version)
.ToList();
return Task.FromResult<IReadOnlyList<SchemaInfo>>(schemas);
}
public Task<int?> 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<IReadOnlyList<string>> GetAllEventTypesAsync(
CancellationToken cancellationToken = default)
{
var eventTypes = _schemas.Values
.Select(s => s.EventType)
.Distinct()
.OrderBy(x => x)
.ToList();
return Task.FromResult<IReadOnlyList<string>>(eventTypes);
}
public Task<bool> SchemaExistsAsync(
string eventType,
int version,
CancellationToken cancellationToken = default)
{
var key = GetKey(eventType, version);
return Task.FromResult(_schemas.ContainsKey(key));
}
/// <summary>
/// Clears all schemas (for testing).
/// </summary>
public void Clear()
{
_schemas.Clear();
}
private static string GetKey(string eventType, int version) => $"{eventType}:v{version}";
}