using System.Collections.Concurrent;
namespace ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms;
///
/// Persistence for across server restarts.
/// Operator-supplied state (EnabledState / AckedState /
/// ConfirmedState / ShelvingState + audit trail) persists; ActiveState is
/// recomputed from the live predicate on startup so operators never re-ack.
///
///
/// Stream E wires this to a SQL-backed store against the ScriptedAlarmState
/// table with audit logging through IAuditLogger.
/// Tests + local dev use .
///
public interface IAlarmStateStore
{
/// Loads the alarm state for a specific alarm identifier.
/// The alarm identifier.
/// Cancellation token.
/// The alarm state if found; otherwise null.
Task LoadAsync(string alarmId, CancellationToken ct);
/// Loads all alarm states from the store.
/// Cancellation token.
/// A collection of all alarm states.
Task> LoadAllAsync(CancellationToken ct);
/// Saves an alarm state to the store.
/// The alarm state to save.
/// Cancellation token.
/// A task representing the save operation.
Task SaveAsync(AlarmConditionState state, CancellationToken ct);
/// Removes an alarm state from the store.
/// The alarm identifier to remove.
/// Cancellation token.
/// A task representing the remove operation.
Task RemoveAsync(string alarmId, CancellationToken ct);
}
/// In-memory default — used by tests + by dev deployments without a SQL backend.
public sealed class InMemoryAlarmStateStore : IAlarmStateStore
{
private readonly ConcurrentDictionary _map
= new(StringComparer.Ordinal);
///
public Task LoadAsync(string alarmId, CancellationToken ct)
=> Task.FromResult(_map.TryGetValue(alarmId, out var v) ? v : null);
///
public Task> LoadAllAsync(CancellationToken ct)
=> Task.FromResult>(_map.Values.ToArray());
///
public Task SaveAsync(AlarmConditionState state, CancellationToken ct)
{
_map[state.AlarmId] = state;
return Task.CompletedTask;
}
///
public Task RemoveAsync(string alarmId, CancellationToken ct)
{
_map.TryRemove(alarmId, out _);
return Task.CompletedTask;
}
}