public void GetIntervalsAndReset_WithMax() { var backOff = new BackOff(backOffBase: 5, attempt: 0, maxAllowed: 30); var result = backOff.GetInterval(); Assert.AreEqual(0, result); result = backOff.GetInterval(); Assert.AreEqual(10, result); result = backOff.GetInterval(); Assert.AreEqual(20, result); result = backOff.GetInterval(); Assert.AreEqual(30, result); result = backOff.GetInterval(); Assert.AreEqual(30, result); result = backOff.GetInterval(); Assert.AreEqual(30, result); result = backOff.GetInterval(); Assert.AreEqual(30, result); backOff.Reset(); result = backOff.GetInterval(); Assert.AreEqual(0, result); }
public PushManagerTests() { _authApiClient = new Mock <IAuthApiClient>(); _log = new Mock <ISplitLogger>(); _sseHandler = new Mock <ISSEHandler>(); _telemetryRuntimeProducer = new Mock <ITelemetryRuntimeProducer>(); var wrapper = new WrapperAdapter(); var backoff = new BackOff(1, 1); _pushManager = new PushManager(_sseHandler.Object, _authApiClient.Object, wrapper, _telemetryRuntimeProducer.Object, backoff, _log.Object); }
public RestStreamClient(HttpClient httpClient, RestConfig restConfig, Parser parser, BackOff backOff = default, ExceptionHandler exceptionHandler = null) { this.httpClient = httpClient; this.restConfig = restConfig; this.parser = parser; this.retryExecutor = new RetryExecutor(backOff ?? new FibonacciBackOff.Builder().build()); this.exceptionHandler = exceptionHandler; this.apiUrl = restConfig.GetUrl(); }
public void SendOTPNonBackOff(int otpCount, BackOff backOff, DateTime dateTime, string code, SendOTPResponse expected) { this.counter.Setup(x => x.GetOTP()).Returns(otpCount); this.dac.Setup(x => x.GetBackOff()).Returns(backOff); this.time.Setup(x => x.GetNow()).Returns(dateTime); this.otp.Setup(x => x.GenerateOTP()).Returns(code); BackOffController backOffCtr = new BackOffController(counter.Object, dac.Object, time.Object, otp.Object); var result = backOffCtr.SendOTP(); result.Should().BeEquivalentTo(expected); }
private void BuildSyncManager() { try { // Synchronizer var impressionsCountSender = new ImpressionsCountSender(_impressionsSdkApiClient, _impressionsCounter, _tasksManager); var backOff = new BackOff(backOffBase: 10, attempt: 0, maxAllowed: 60); var synchronizer = new Synchronizer(_splitFetcher, _selfRefreshingSegmentFetcher, _impressionsLog, _eventsLog, impressionsCountSender, _wrapperAdapter, _statusManager, _telemetrySyncTask, _tasksManager, _splitCache, backOff, _config.OnDemandFetchMaxRetries, _config.OnDemandFetchRetryDelayMs, _segmentCache); // Workers var splitsWorker = new SplitsWorker(_splitCache, synchronizer, _tasksManager); var segmentsWorker = new SegmentsWorker(synchronizer, _tasksManager); // NotificationProcessor var notificationProcessor = new NotificationProcessor(splitsWorker, segmentsWorker); // NotificationParser var notificationParser = new NotificationParser(); // NotificationManagerKeeper var notificationManagerKeeper = new NotificationManagerKeeper(_telemetryRuntimeProducer); // EventSourceClient var headers = GetHeaders(); headers.Add(Constants.Http.SplitSDKClientKey, ApiKey.Substring(ApiKey.Length - 4)); headers.Add(Constants.Http.Accept, Constants.Http.EventStream); var sseHttpClient = new SplitioHttpClient(ApiKey, _config.HttpConnectionTimeout, headers); var eventSourceClient = new EventSourceClient(notificationParser, _wrapperAdapter, sseHttpClient, _telemetryRuntimeProducer, _tasksManager); // SSEHandler var sseHandler = new SSEHandler(_config.StreamingServiceURL, splitsWorker, segmentsWorker, notificationProcessor, notificationManagerKeeper, eventSourceClient: eventSourceClient); // AuthApiClient var httpClient = new SplitioHttpClient(ApiKey, _config.HttpConnectionTimeout, GetHeaders()); var authApiClient = new AuthApiClient(_config.AuthServiceURL, ApiKey, httpClient, _telemetryRuntimeProducer); // PushManager var backoff = new BackOff(_config.AuthRetryBackoffBase, attempt: 1); var pushManager = new PushManager(sseHandler, authApiClient, _wrapperAdapter, _telemetryRuntimeProducer, backoff); // SyncManager _syncManager = new SyncManager(_config.StreamingEnabled, synchronizer, pushManager, sseHandler, notificationManagerKeeper, _telemetryRuntimeProducer, _statusManager, _tasksManager, _wrapperAdapter, _telemetrySyncTask); } catch (Exception ex) { _log.Error($"BuildSyncManager: {ex.Message}"); } }
/// <summary> /// Handles back-off. In case the request doesn't support retry or the back-off time span is greater than the /// maximum time span allowed for a request, the handler returns <c>false</c>. Otherwise, current thread will /// block for x milliseconds (x is defined by the <see cref="BackOff"/> instance), and this handler returns /// <c>true</c>. /// </summary> private bool Handle(bool supportsRetry, int currentFailedTry, CancellationToken cancellationToken) { if (!supportsRetry || BackOff.MaxNumOfRetries < currentFailedTry) { return(false); } TimeSpan ts = BackOff.GetNextBackOff(currentFailedTry); if (ts > MaxTimeSpan || ts < TimeSpan.Zero) { return(false); } Wait(ts, cancellationToken); Logger.Debug("Back-Off handled the error. Waited {0}ms before next retry...", ts.TotalMilliseconds); return(true); }
public void GetIntervalsAndReset() { var backOff = new BackOff(backOffBase: 1, attempt: 0); var result = backOff.GetInterval(); Assert.AreEqual(0, result); result = backOff.GetInterval(); Assert.AreEqual(2, result); result = backOff.GetInterval(); Assert.AreEqual(4, result); backOff.Reset(); result = backOff.GetInterval(); Assert.AreEqual(0, result); }
protected override void Receive(CancellationToken token, IConnection connection) { var backOff = new BackOff(MaximumDelay); using (ISession session = connection.CreateSession(true, AcknowledgeMode.AutoAcknowledge)) { CurrentSessions.SetSession(session); using (IMessageConsumer consumer = createConsumer(session)) { while (!token.IsCancellationRequested) { IMessage message; using (var lockReset = new ManualResetEventSlim(false)) { using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { Transaction.Current.TransactionCompleted += (sender, args) => lockReset.Set(); message = consumer.ReceiveNoWait(); if (message != null) { Exception exception = null; TransportMessage transportMessage = null; try { transportMessage = ConvertMessage(message); if (ProcessMessage(transportMessage)) { scope.Complete(); } } catch (Exception ex) { Logger.Error("Error processing message.", ex); exception = ex; } finally { endProcessMessage(transportMessage, exception); } } } lockReset.Wait(); } backOff.Wait(() => message == null); } consumer.Close(); } session.Close(); } }
? Math.Max(BackOff(x, y), schedule.BackOff(x, y))
? Math.Min(BackOff(x, y), schedule.BackOff(x, y))
internal RetryExecutor(BackOff backOff) { this.backOff = backOff; }
public static async Task BlockAsync(int retries, int secsDelay, Func <Task> retryBock, CancellationToken token = new CancellationToken(), List <string> nonRetryErrors = null, List <object> nonRetryExceptions = null, bool overrideDoNotRetry = false) { if (nonRetryExceptions == null) { nonRetryExceptions = new List <object>(); } var backOff = new BackOff(); var backOffStarted = false; while (true) { var useBackOff = false; try { await retryBock(); break; } catch (Exception ex) { if (token.IsCancellationRequested) { throw; } if (nonRetryErrors != null) { if (nonRetryErrors.Any(strError => ex.Message.Replace(" ", "").ToLower().Contains(strError.ToLower()))) { break; } } try { Trace.WriteLine("ERROR: " + ex.Message); if (ex.InnerException != null) { Trace.WriteLine("ERROR: " + ex.InnerException.Message); } } catch { } if (ex.Message.ToLower().Contains("too many")) { useBackOff = true; if (!backOffStarted && retries < 20) { retries = 20; } backOffStarted = true; } LastErrorMessage = ex.ToString(); if (nonRetryExceptions.Any(exception => ex.GetType() == exception.GetType())) { throw; } if (--retries < 0) { throw; } if (DoNotRetry && !overrideDoNotRetry) { throw; } } RetryCount += 1; if (StopRetries) { break; } if (useBackOff) { await backOff.RunAsync(); } else { await Task.Delay(secsDelay * 1000, token); } if (StopRetries) { break; } } }
public static T Block <T>(int retries, int secsDelay, Func <T> retryBock, List <Exception> nonRetryExceptions = null, bool overrideDoNotRetry = false) { if (nonRetryExceptions == null) { nonRetryExceptions = new List <Exception>(); } var backOff = new BackOff(); var backOffStarted = false; while (true) { var useBackOff = false; try { return(retryBock()); } catch (Exception ex) { if (ex.Message.ToLower().Contains("too many requests received")) { useBackOff = true; if (!backOffStarted && retries < 20) { retries = 20; } backOffStarted = true; } try { Trace.WriteLine("ERROR: " + ex.Message); if (ex.InnerException != null) { Trace.WriteLine("ERROR: " + ex.InnerException.Message); } } catch { } RetryCount += 1; LastErrorMessage = ex.ToString(); if (nonRetryExceptions.Any(exception => ex.GetType() == exception.GetType())) { throw; } if (--retries < 0) { throw; } if (DoNotRetry && !overrideDoNotRetry) { throw; } } RetryCount += 1; if (useBackOff) { backOff.Run(); } else { System.Threading.Thread.Sleep(secsDelay * 1000); } } }