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(); }
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; } } }