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