private void RetryOrStopIfNecessary(HttpStatusCode statusCode) { if (!IsRunning || ((int)statusCode >= 200 && (int)statusCode <= 299)) { return; } if (!Continuous) { _workExecutor.StartNew(Stop); return; } if (!Misc.IsTransientError(statusCode)) { // Log.To.ChangeTracker.I(Tag, String.Format ("{0} got a non-transient error ({1}), stopping NOW...", this, statusCode)); _workExecutor.StartNew(Stop); return; } Log.To.ChangeTracker.I(Tag, "{0} transient error ({1}) detected, sleeping for {2}ms...", this, statusCode, Backoff.GetSleepTime().TotalMilliseconds); Backoff.DelayAppropriateAmountOfTime().ContinueWith(t => PerformRetry(true)); }
private void RetryOrStopIfNecessary(Exception e) { if (!IsRunning) { return; } if (e == null) { // No error occurred, keep going if continuous if (Continuous) { PerformRetry(false); } else { _workExecutor.StartNew(Stop); } return; } Error = Misc.Flatten(e).First(); string statusCode; if (Misc.IsTransientNetworkError(e, out statusCode)) { // Transient error occurred in a replication -> RETRY or STOP if (!Continuous && !Backoff.CanContinue) { // Give up for non-continuous Log.To.ChangeTracker.I(Tag, "{0} transient error ({1}) detected, giving up NOW...", this, statusCode); _workExecutor.StartNew(Stop); return; } // Keep retrying for continuous Log.To.ChangeTracker.I(Tag, "{0} transient error ({1}) detected, sleeping for {2}ms...", this, statusCode, Backoff.GetSleepTime().TotalMilliseconds); Backoff.DelayAppropriateAmountOfTime().ContinueWith(t => PerformRetry(true)); return; } if (String.IsNullOrEmpty(statusCode)) { Log.To.ChangeTracker.I(Tag, String.Format ("{0} got an exception, stopping NOW...", this), e); } else { Log.To.ChangeTracker.I(Tag, String.Format ("{0} got a non-transient error ({1}), stopping NOW...", this, statusCode)); } // Non-transient error occurred in a continuous replication -> STOP _workExecutor.StartNew(Stop); }
private Task ChangeFeedResponseHandler(Task <HttpResponseMessage> responseTask) { if (ResponseFailed(responseTask)) { return(Task.FromResult(false)); } var response = responseTask.Result; UpdateServerType(response); if (response.Content == null) { throw Misc.CreateExceptionAndLog(Log.To.ChangeTracker, response.StatusCode.GetStatusCode(), Tag, "Got empty change tracker response"); } Log.To.ChangeTracker.D(Tag, "Getting stream from change tracker response"); return(response.Content.ReadAsStreamAsync().ContinueWith((Task <Stream> t) => { try { var result = _responseLogic.ProcessResponseStream(t?.Result, changesFeedRequestTokenSource == null ? CancellationToken.None : changesFeedRequestTokenSource.Token); Backoff.ResetBackoff(); if (result == ChangeTrackerResponseCode.ChangeHeartbeat) { Heartbeat = _responseLogic.Heartbeat; _workExecutor.StartNew(Run); } } catch (CouchbaseLiteException e) { if (e.Code == StatusCode.BadJson) { if (Backoff.CanContinue) { Log.To.ChangeTracker.W(Tag, "{0} Couldn't parse JSON from remote, " + "retrying in {1}ms", this, Backoff.GetSleepTime().TotalMilliseconds); Backoff.DelayAppropriateAmountOfTime().ContinueWith(t1 => { Log.To.ChangeTracker.I(Tag, "{0} retrying NOW...", this); _workExecutor.StartNew(Run); }); } else { RetryOrStopIfNecessary(e); } } } catch (Exception e) { RetryOrStopIfNecessary(e); } finally { Misc.SafeDispose(ref changesFeedRequestTokenSource); response.Dispose(); } })); }