using System.Collections.Immutable; namespace HermesSocketServer.Store.Internal { public abstract class GroupSaveStore : IStore where K : class where V : class { protected readonly IDictionary _store; protected readonly IList _added; protected readonly IList _modified; protected readonly IList _deleted; protected readonly object _lock; public GroupSaveStore() { _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, V newValue); protected abstract void OnPostRemove(K key, V value); 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, V value) { if (key == null) return false; lock (_lock) { if (_store.TryGetValue(key, out V? oldValue)) { OnInitialModify(key, oldValue, value); _store[key] = value; if (!_added.Contains(key) && !_modified.Contains(key)) { _modified.Add(key); } return true; } } return false; } public bool Modify(K? key, Action modify) { if (key == null) return false; lock (_lock) { if (_store.TryGetValue(key, out V? value)) { modify(value); if (!_added.Contains(key) && !_modified.Contains(key)) { _modified.Add(key); } return true; } } return false; } public bool Remove(K? key, bool fromCascade = false) { if (key == null) return false; lock (_lock) { if (_store.TryGetValue(key, out var value)) { if (_store.Remove(key)) { OnPostRemove(key, value); if (!_added.Remove(key)) { _modified.Remove(key); if (!fromCascade && !_deleted.Contains(key)) { _deleted.Add(key); } } return true; } } } return false; } public bool Set(K? key, V value) { if (key == null) return false; lock (_lock) { if (_store.TryGetValue(key, out V? fetched)) { if (fetched != value) { OnInitialModify(key, fetched, value); _store[key] = value; if (!_added.Contains(key) && !_modified.Contains(key)) { _modified.Add(key); } return true; } } else { OnInitialAdd(key, value); _store.Add(key, value); if (!_deleted.Remove(key) && !_added.Contains(key)) { _added.Add(key); } return true; } } return false; } } }