using System.Collections.Immutable; namespace HermesSocketServer.Store { public abstract class GroupSaveStore : IStore where K : class where V : class { private readonly Serilog.ILogger _logger; protected readonly IDictionary _store; protected readonly IList _added; protected readonly IList _modified; protected readonly IList _deleted; protected readonly object _lock; public GroupSaveStore(Serilog.ILogger logger) { _logger = logger; _store = new Dictionary(); _added = new List(); _modified = new List(); _deleted = new List(); _lock = new object(); } public abstract Task Load(); protected abstract void OnInitialAdd(K key, V value); protected abstract void OnInitialModify(K key, V value); protected abstract void OnInitialRemove(K key); public abstract Task Save(); public V? Get(K key) { lock (_lock) { if (_store.TryGetValue(key, out var value)) return value; } return null; } public IDictionary Get() { lock (_lock) { return _store.ToImmutableDictionary(); } } public bool Modify(K? key, Action action) { if (key == null) return false; lock (_lock) { if (_store.TryGetValue(key, out V? value)) { if (value == null) return false; action(value); if (!_added.Contains(key) && !_modified.Contains(key)) { _modified.Add(key); _logger.Information($"added key to _modified {key}"); } OnInitialModify(key, value); return true; } } return false; } public void Remove(K? key) { if (key == null) return; lock (_lock) { if (_store.Remove(key)) { _logger.Information($"removed key from _deleted {key}"); OnInitialRemove(key); if (!_added.Remove(key)) { _modified.Remove(key); _logger.Information($"removed key from _added & _modified {key}"); if (!_deleted.Contains(key)) { _deleted.Add(key); _logger.Information($"added key to _deleted {key}"); } } } } } public bool Set(K? key, V? value) { if (key == null || value == null) return false; lock (_lock) { if (_store.TryGetValue(key, out V? fetched)) { if (fetched != value) { OnInitialModify(key, value); _store[key] = value; if (!_added.Contains(key) && !_modified.Contains(key)) { _modified.Add(key); _logger.Information($"added key to _modified {key}"); } return true; } } else { OnInitialAdd(key, value); _store.Add(key, value); if (!_deleted.Remove(key) && !_added.Contains(key)) { _added.Add(key); _logger.Information($"added key to _added {key}"); } return true; } } return false; } } }