public async Task <TRecord?> ExecuteReturnNewItemAsync(CancellationToken cancellationToken) { PrepareRequest(); _request.ReturnValues = ReturnValue.ALL_NEW; try { var response = await _table.DynamoClient.UpdateItemAsync(_request); return(_table.DeserializeItem <TRecord>(response.Attributes)); } catch (ConditionalCheckFailedException) { return(default(TRecord)); } }
public async Task <(bool Success, IEnumerable <TRecord> Items)> TryExecuteAsync(int maxAttempts = 5, CancellationToken cancellationToken = default) { if (!_request.TransactItems.Any()) { throw new ArgumentException("primary keys cannot be empty"); } if (_request.TransactItems.Count > 25) { throw new ArgumentException("too many primary keys"); } for (var i = 0; i < _request.TransactItems.Count; ++i) { _request.TransactItems[i].Get.ProjectionExpression = _converters[i].ConvertProjections(); } // perform transaction try { var result = new List <TRecord>(); var response = await _table.DynamoClient.TransactGetItemsAsync(_request, cancellationToken); foreach (var itemResponse in response.Responses) { var record = _table.DeserializeItem <TRecord>(itemResponse.Item); if (!(record is null)) { result.Add(record); } } return(Success : true, Items : result); } catch (TransactionCanceledException) { // transaction failed return(Success : false, Items : Enumerable.Empty <TRecord>()); } }
public async Task <TRecord?> ExecuteAsync(CancellationToken cancellationToken) { _request.ProjectionExpression = _converter.ConvertProjections(); var response = await _table.DynamoClient.GetItemAsync(_request, cancellationToken); return(response.IsItemSet ? _table.DeserializeItem <TRecord>(response.Item) : null); }
public async Task <TRecord?> ExecuteReturnOldItemAsync(CancellationToken cancellationToken) { _request.ConditionExpression = _converter.ConvertConditions(_table.Options); _request.ReturnValues = ReturnValue.ALL_OLD; try { var response = await _table.DynamoClient.DeleteItemAsync(_request); return(_table.DeserializeItem <TRecord>(response.Attributes)); } catch (ConditionalCheckFailedException) { return(default(TRecord)); } }
public async Task <IEnumerable <TRecord> > ExecuteAsync(int maxAttempts, CancellationToken cancellationToken = default) { var requestTableAndKeys = _request.RequestItems.First(); requestTableAndKeys.Value.ProjectionExpression = _converter.ConvertProjections(); // NOTE (2021-06-30, bjorg): batch operations may run out of capacity/bandwidth and may have to be completed in batches themselves var result = new List <TRecord>(); var attempts = 1; do { try { var response = await _table.DynamoClient.BatchGetItemAsync(_request, cancellationToken); if (response.Responses.Any()) { foreach (var item in response.Responses.Single().Value) { var record = _table.DeserializeItem <TRecord>(item); if (!(record is null)) { result.Add(record); } } } // check if all requested primary keys were processed if (!response.UnprocessedKeys.Any()) { break; } // repeat request with unprocessed primary keys requestTableAndKeys.Value.Keys = response.UnprocessedKeys.First().Value.Keys; } catch (ProvisionedThroughputExceededException) { // NOTE (2021-06-30, bjorg): not a single item could be returned due to insufficient read capacity } // use exponential backoff before attempting next operation if (attempts >= maxAttempts) { throw new DynamoTableBatchGetItemsMaxAttemptsExceededException(result); } await Task.Delay(TimeSpan.FromMilliseconds(MILLISECOND_BACKOFF << (attempts++ - 1))); } while(true); return(result); }