コード例 #1
0
        private static AsyncPolicyWrap <HttpResponseMessage> CreatePollyPolicy(PollyOptions pollyOptions)
        {
            var retries = Backoff.ConstantBackoff(
                TimeSpan.FromMilliseconds(pollyOptions.RetryBackOffMs),
                pollyOptions.RetryCount,
                true);

            // Timeout policy
            var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(pollyOptions.TimeoutMs));

            // Wrap timeout policy with retry
            var retryWithTimeout = Policy
                                   .Handle <TimeoutRejectedException>()
                                   .Or <TimeoutException>()
                                   .OrResult <HttpResponseMessage>(IsTransientError)
                                   .WaitAndRetryAsync(retries)
                                   .WrapAsync(timeoutPolicy);

            // Wrap retry with circuit breaker
            var circuitBreaker = Policy
                                 .Handle <HttpRequestException>()
                                 .Or <TimeoutRejectedException>()
                                 .Or <TimeoutException>()
                                 .OrResult <HttpResponseMessage>(IsTransientError)
                                 .CircuitBreakerAsync(
                handledEventsAllowedBeforeBreaking: pollyOptions.ExceptionsBeforeBreak,
                durationOfBreak: TimeSpan.FromMilliseconds(pollyOptions.BreakDurationMs))
                                 .WrapAsync(retryWithTimeout);

            return(circuitBreaker);
        }
コード例 #2
0
        public void Backoff_WithFastFirstEqualToTrue_ResultIsZero()
        {
            // Arrange
            var        delay      = TimeSpan.FromMilliseconds(1);
            const int  retryCount = 3;
            const bool fastFirst  = true;

            // Act
            IEnumerable <TimeSpan> result = Backoff.ConstantBackoff(delay, retryCount, fastFirst);

            // Assert
            result.Should().NotBeNull();
            result.Should().HaveCount(retryCount);

            bool first = true;

            foreach (TimeSpan timeSpan in result)
            {
                if (first)
                {
                    timeSpan.Should().Be(TimeSpan.Zero);
                    first = false;
                }
                else
                {
                    timeSpan.Should().Be(delay);
                }
            }
        }
コード例 #3
0
        public ConferenceRegistrationDbContext(DbContextOptions options)
            : base(options)
        {
            var delay = Backoff.ConstantBackoff(TimeSpan.FromMilliseconds(200), retryCount: 5, fastFirst: true);

            this.retryPolicy = Policy
                               .Handle <Exception>()
                               .WaitAndRetryAsync(delay, (exception, i, span) =>
            {
                Trace.TraceWarning(
                    $"An error occurred in attempt number {i} to access the database in ConferenceService: {exception.Message}");
            });
        }
コード例 #4
0
        public static SleepDurationProvider Constant(int retryCount, TimeSpan initialDelay)
        {
            if (retryCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(retryCount), retryCount, "should be >= 0");
            }
            if (initialDelay < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(initialDelay), initialDelay, "should be >= 0ms");
            }

            return(new SleepDurationProvider(retryCount, Backoff.ConstantBackoff(initialDelay, retryCount)));
        }
コード例 #5
0
        public OrderEventHandler(Func <ConferenceContext> contextFactory)
        {
            this.contextFactory = contextFactory;
            var delay = Backoff.ConstantBackoff(TimeSpan.FromMilliseconds(200), retryCount: 5, fastFirst: true);

            this.retryPolicy = Policy
                               .Handle <Exception>()
                               .WaitAndRetryAsync(delay, (exception, i, span) =>
            {
                Trace.TraceWarning(
                    $"An error occurred in attempt number {i} to access the database in ConferenceService: {exception.Message}");
            });
        }
コード例 #6
0
            internal static IEnumerable <TimeSpan> Constant(int retryCount, TimeSpan delay)
            {
                if (retryCount < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(retryCount), retryCount, "should be >= 0");
                }
                if (delay < TimeSpan.Zero)
                {
                    throw new ArgumentOutOfRangeException(nameof(delay), delay, "should be >= 0ms");
                }

                return(Backoff.ConstantBackoff(delay, retryCount));
            }
コード例 #7
0
        public void Backoff_WithRetryEqualToZero_ResultIsEmpty()
        {
            // Arrange
            var        delay      = TimeSpan.FromMilliseconds(1);
            const int  retryCount = 0;
            const bool fastFirst  = false;

            // Act
            IEnumerable <TimeSpan> result = Backoff.ConstantBackoff(delay, retryCount, fastFirst);

            // Assert
            result.Should().NotBeNull();
            result.Should().BeEmpty();
        }
コード例 #8
0
        public void Backoff_WithRetryCountLessThanZero_ThrowsException()
        {
            // Arrange
            var        delay      = TimeSpan.FromMilliseconds(1);
            const int  retryCount = -1;
            const bool fastFirst  = false;

            // Act
            Action act = () => Backoff.ConstantBackoff(delay, retryCount, fastFirst);

            // Assert
            act.Should().Throw <ArgumentOutOfRangeException>()
            .And.ParamName.Should().Be("retryCount");
        }
コード例 #9
0
        public void Backoff_WithDelayLessThanZero_ThrowsException()
        {
            // Arrange
            var        delay      = new TimeSpan(-1);
            const int  retryCount = 3;
            const bool fastFirst  = false;

            // Act
            Action act = () => Backoff.ConstantBackoff(delay, retryCount, fastFirst);

            // Assert
            act.Should().Throw <ArgumentOutOfRangeException>()
            .And.ParamName.Should().Be("delay");
        }
コード例 #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserVoteController"/> class.
 /// </summary>
 /// <param name="logger">Logger implementation to send logs to the logger service.</param>
 /// <param name="telemetryClient">The Application Insights telemetry client.</param>
 /// <param name="userVoteStorageProvider">Instance of user vote storage provider to add and delete user vote.</param>
 /// <param name="teamIdeaStorageProvider">Instance of team post storage provider to update post and get information of posts.</param>
 /// <param name="teamIdeaSearchService">The team post search service dependency injection.</param>
 public UserVoteController(
     ILogger <UserVoteController> logger,
     TelemetryClient telemetryClient,
     IUserVoteStorageProvider userVoteStorageProvider,
     IIdeaStorageProvider teamIdeaStorageProvider,
     IIdeaSearchService teamIdeaSearchService)
     : base(telemetryClient)
 {
     this.logger = logger;
     this.userVoteStorageProvider = userVoteStorageProvider;
     this.teamIdeaStorageProvider = teamIdeaStorageProvider;
     this.teamIdeaSearchService   = teamIdeaSearchService;
     this.retryPolicy             = Policy.Handle <StorageException>(ex => ex.RequestInformation.HttpStatusCode == StatusCodes.Status412PreconditionFailed)
                                    .WaitAndRetryAsync(Backoff.ConstantBackoff(TimeSpan.FromMilliseconds(250), 25));
 }
コード例 #11
0
        /// <summary>
        /// Create an constant backoff retry delay of 1, 1, 1, 1s.
        /// </summary>
        /// <typeparam name="T">The type of response.</typeparam>
        /// <param name="option">The retry option.</param>
        /// <param name="context">Request context.</param>
        /// <param name="action">Action to execute.</param>
        /// <param name="predicate">Handle result predicate.</param>
        /// <param name="onRetry">Handle custom on retries.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static Task <T> ConstantBackoff <T>(
            RetryOption option,
            Context context,
            Func <Context, Task <T> > action,
            Func <T, bool> predicate,
            Action <DelegateResult <T>, TimeSpan, Context> onRetry)
        {
            if (option is null)
            {
                throw new ArgumentNullException(nameof(option));
            }

            var delay = Backoff.ConstantBackoff(TimeSpan.FromMilliseconds(option.MinDelayIsMs), retryCount: option.MaxRetry);

            return(HandleRetry(context, action, predicate, onRetry, delay));
        }
コード例 #12
0
        public void Backoff_ResultIsConstant()
        {
            // Arrange
            var        delay      = TimeSpan.FromMilliseconds(10);
            const int  retryCount = 3;
            const bool fastFirst  = false;

            // Act
            IEnumerable <TimeSpan> result = Backoff.ConstantBackoff(delay, retryCount, fastFirst);

            // Assert
            result.Should().NotBeNull();
            result.Should().HaveCount(retryCount);

            foreach (TimeSpan timeSpan in result)
            {
                timeSpan.Should().Be(delay);
            }
        }
コード例 #13
0
        public ConferenceService(IBus bus, ConferenceContext conferenceContext)
        {
            // NOTE: the database storage cannot be transactional consistent with the
            // event bus, so there is a chance that the conference state is saved
            // to the database but the events are not published. The recommended
            // mechanism to solve this lack of transaction support is to persist
            // failed events to a table in the same database as the conference, in a
            // queue that is retried until successful delivery of events is
            // guaranteed. This mechanism has been implemented for the AzureEventSourcedRepository
            // and that implementation can be used as a guide to implement it here too.

            context  = conferenceContext;
            this.bus = bus;

            var delay = Backoff.ConstantBackoff(TimeSpan.FromMilliseconds(200), retryCount: 5, fastFirst: true);

            this.retryPolicy = Policy
                               .Handle <Exception>()
                               .WaitAndRetryAsync(delay, (exception, i, span) =>
            {
                Trace.TraceWarning(
                    $"An error occurred in attempt number {i} to access the database in ConferenceService: {exception.Message}");
            });
        }