public async Task <ValueRecord> AddOrUpdate( KeyRecord key, Func <KeyRecord, Task <ValueRecord> > addFactory, Func <KeyRecord, ValueRecord, Task <ValueRecord> > updateFactory, CancellationToken token) { var strategy = options.UpsertRetry; var attempt = 1; while (true) { logger.LogDebug("Storage.AddOrUpdate({KeyId}): {Attempt} begins.", key.Id, attempt); ValueRecord newValue; if (await TryGet(key, token) is not Some <ValueRecord>(var currentValue)) { var addedKey = new MongoKeyRecord(key.Id, key.Type, key.Content); await InsertOne(keyCollection, addedKey, token); currentValue = null; newValue = await addFactory(key); logger.LogDebug("Storage.AddOrUpdate({KeyId}): {Attempt} adding value.", key.Id, attempt); }
public async Task <ValueRecord> AddOrGet( KeyRecord key, Func <KeyRecord, Task <ValueRecord> > addFactory, CancellationToken token) { var strategy = options.UpsertRetry; var attempt = 1; while (true) { logger.LogDebug("Storage.AddOrGet({KeyId}): {Attempt} begins.", key.Id, attempt); if (await TryGet(key, token) is Some <ValueRecord>(var currentValue)) { logger.LogDebug("Storage.AddOrGet({KeyId}): {Attempt} got value.", key.Id, attempt); return(currentValue); } var addedKey = new MongoKeyRecord(key.Id, key.Type, key.Content); await InsertOne(keyCollection, addedKey, token); var newValue = await addFactory(key); if (await AddValue(key, currentValue: null, newValue, token) is Some <ValueRecord>(var added)) { logger.LogDebug("Storage.AddOrGet({KeyId}): {Attempt} added initial version.", key.Id, attempt); return(added); } attempt++; if (!strategy.CanRetry(attempt)) { logger.LogDebug("Storage.AddOrGet({KeyId}): {Attempt} won't proceed.", key.Id, attempt); break; } await Task.Delay(strategy.DelayTime(attempt), token); } throw new StorageConcurrencyException(); }