RetryPolicy.java
// SPDX-License-Identifier: Apache-2.0
package com.shengzhiai.yugu.stcompat.internal;
/**
* Retry policy shared by every Yugu SDK (DESIGN 2.3). Defaults: maxRetries 2 (3 attempts),
* initialDelayMs 200, multiplier 2.0, maxDelayMs 4000, jitter 0.3, respectRetryAfter true,
* maxRetryAfterMs 30000.
*
* <pre>
* delay(n) = min(maxDelayMs, initialDelayMs * multiplier^(n-1)) * (1 + U(-jitter, +jitter)) n = 1..maxRetries
* if respectRetryAfter and response has Retry-After: delay = max(delay, min(retryAfterMs, maxRetryAfterMs))
* </pre>
*/
public final class RetryPolicy {
public static final RetryPolicy DEFAULT = new RetryPolicy(2, 200, 2.0, 4000, 0.3, true, 30000);
public final int maxRetries;
public final long initialDelayMs;
public final double multiplier;
public final long maxDelayMs;
public final double jitter;
public final boolean respectRetryAfter;
public final long maxRetryAfterMs;
public RetryPolicy(int maxRetries, long initialDelayMs, double multiplier, long maxDelayMs, double jitter,
boolean respectRetryAfter, long maxRetryAfterMs) {
if (maxRetries < 0 || initialDelayMs < 0 || multiplier < 1.0 || maxDelayMs < 0 || jitter < 0 || jitter >= 1.0
|| maxRetryAfterMs < 0) {
throw new IllegalArgumentException("invalid retry policy");
}
this.maxRetries = maxRetries;
this.initialDelayMs = initialDelayMs;
this.multiplier = multiplier;
this.maxDelayMs = maxDelayMs;
this.jitter = jitter;
this.respectRetryAfter = respectRetryAfter;
this.maxRetryAfterMs = maxRetryAfterMs;
}
/** Delay without jitter before retry {@code n} (1-based). */
public double baseDelayMs(int n) {
return Math.min((double) maxDelayMs, initialDelayMs * Math.pow(multiplier, n - 1));
}
/**
* Delay before retry {@code n} (1-based).
*
* @param u uniform random number in [0, 1), mapped to U(-jitter, +jitter)
* @param retryAfterMs Retry-After of the failed response in ms, negative when absent
*/
public long delayMs(int n, double u, long retryAfterMs) {
double factor = 1.0 + (u * 2.0 - 1.0) * jitter;
long delay = Math.max(0L, Math.round(baseDelayMs(n) * factor));
if (respectRetryAfter && retryAfterMs >= 0) {
delay = Math.max(delay, Math.min(retryAfterMs, maxRetryAfterMs));
}
return delay;
}
}