/// <summary> /// Creates and initializes a retryable read 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 read context.</returns> public static async Task <RetryableReadContext> CreateAsync(IReadBinding binding, bool retryRequested, CancellationToken cancellationToken) { var context = new RetryableReadContext(binding, retryRequested); try { await context.InitializeAsync(cancellationToken).ConfigureAwait(false); if (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>(IRetryableReadOperation <TResult> operation, RetryableReadContext context, CancellationToken cancellationToken) { if (!ShouldReadBeRetried(context)) { return(await operation.ExecuteAttemptAsync(context, attempt : 1, transactionNumber : null, cancellationToken).ConfigureAwait(false)); } var initialServerVersion = context.Channel.ConnectionDescription.ServerVersion; Exception originalException; try { return(await operation.ExecuteAttemptAsync(context, attempt : 1, transactionNumber : null, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(RetryabilityHelper.IsRetryableReadException(ex)) { originalException = ex; } try { context.ReplaceChannelSource(context.Binding.GetReadChannelSource(cancellationToken)); context.ReplaceChannel(context.ChannelSource.GetChannel(cancellationToken)); } catch { throw originalException; } if (context.Channel.ConnectionDescription.ServerVersion < initialServerVersion) { throw originalException; } if (!AreRetryableReadsSupported(context)) { throw originalException; } try { return(await operation.ExecuteAttemptAsync(context, attempt : 2, transactionNumber : null, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) when(ShouldThrowOriginalException(ex)) { throw originalException; } }
public static TResult Execute <TResult>(IRetryableReadOperation <TResult> operation, RetryableReadContext context, CancellationToken cancellationToken) { if (!ShouldReadBeRetried(context)) { return(operation.ExecuteAttempt(context, attempt: 1, transactionNumber: null, cancellationToken)); } Exception originalException; try { return(operation.ExecuteAttempt(context, attempt: 1, transactionNumber: null, cancellationToken)); } catch (Exception ex) when(RetryabilityHelper.IsRetryableReadException(ex)) { originalException = ex; } try { context.ReplaceChannelSource(context.Binding.GetReadChannelSource(cancellationToken)); context.ReplaceChannel(context.ChannelSource.GetChannel(cancellationToken)); } catch { throw originalException; } try { return(operation.ExecuteAttempt(context, attempt: 2, transactionNumber: null, cancellationToken)); } catch (Exception ex) when(ShouldThrowOriginalException(ex)) { throw originalException; } }