public void Dispose() { try { _transaction?.Dispose(); // Protect against multiple disposals _transaction = null; } catch (Exception e) { Logger.Error("Error disposing", e); } }
public void Dispose() { _transaction?.Dispose(); }
internal async Task <TResult> RunAsync <TResult>(Func <SpannerTransaction, Task <TResult> > asyncWork, CancellationToken cancellationToken = default) { GaxPreconditions.CheckNotNull(asyncWork, nameof(asyncWork)); // Session will be initialized and subsequently modified by CommitAttempt. PooledSession session = null; try { return(await ExecuteWithRetryAsync(CommitAttempt, cancellationToken).ConfigureAwait(false)); } finally { session?.Dispose(); } async Task <TResult> CommitAttempt() { return(await ExecuteHelper.WithErrorTranslationAndProfiling( async() => { SpannerTransaction transaction = null; try { session = await(session?.WithFreshTransactionOrNewAsync(SpannerConnection.s_readWriteTransactionOptions, cancellationToken) ?? _connection.AcquireReadWriteSessionAsync(cancellationToken)).ConfigureAwait(false); transaction = new SpannerTransaction(_connection, TransactionMode.ReadWrite, session, null); TResult result = await asyncWork(transaction).ConfigureAwait(false); await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); return result; } // We only catch to attempt a rollback, and that is possible if we have a transaction already. // If the exception was thrown when refreshing the session the we don't have a transaction yet. catch when(transaction != null) { try { await transaction.RollbackAsync(cancellationToken).ConfigureAwait(false); } catch (Exception e) { // If the commit failed, calling Rollback will fail as well. // We don't want that or any other rollback exception to propagate, // it will not trigger the retry _connection.Logger.Warn("A rollback attempt failed on RetriableTransaction.RunAsync.CommitAttempt", e); } // Throw, the retry helper will know when to retry. throw; } finally { if (transaction != null) { // Let's make sure that the associated session is not released to the pool // because we'll be attempting to get a fresh transaction for this same session first. // If that fails will attempt a new session acquisition. // This session will be disposed of by the pool if it can't be refreshed or by the RunAsync method // if we are not retrying anymore. transaction.DisposeBehavior = DisposeBehavior.Detach; transaction.Dispose(); } } }, "RetriableTransaction.RunAsync.CommitAttempt", _connection.Logger).ConfigureAwait(false)); } }