public void ShouldNotRetryOnSuccess()
        {
            var retryLogic = new RetryLogic(TimeSpan.FromSeconds(5), null);
            var work       = CreateFailingWork(5);

            var result = retryLogic.Retry(() => work.Work(null));

            result.Should().Be(5);
            work.Invocations.Should().Be(1);
        }
        public void ShouldRetryOnTransientErrors(Exception error)
        {
            var retryLogic = new RetryLogic(TimeSpan.FromSeconds(5), null);
            var work       = CreateFailingWork(5, error);

            var result = retryLogic.Retry(() => work.Work(null));

            result.Should().Be(5);
            work.Invocations.Should().Be(2);
        }
        public void ShouldNotRetryOnNonTransientErrors(Exception error)
        {
            var retryLogic = new RetryLogic(TimeSpan.FromSeconds(5), null);
            var work       = CreateFailingWork(0, error);

            var exc = Record.Exception(() => retryLogic.Retry(() => work.Work(null)));

            exc.Should().Be(error);
            work.Invocations.Should().Be(1);
        }
        public void ShouldRetryAtLeastTwice()
        {
            var error      = new TransientException("code", "message");
            var logger     = new Mock <IDriverLogger>();
            var retryLogic = new RetryLogic(TimeSpan.FromSeconds(1), logger.Object);
            var work       = CreateFailingWork(TimeSpan.FromSeconds(2), 1, error);

            var result = retryLogic.Retry(() => work.Work(null));

            result.Should().Be(1);
            logger.Verify(x => x.Warn(error,
                                      It.Is <string>(s => s.StartsWith("Transaction failed and will be retried in"))),
                          Times.Once);
        }
        public void ShouldLogRetries(int errorCount)
        {
            var error      = new TransientException("code", "message");
            var logger     = new Mock <IDriverLogger>();
            var retryLogic = new RetryLogic(TimeSpan.FromMinutes(1), logger.Object);
            var work       = CreateFailingWork(1,
                                               Enumerable.Range(1, errorCount).Select(x => error).Cast <Exception>().ToArray());

            var result = retryLogic.Retry(() => work.Work(null));

            result.Should().Be(1);
            logger.Verify(x => x.Warn(error,
                                      It.Is <string>(s => s.StartsWith("Transaction failed and will be retried in"))),
                          Times.Exactly(errorCount));
        }
        public void ShouldThrowServiceUnavailableWhenRetriesTimedOut()
        {
            var errorCount = 3;
            var exceptions = Enumerable.Range(1, errorCount).Select(i => new TransientException($"{i}", $"{i}"))
                             .Cast <Exception>().ToArray();
            var logger     = new Mock <IDriverLogger>();
            var retryLogic = new RetryLogic(TimeSpan.FromSeconds(2), logger.Object);
            var work       = CreateFailingWork(TimeSpan.FromSeconds(1), 1, exceptions);

            var exc = Record.Exception(() => retryLogic.Retry(() => work.Work(null)));

            exc.Should().BeOfType <ServiceUnavailableException>()
            .Which.InnerException.Should().BeOfType <AggregateException>()
            .Which.InnerExceptions.Should().BeSubsetOf(exceptions);
        }