|
- using Campaign_Tracker.Server.Seed.Models;
-
- namespace Campaign_Tracker.Server.Seed;
-
- public sealed class InMemorySeedDataStore : ISeedDataStore
- {
- private readonly object _sync = new();
- private readonly SeedDataSnapshot _snapshot = new();
-
- public Task UpsertSeedDataAsync(SeedDataSet seedData, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- lock (_sync)
- {
- UpsertMissing(_snapshot.ReferenceValues, seedData.ReferenceValues, Clone);
- UpsertMissing(_snapshot.RequiredFieldRules, seedData.RequiredFieldRules, Clone);
- UpsertMissing(_snapshot.EscalationRules, seedData.EscalationRules, Clone);
- }
-
- return Task.CompletedTask;
- }
-
- public Task<IReadOnlyList<ReferenceValue>> GetReferenceValuesAsync(CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- lock (_sync)
- {
- return Task.FromResult<IReadOnlyList<ReferenceValue>>(
- _snapshot.ReferenceValues.Select(Clone).ToArray());
- }
- }
-
- public Task<IReadOnlyList<RequiredFieldRule>> GetRequiredFieldRulesAsync(CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- lock (_sync)
- {
- return Task.FromResult<IReadOnlyList<RequiredFieldRule>>(
- _snapshot.RequiredFieldRules.Select(Clone).ToArray());
- }
- }
-
- public Task<IReadOnlyList<EscalationRule>> GetEscalationRulesAsync(CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- lock (_sync)
- {
- return Task.FromResult<IReadOnlyList<EscalationRule>>(
- _snapshot.EscalationRules.Select(Clone).ToArray());
- }
- }
-
- public Task SaveReferenceValueAsync(ReferenceValue referenceValue, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- lock (_sync)
- {
- ReplaceBySeedKey(_snapshot.ReferenceValues, referenceValue, Clone);
- }
-
- return Task.CompletedTask;
- }
-
- public Task SaveRequiredFieldRuleAsync(RequiredFieldRule rule, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- lock (_sync)
- {
- ReplaceBySeedKey(_snapshot.RequiredFieldRules, rule, Clone);
- }
-
- return Task.CompletedTask;
- }
-
- public Task SaveEscalationRuleAsync(EscalationRule rule, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- lock (_sync)
- {
- ReplaceBySeedKey(_snapshot.EscalationRules, rule, Clone);
- }
-
- return Task.CompletedTask;
- }
-
- internal static void UpsertMissing<T>(
- List<T> target,
- IEnumerable<T> defaults,
- Func<T, T> clone)
- where T : class
- {
- foreach (var item in defaults)
- {
- var key = GetSeedKey(item);
- if (target.Any(existing => SameSeedKey(GetSeedKey(existing), key)))
- {
- continue;
- }
-
- target.Add(clone(item));
- }
- }
-
- internal static void ReplaceBySeedKey<T>(
- List<T> target,
- T item,
- Func<T, T> clone)
- where T : class
- {
- var key = GetSeedKey(item);
- var existingIndex = target.FindIndex(existing => SameSeedKey(GetSeedKey(existing), key));
- if (existingIndex >= 0)
- {
- target[existingIndex] = clone(item);
- }
- else
- {
- target.Add(clone(item));
- }
- }
-
- internal static ReferenceValue Clone(ReferenceValue value) => new()
- {
- Id = value.Id,
- SeedKey = value.SeedKey,
- Category = value.Category,
- Name = value.Name,
- Description = value.Description,
- Value = value.Value,
- Source = value.Source,
- IsActive = value.IsActive,
- CreatedAt = value.CreatedAt,
- UpdatedAt = value.UpdatedAt,
- };
-
- internal static RequiredFieldRule Clone(RequiredFieldRule rule) => new()
- {
- Id = rule.Id,
- SeedKey = rule.SeedKey,
- Name = rule.Name,
- Description = rule.Description,
- EntityType = rule.EntityType,
- FieldPath = rule.FieldPath,
- ReadinessFeatureKey = rule.ReadinessFeatureKey,
- IsRequired = rule.IsRequired,
- Source = rule.Source,
- IsActive = rule.IsActive,
- CreatedAt = rule.CreatedAt,
- UpdatedAt = rule.UpdatedAt,
- };
-
- internal static EscalationRule Clone(EscalationRule rule) => new()
- {
- Id = rule.Id,
- SeedKey = rule.SeedKey,
- Name = rule.Name,
- Description = rule.Description,
- Scenario = rule.Scenario,
- TriggerCondition = rule.TriggerCondition,
- Action = rule.Action,
- MilestoneBasis = rule.MilestoneBasis,
- AlertWindow = rule.AlertWindow,
- Priority = rule.Priority,
- Source = rule.Source,
- IsActive = rule.IsActive,
- CreatedAt = rule.CreatedAt,
- UpdatedAt = rule.UpdatedAt,
- };
-
- private static string GetSeedKey<T>(T item) where T : class =>
- item switch
- {
- ReferenceValue value => value.SeedKey,
- RequiredFieldRule rule => rule.SeedKey,
- EscalationRule rule => rule.SeedKey,
- _ => throw new InvalidOperationException($"Unsupported seed item type {typeof(T).Name}."),
- };
-
- private static bool SameSeedKey(string left, string right) =>
- string.Equals(left, right, StringComparison.OrdinalIgnoreCase);
-
- internal sealed class SeedDataSnapshot
- {
- public List<ReferenceValue> ReferenceValues { get; init; } = [];
- public List<RequiredFieldRule> RequiredFieldRules { get; init; } = [];
- public List<EscalationRule> EscalationRules { get; init; } = [];
- }
- }
|