public void AllFeatures() { // All retry features in one method: Retry.Execute(() => DummyMethods.DoWork("Hello world"), TimeSpan.FromMilliseconds(100), 2, DummyMethods.ExecuteOnEveryException, DummyMethods.ExecuteWhenMaxRetriesReachedBeforeExceptionIsThrown, typeof(ArgumentException), typeof(DbException)); }
public Consignment SaveConsignment(Consignment consignment) { //Validate the object before trying to save. //I added a custom attribute for validating phone numbers. I only did it for phone numbers - but in reality all of the properties that needed validation would have it. if (!_consignmentValidator.IsValid(consignment)) { return(consignment); } try { //Generic retry pattern to accomodate for failed attempts & retrying. //Both the delay between attempts & the amount of times to retry are stored in the appsettings.json config files var isSuccess = Retry.Execute(() => WriteConsignment(consignment), new TimeSpan(0, 0, _retryDelay), _retryCount, true); if (isSuccess) { return(consignment); } //If after retry logic the saving of the consignment was still unsuccessful then throw an error to be caught and handled appropriately. throw new Exception($"Failed to save consignment after {_retryCount} attempts"); } catch (Exception e) { //Log & rethrow error Console.WriteLine(e); throw; } }
public RabbitMqPersistentConnection( IConfiguration configuration, ILogger <RabbitMqPersistentConnection> logger) { _configuration = configuration; _logger = logger; ConnectionFactory cf = new ConnectionFactory { UserName = _configuration["EventBusUserName"], Password = _configuration["EventBusPass"], VirtualHost = _configuration["EventBusVirtualHost"], HostName = _configuration["EventBusHostName"], Port = int.Parse(_configuration["EventBusPort"]) }; var retry = new Retry { Log = methodName => { _logger.LogWarning($"Retiring action {methodName} in 2 sec"); } }; retry.Execute(() => { _persistentConnection = cf.CreateConnection(); }); }
public void should_call_action_and_return_value() { int result = Retry.Execute(() => AddOneTime(2), TimeSpan.FromMilliseconds(100), 1); result.Should().Be(1); _timesCalled.Should().Be(2); }
private void Connect() { try { Retry.Execute(() => { EnsureClient(); MyClients.Add(serviceType, m_WsDualClient); client.Register(serviceType); Initialize(); SetRequestParameters(client.GetRequestParameter(ServiceType)); }, TimeSpan.FromSeconds(2), 1); InitialSuccess = true; } catch (AggregateException ex) { var msg = "连接不上服务器:" + ex.InnerExceptions.First().Message; MessageBox.Show(msg); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { } }
public void Retry_succeeds_if_action_succeeds() { // setup var retry = new Retry(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), 1, ex => { throw ex; }); // execute and verify Assert.DoesNotThrow(() => retry.Execute(() => Task.FromResult(true))); }
public void RetryWithReturnValue() { // Execute the DoWork Once (once + no retries) int returnValue = Retry.Execute(() => { // Happy flow return(1); }, TimeSpan.FromMilliseconds(100), 0); }
public void RetryWithoutReturnValue() { // Execute the DoWork a maximum of 3 times (once + two retries) Retry.Execute(() => { // Happy flow }, TimeSpan.FromMilliseconds(100), 2); }
public void should_call_action_when_final_exception_occures() { var logger = A.Fake <ILog>(); Action action = () => Retry.Execute(() => AddOne(100), TimeSpan.FromMilliseconds(1), 9, exception => logger.Warn(exception), exception => logger.Error(exception)); action.ShouldThrow <NotSupportedException>(); A.CallTo(() => logger.Error(A <Exception> .That.Matches(x => x.GetType() == typeof(AggregateException)))).MustHaveHappened(Repeated.Exactly.Times(1)); A.CallTo(() => logger.Warn(A <Exception> .That.Matches(x => x.GetType() == typeof(NotSupportedException)))).MustHaveHappened(Repeated.Exactly.Times(10)); }
public void should_call_action_when_each_exception_occures() { var logger = A.Fake <ILog>(); Retry.Execute(() => AddOne(5), TimeSpan.FromMilliseconds(100), 100, exception => logger.Warn(exception), exception => logger.Error(exception)); A.CallTo(() => logger.Warn(A <Exception> .That.Matches(x => x.GetType() == typeof(NotSupportedException)))).MustHaveHappened(Repeated.Exactly.Times(4)); A.CallTo(() => logger.Error(A <Exception> ._)).MustHaveHappened(Repeated.Never); }
public void ExecuteTest() { int retryCount = 0; try { int result1 = Retry.Execute( () => { retryCount++; if (retryCount < 5) { throw new OperationCanceledException(); } return(retryCount); }, 3, exception => exception is OperationCanceledException); Assert.Fail(result1.ToString()); } catch (OperationCanceledException) { Assert.AreEqual(4, retryCount); } retryCount = 0; int result2 = Retry.Execute(() => { retryCount++; if (retryCount < 5) { throw new OperationCanceledException(); } return(retryCount); }, 5, exception => exception is OperationCanceledException); Assert.AreEqual(5, retryCount); Assert.AreEqual(5, result2); retryCount = 0; int result3 = Retry.Execute(() => { retryCount++; return(retryCount); }, 0, exception => exception is OperationCanceledException); Assert.AreEqual(1, retryCount); }
public void Retry_fails_if_timeout_reached() { // setup int count = 0; var retry = new Retry(TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(5), 2, e => count++); // execute var ex = Assert.Throws <AggregateException>(() => retry.Execute(() => Task.FromResult(false))); // verify count.Should().Be(3); // 1ms, 2ms, 4ms }
public void should_sleep_given_timespan_between_exceptions() { var stopwatch = new Stopwatch(); stopwatch.Start(); Retry.Execute(() => AddOne(4), TimeSpan.FromMilliseconds(500), 3); stopwatch.Stop(); stopwatch.ElapsedMilliseconds.Should().BeGreaterOrEqualTo(1499); // Weird, should be 1500, but is sometimes faster (1499) // Do not sleep after last call or before first call. stopwatch.ElapsedMilliseconds.Should().BeLessOrEqualTo(2000); }
public void Retry_collects_all_exceptions() { // setup var individualExceptions = new List <Exception>(); var retry = new Retry(TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(5), 2, individualExceptions.Add); // execute var ex = Assert.Throws <AggregateException>(() => retry.Execute(() => { throw new Exception(); })); // verify individualExceptions.Count.Should().Be(3); // 1ms, 2ms, 4ms ((AggregateException)ex.InnerExceptions[0]).InnerExceptions.Should().Equal(individualExceptions); }
/// <summary> /// Used when you are redirected to a page /// </summary> protected TPageType GetPage <TPageType>() where TPageType : BasePage, new() { var page = new TPageType(); page.SetLogger(Logger, Browser); Retry.Execute(Logger, () => { var currentUrl = Browser.GetCurrentUrl(); var pageUrl = TestData.Get.GetUrl(page.UrlForPage); Assert.Equal(pageUrl.ToString(), currentUrl); }); return(page); }
public void ExecuteAsync_Failes3of3Times_Failure() { var retry = new Retry(Enumerable.Repeat(TimeSpan.FromMilliseconds(10), 3)); var failureCount = 0; var action = new Action(() => { if (failureCount < 3) { failureCount++; throw new Exception(); } }); Assert.ThrowsException <AggregateException>(() => retry.Execute(action)); }
public void ExecuteAsync_Failes2of3Times_Success() { var retry = new Retry(Enumerable.Repeat(TimeSpan.FromMilliseconds(10), 3)); var failureCount = 0; var action = new Action(() => { if (failureCount < 2) { failureCount++; throw new Exception(); } }); retry.Execute(action); Assert.AreEqual(2, failureCount); }
public void ShouldRetryTwice() { int retry = 0; bool result = Retry.Execute(() => { if (retry < 2) { retry++; throw new ArgumentException("Cannot connect to host"); } return(true); }, new TimeSpan(0, 0, 1), 3, true, true); Assert.IsTrue(result, "Should return true after 2 failures"); Assert.AreEqual(retry, 2); }
public void EnsureDatabaseExists(string database = null, bool createDatabaseIfNotExists = true) { database = database ?? Store.Database; if (string.IsNullOrWhiteSpace(database)) { throw new ArgumentException("Value cannot be null or whitespace.", nameof(database)); } try { var retry = new Retry { Log = methodName => { _logger.LogWarning($"Retiring action {methodName} in 2 sec"); } }; retry.Execute(() => { Store.Maintenance.ForDatabase(database).Send(new GetStatisticsOperation()); }); //Store.Maintenance.ForDatabase(database).Send(new GetStatisticsOperation()); } catch (DatabaseDoesNotExistException) { if (createDatabaseIfNotExists == false) { throw; } try { Store.Maintenance.Server.Send(new CreateDatabaseOperation(new DatabaseRecord(database))); } catch (ConcurrencyException) { _logger.LogError("The database was already created before calling CreateDatabaseOperation"); } } catch (Exception e) { _logger.LogError(e.Message, e); } }
public void Retry_tries_until_message_succeeds() { // setup int count = 0; var retry = new Retry(TimeSpan.FromMilliseconds(1), TimeSpan.MaxValue, 1, ex => { count++; }); var results = new Queue <Task <bool> >(); results.Enqueue(Task.FromResult(false)); var tcs = new TaskCompletionSource <bool>(); tcs.SetException(new Exception("foo")); results.Enqueue(tcs.Task); results.Enqueue(Task.FromResult(true)); // execute retry.Execute(results.Dequeue); // verify count.Should().Be(2); }
public void should_throw_exception_when_retry_is_smaller_then_zero() { Action action = () => Retry.Execute(() => AddOne(100), TimeSpan.FromMilliseconds(1), -1); action.ShouldThrow <ArgumentException>(); }
public virtual async Task ExecuteHttpCommand(IHttpCommand command, IRetryPolicy retryPolicy = null, CancellationToken cancellationToken = default(CancellationToken)) { if (command == null) { return; } async Task action() { try { using (CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) { DateTime now = DateTime.Now; try // ловим таймаут { cancellationTokenSource.CancelAfter(command.ExpiryTime != TimeSpan.Zero ? (int)command.ExpiryTime.TotalMilliseconds : int.MaxValue); HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(command.Method), command.Uri); //пропускаем запрос через декораторы await HttpRequestPipeline(command, request, request.Properties, cancellationTokenSource.Token).ConfigureAwait(false); if (cancellationTokenSource.Token.IsCancellationRequested) { throw new OperationCanceledException(cancellationToken); } //пропускаем запрос через обработчик команды await command.OnExecuting(request, cancellationTokenSource.Token).ConfigureAwait(false); if (cancellationTokenSource.Token.IsCancellationRequested) { throw new OperationCanceledException(cancellationToken); } HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token).ConfigureAwait(false); if (cancellationTokenSource.Token.IsCancellationRequested) { throw new OperationCanceledException(cancellationToken); } //пропускаем ответ через декораторы await HttpResponsePipeline(command, response, request.Properties, cancellationTokenSource.Token).ConfigureAwait(false); if (cancellationTokenSource.Token.IsCancellationRequested) { throw new OperationCanceledException(cancellationToken); } //пропускаем ответ через обработчик команды await command.OnExecuted(response, cancellationTokenSource.Token).ConfigureAwait(false); command.Exception = null; return; } catch (Exception ex) //таймаут { if (ex is OperationCanceledException && command.ExpiryTime != TimeSpan.Zero && (now + command.ExpiryTime) < DateTime.Now) { throw new TimeoutException(string.Empty, ex); } throw; } } } catch (Exception ex) { command.Exception = ex; throw; } } if (retryPolicy == null) { await action(); } else { IRetry retry = new Retry(); await retry.Execute(action, retryPolicy, cancellationToken); } }
public void Execute_Succeeds() { var result = Retry.Execute(() => TestMethod(), 3, new TimeSpan(0, 0, 2)); Assert.IsTrue(result); }
public void should_throw_exception_when_type_is_not_typeof_exceptions() { Action action = () => Retry.Execute(() => AddOne(100), TimeSpan.FromMilliseconds(1), 1, null, null, typeof(System.IO.DirectoryInfo), typeof(FileVersionInfo), typeof(ArgumentException)); action.ShouldThrow <SimpleRetryArgumentException>().WithMessage("All types should be of base type exception. Found 2 type(s) that are not exceptions: DirectoryInfo, FileVersionInfo\r\nParameter name: exceptionTypesToHandle"); }
public void should_only_catch_given_exceptions() { Action action = () => Retry.Execute(() => AddOne(100), TimeSpan.FromMilliseconds(1), 10, null, null, typeof(DivideByZeroException)); action.ShouldThrow <NotSupportedException>(); }
public void ExecuteMethodBeforeFinalExceptionIsThrown() { // Execute the DoWork and only Execute a method before the final AggregateException is thrown Retry.Execute(() => DummyMethods.DoWork("Hello world"), TimeSpan.FromMilliseconds(100), 2, executeBeforeFinalException: DummyMethods.ExecuteWhenMaxRetriesReachedBeforeExceptionIsThrown); }
public void ExecuteMethodOnEachException() { // Execute the DoWork and only Execute a method after each exception is thrown. Retry.Execute(() => DummyMethods.DoWork("Hello world"), TimeSpan.FromMilliseconds(100), 2, executeOnEveryException: DummyMethods.ExecuteOnEveryException); }
public void RetryOnlySpecificExceptions() { // Execute the DoWork and only retry with an exception that is of (base)type DbException Retry.Execute(() => DummyMethods.DoWork("Hello world"), TimeSpan.FromMilliseconds(100), 2, exceptionTypesToHandle: new[] { typeof(ArgumentException), typeof(ArgumentOutOfRangeException) }); }
public void RetryOnlySpecificException() { // Execute the DoWork and only retry with an exception that is of (base)type DbException Retry.Execute(() => DummyMethods.DoWork("Hello world"), TimeSpan.FromMilliseconds(100), 2, exceptionTypesToHandle: typeof(DbException)); }
public void should_catch_child_exception() { Retry.Execute(() => AddOne(2), TimeSpan.FromMilliseconds(100), 1, null, null, typeof(SystemException)); _timesCalled.Should().Be(2); }