public Func <Key, ValueTask <T> > CreateIndexMany <Key>(Func <T, IEnumerable <Key> > keySelector) { keySelector.NotNull(nameof(keySelector)); var index = new AtomicDictionary <Key, T>(); _upserters.Add(async transaction => { foreach (var key in keySelector(transaction.Item)) { index[key] = transaction.Item; } }); _deleters.Add(async item => { foreach (var key in keySelector(item)) { index.TryRemove(key); } }); return(async key => { await Initialize(); return index.TryGetValue(key, out var item) ? item : default; }); }
public Func <Key, ValueTask <T> > CreatePrimaryKey <Key>(Expression <Func <T, Key> > keySelectorExpression) { keySelectorExpression.NotNull(nameof(keySelectorExpression)); if (!_primaryKeyCreated.TrySet(true)) { throw new Exception("Primary Key already exists"); } var keySelector = keySelectorExpression.Compile(); var index = new AtomicDictionary <Key, T>(); _items = index.Values; _upserters.Add(async transaction => { var key = keySelector(transaction.Item); if (key is null) { throw new Exception($"Upsert failed, key is null. Key: {keySelectorExpression.ToString()}, Document: {typeof(T).FullName}"); } if (transaction.Write && _settings.DataDir.IsNotNullOrWhiteSpace()) { var zipFile = GetFile(key.ToString()); var zipPath = zipFile.FullName; using (await _fileLocks.GetOrAdd(zipPath).EnterAsync()) { var tempFile = new FileInfo($"{zipPath}.temp"); using (var zip = ZipFile.Open(tempFile.FullName, ZipArchiveMode.Update)) { var name = zipFile.Name.SkipLast(zipFile.Extension.Length).AsString(); using var stream = zip.CreateEntry(name, CompressionLevel.Optimal).Open(); await Jsonizer.SerializeAsync(transaction.Item, stream); } await tempFile.MoveAsync(zipFile); } } else if (index.ContainsKey(key)) { throw new Exception($"Duplicate entry found in db.json files. Key: {key}"); } index[key] = transaction.Item; }); _deleters.Add(async item => { var key = keySelector(item); if (key is null) { throw new Exception($"Delete failed, key is null. Key: {keySelectorExpression.ToString()}, Document: {typeof(T).FullName}"); } if (index.TryRemove(key) && _settings.DataDir.IsNotNullOrWhiteSpace()) { var zip = GetFile(key.ToString()); using (await _fileLocks.GetOrAdd(zip.FullName).EnterAsync()) await zip.DeleteAsync(); } }); return(async key => { await Initialize(); return index.TryGetValue(key, out var item) ? item : default; }); }