Beispiel #1
0
        /// <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;
            }
        }