async Task IRetriableStatement.RetryAsync(SpannerRetriableTransaction transaction, CancellationToken cancellationToken, int timeoutSeconds)
        {
            try
            {
                await _command.CreateSpannerBatchCommand().ExecuteNonQueryAsync(cancellationToken);

                // Fallthrough and throw the exception at the end of the method.
            }
            catch (SpannerBatchNonQueryException e)
            {
                // Check that we got the exact same exception and results this time as the previous time.
                if (_exception is SpannerBatchNonQueryException batchException &&
                    e.ErrorCode == _exception.ErrorCode &&
                    e.Message.Equals(_exception.Message)
                    // A Batch DML statement returns the update counts of the first N statements and the error
                    // that occurred for statement N+1.
                    && e.SuccessfulCommandResults.SequenceEqual(batchException.SuccessfulCommandResults)
                    )
                {
                    return;
                }
            }
            catch (SpannerException e) when(e.ErrorCode != ErrorCode.Aborted)
            {
                // Check that we got the exact same exception during the retry as during the initial attempt.
                // This happens if the Batch DML RPC itself failed, and not one of the DML statements.
                if (!(_exception is SpannerBatchNonQueryException) && SpannerRetriableTransaction.SpannerExceptionsEqualForRetry(e, _exception))
                {
                    return;
                }
            }
            throw new SpannerAbortedDueToConcurrentModificationException();
        }
Example #2
0
 async Task IRetriableStatement.RetryAsync(SpannerRetriableTransaction transaction, CancellationToken cancellationToken, int timeoutSeconds)
 {
     try
     {
         _command.Transaction = transaction;
         if (!_updateCounts.SequenceEqual(await _command.CreateSpannerBatchCommand().ExecuteNonQueryAsync(cancellationToken)))
         {
             throw new SpannerAbortedDueToConcurrentModificationException();
         }
     }
     catch (SpannerException e) when(e.ErrorCode != ErrorCode.Aborted)
     {
         throw new SpannerAbortedDueToConcurrentModificationException();
     }
 }
        internal async Task <IReadOnlyList <long> > ExecuteNonQueryWithRetryAsync(SpannerRetriableBatchCommand command, CancellationToken cancellationToken = default)
        {
            while (true)
            {
                var spannerCommand = command.CreateSpannerBatchCommand();
                try
                {
                    IReadOnlyList <long> res = await spannerCommand.ExecuteNonQueryAsync(cancellationToken);

                    _retriableStatements.Add(new RetriableBatchDmlStatement(command, res));
                    return(res);
                }
                catch (SpannerException e) when(e.ErrorCode == ErrorCode.Aborted)
                {
                    await RetryAsync(e, cancellationToken);
                }
                catch (SpannerException e)
                {
                    _retriableStatements.Add(new FailedBatchDmlStatement(command, e));
                    throw;
                }
            }
        }