/// <summary> /// Creates and initializes a retryable write operation context. /// </summary> /// <param name="binding">The binding.</param> /// <param name="retryRequested">if set to <c>true</c> [retry requested].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A retryable write context.</returns> public static async Task <RetryableWriteContext> CreateAsync(IWriteBinding binding, bool retryRequested, CancellationToken cancellationToken) { var context = new RetryableWriteContext(binding, retryRequested); try { await context.InitializeAsync(cancellationToken).ConfigureAwait(false); if (context.Binding.Session.IsInTransaction && ChannelPinningHelper.PinChannelSourceAndChannelIfRequired( context.ChannelSource, context.Channel, context.Binding.Session, out var pinnedChannelSource, out var pinnedChannel)) { context.ReplaceChannelSource(pinnedChannelSource); context.ReplaceChannel(pinnedChannel); } return(context); } catch { context.Dispose(); throw; } }
public static async Task <TResult> ExecuteAsync <TResult>(IRetryableWriteOperation <TResult> operation, RetryableWriteContext context, CancellationToken cancellationToken) { if (!context.RetryRequested || !AreRetryableWritesSupported(context.Channel.ConnectionDescription)) { return(await operation.ExecuteAttemptAsync(context, 1, null, cancellationToken).ConfigureAwait(false)); } var transactionNumber = context.Binding.Session.AdvanceTransactionNumber(); Exception originalException; try { return(await operation.ExecuteAttemptAsync(context, 1, transactionNumber, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(IsRetryableException(ex)) { originalException = ex; } try { context.ReplaceChannelSource(await context.Binding.GetWriteChannelSourceAsync(cancellationToken).ConfigureAwait(false)); context.ReplaceChannel(await context.ChannelSource.GetChannelAsync(cancellationToken).ConfigureAwait(false)); } catch { throw originalException; } if (!AreRetryableWritesSupported(context.Channel.ConnectionDescription)) { throw originalException; } try { return(await operation.ExecuteAttemptAsync(context, 2, transactionNumber, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(ShouldThrowOriginalException(ex)) { throw originalException; } }
public static TResult Execute <TResult>(IRetryableWriteOperation <TResult> operation, RetryableWriteContext context, CancellationToken cancellationToken) { if (!AreRetriesAllowed(operation, context)) { return(operation.ExecuteAttempt(context, 1, null, cancellationToken)); } var transactionNumber = context.Binding.Session.AdvanceTransactionNumber(); Exception originalException; try { return(operation.ExecuteAttempt(context, 1, transactionNumber, cancellationToken)); } catch (Exception ex) when(RetryabilityHelper.IsRetryableWriteException(ex)) { originalException = ex; } try { context.ReplaceChannelSource(context.Binding.GetWriteChannelSource(cancellationToken)); context.ReplaceChannel(context.ChannelSource.GetChannel(cancellationToken)); } catch { throw originalException; } if (!AreRetryableWritesSupported(context.Channel.ConnectionDescription)) { throw originalException; } try { return(operation.ExecuteAttempt(context, 2, transactionNumber, cancellationToken)); } catch (Exception ex) when(ShouldThrowOriginalException(ex)) { throw originalException; } }