@Override public TimedAttemptSettings createNextAttempt( Throwable prevThrowable, ResponseT prevResponse, TimedAttemptSettings prevSettings) { if (prevThrowable != null && prevThrowable instanceof DeadlineExceededException) { return TimedAttemptSettings.newBuilder() .setGlobalSettings(prevSettings.getGlobalSettings()) .setRetryDelay(prevSettings.getRetryDelay()) .setRpcTimeout(prevSettings.getRpcTimeout()) .setRandomizedRetryDelay(DEADLINE_SLEEP_DURATION) .setAttemptCount(prevSettings.getAttemptCount() + 1) .setFirstAttemptStartTimeNanos(prevSettings.getFirstAttemptStartTimeNanos()) .build(); } return null; }
/** * {@inheritDoc} * * <p>The attempt settings will be reset if the stream attempt produced any messages. */ @Override public TimedAttemptSettings createNextAttempt( Throwable prevThrowable, ResponseT prevResponse, TimedAttemptSettings prevSettings) { if (prevThrowable instanceof ServerStreamingAttemptException) { ServerStreamingAttemptException attemptException = (ServerStreamingAttemptException) prevThrowable; prevThrowable = prevThrowable.getCause(); // If we have made progress in the last attempt, then reset the delays if (attemptException.hasSeenResponses()) { prevSettings = createFirstAttempt() .toBuilder() .setFirstAttemptStartTimeNanos(prevSettings.getFirstAttemptStartTimeNanos()) .setOverallAttemptCount(prevSettings.getOverallAttemptCount()) .build(); } } return super.createNextAttempt(prevThrowable, prevResponse, prevSettings); }
/** * {@inheritDoc} * * <p>The attempt settings will be reset if the stream attempt produced any messages. */ @Override public TimedAttemptSettings createNextAttempt( Throwable prevThrowable, ResponseT prevResponse, TimedAttemptSettings prevSettings) { if (prevThrowable instanceof ServerStreamingAttemptException) { ServerStreamingAttemptException attemptException = (ServerStreamingAttemptException) prevThrowable; prevThrowable = prevThrowable.getCause(); // If we have made progress in the last attempt, then reset the delays if (attemptException.hasSeenResponses()) { prevSettings = createFirstAttempt() .toBuilder() .setFirstAttemptStartTimeNanos(prevSettings.getFirstAttemptStartTimeNanos()) .setOverallAttemptCount(prevSettings.getOverallAttemptCount()) .build(); } } return super.createNextAttempt(prevThrowable, prevResponse, prevSettings); }
/** * Returns {@code true} if another attempt should be made, or {@code false} otherwise. * * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if * accepted * @return {@code true} if {@code nextAttemptSettings} does not exceed either maxAttempts limit or * totalTimeout limit, or {@code false} otherwise */ @Override public boolean shouldRetry(TimedAttemptSettings nextAttemptSettings) { RetrySettings globalSettings = nextAttemptSettings.getGlobalSettings(); long totalTimeSpentNanos = clock.nanoTime() - nextAttemptSettings.getFirstAttemptStartTimeNanos() + nextAttemptSettings.getRandomizedRetryDelay().toNanos(); return totalTimeSpentNanos <= globalSettings.getTotalTimeout().toNanos() && (globalSettings.getMaxAttempts() <= 0 || nextAttemptSettings.getAttemptCount() < globalSettings.getMaxAttempts()); }
/** * Returns {@code true} if another attempt should be made, or {@code false} otherwise. * * @param nextAttemptSettings attempt settings, which will be used for the next attempt, if * accepted * @return {@code true} if {@code nextAttemptSettings} does not exceed either maxAttempts limit or * totalTimeout limit, or {@code false} otherwise */ @Override public boolean shouldRetry(TimedAttemptSettings nextAttemptSettings) { RetrySettings globalSettings = nextAttemptSettings.getGlobalSettings(); long totalTimeSpentNanos = clock.nanoTime() - nextAttemptSettings.getFirstAttemptStartTimeNanos() + nextAttemptSettings.getRandomizedRetryDelay().toNanos(); return totalTimeSpentNanos <= globalSettings.getTotalTimeout().toNanos() && (globalSettings.getMaxAttempts() <= 0 || nextAttemptSettings.getAttemptCount() < globalSettings.getMaxAttempts()); }
protected Long getNextBackoff() { if (currentBackoff == null) { // Historically, the client waited for "total timeout" after the first failure. For now, // that behavior is preserved, even though that's not the ideal. // // TODO: Think through retries, and create policy that works with the mental model most // users would have of relating to retries. That would likely involve updating some // default settings in addition to changing the algorithm. currentBackoff = exponentialRetryAlgorithm.createFirstAttempt(); } currentBackoff = exponentialRetryAlgorithm.createNextAttempt(currentBackoff); if (!exponentialRetryAlgorithm.shouldRetry(currentBackoff)) { // TODO: consider creating a subclass of exponentialRetryAlgorithm to encapsulate this logic long timeLeftNs = currentBackoff.getGlobalSettings().getTotalTimeout().toNanos() - (clock.nanoTime() - currentBackoff.getFirstAttemptStartTimeNanos()); long timeLeftMs = TimeUnit.NANOSECONDS.toMillis(timeLeftNs); if (timeLeftMs > currentBackoff.getGlobalSettings().getInitialRetryDelay().toMillis()) { // The backoff algorithm doesn't always wait until the timeout is achieved. Wait // one final time so that retries hit return timeLeftMs; } else { // Finish for real. return null; } } else { return currentBackoff.getRetryDelay().toMillis(); } }
@Override public TimedAttemptSettings createNextAttempt( Throwable prevThrowable, ResponseT prevResponse, TimedAttemptSettings prevSettings) { if (prevThrowable != null && prevThrowable instanceof DeadlineExceededException) { return TimedAttemptSettings.newBuilder() .setGlobalSettings(prevSettings.getGlobalSettings()) .setRetryDelay(prevSettings.getRetryDelay()) .setRpcTimeout(prevSettings.getRpcTimeout()) .setRandomizedRetryDelay(DEADLINE_SLEEP_DURATION) .setAttemptCount(prevSettings.getAttemptCount() + 1) .setFirstAttemptStartTimeNanos(prevSettings.getFirstAttemptStartTimeNanos()) .build(); } return null; }
.setAttemptCount(prevSettings.getAttemptCount() + 1) .setOverallAttemptCount(prevSettings.getOverallAttemptCount() + 1) .setFirstAttemptStartTimeNanos(prevSettings.getFirstAttemptStartTimeNanos()) .build();
.setAttemptCount(prevSettings.getAttemptCount() + 1) .setOverallAttemptCount(prevSettings.getOverallAttemptCount() + 1) .setFirstAttemptStartTimeNanos(prevSettings.getFirstAttemptStartTimeNanos()) .build();