forked from aws/aws-durable-execution-sdk-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRetryStrategies.java
More file actions
132 lines (113 loc) · 5.4 KB
/
Copy pathRetryStrategies.java
File metadata and controls
132 lines (113 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.retry;
import java.time.Duration;
import software.amazon.lambda.durable.util.ParameterValidator;
/**
* Factory class for creating common retry strategies.
*
* <p>This class provides preset retry strategies for common use cases, as well as factory methods for creating custom
* retry strategies with exponential backoff and jitter.
*/
public class RetryStrategies {
/** Preset retry strategies for common use cases. */
public static class Presets {
/**
* Default retry strategy: - 6 total attempts (1 initial + 5 retries) - Initial delay: 5 seconds - Max delay: 60
* seconds - Backoff rate: 2x - Jitter: FULL
*/
public static final RetryStrategy DEFAULT = exponentialBackoff(
6, // maxAttempts
Duration.ofSeconds(5), // initialDelay
Duration.ofSeconds(60), // maxDelay
2.0, // backoffRate
JitterStrategy.FULL // jitter
);
/** Linear retry strategy: 6 total attempts (1 initial + 5 retries) with 1s, 2s, 3s, 4s, and 5s delays. */
public static final RetryStrategy LINEAR = linearBackoff(6, Duration.ofSeconds(1), Duration.ofSeconds(1));
/** No retry strategy - fails immediately on first error. Use this for operations that should not be retried. */
public static final RetryStrategy NO_RETRY = (error, attempt) -> RetryDecision.fail();
}
/**
* Creates an exponential backoff retry strategy.
*
* <p>The delay calculation follows the formula: baseDelay = min(initialDelay × backoffRate^(attempt-1), maxDelay)
*
* @param maxAttempts Maximum number of attempts (including initial attempt)
* @param initialDelay Initial delay before first retry
* @param maxDelay Maximum delay between retries
* @param backoffRate Multiplier for exponential backoff
* @param jitter Jitter strategy to apply to delays
* @return RetryStrategy implementing exponential backoff with jitter
*/
public static RetryStrategy exponentialBackoff(
int maxAttempts, Duration initialDelay, Duration maxDelay, double backoffRate, JitterStrategy jitter) {
if (maxAttempts <= 0) {
throw new IllegalArgumentException("maxAttempts must be positive");
}
ParameterValidator.validateDuration(initialDelay, "initialDelay");
ParameterValidator.validateDuration(maxDelay, "maxDelay");
if (backoffRate <= 0) {
throw new IllegalArgumentException("backoffRate must be positive");
}
return (error, attempt) -> {
// Check if we've exceeded max attempts (attemptNumber is 1-based)
if (attempt >= maxAttempts) {
return RetryDecision.fail();
}
// Calculate delay with exponential backoff
double initialDelaySeconds = initialDelay.toSeconds();
double maxDelaySeconds = maxDelay.toSeconds();
double baseDelay = Math.min(initialDelaySeconds * Math.pow(backoffRate, attempt - 1), maxDelaySeconds);
// Apply jitter
double delayWithJitter = jitter.apply(baseDelay);
// Round to nearest second, minimum 1
// Same rounding logic as TS SDK: https://tinyurl.com/4ntxsefu
long finalDelaySeconds = Math.max(1, Math.round(delayWithJitter));
return RetryDecision.retry(Duration.ofSeconds(finalDelaySeconds));
};
}
/**
* Creates a linear backoff retry strategy.
*
* <p>The delay calculation follows the formula: delay = initialDelay + increment × (attempt-1)
*
* @param maxAttempts Maximum number of attempts (including initial attempt)
* @param initialDelay Initial delay before first retry
* @param increment Amount to add to the delay after each retry attempt
* @return RetryStrategy implementing linear backoff
*/
public static RetryStrategy linearBackoff(int maxAttempts, Duration initialDelay, Duration increment) {
if (maxAttempts <= 0) {
throw new IllegalArgumentException("maxAttempts must be positive");
}
ParameterValidator.validateDuration(initialDelay, "initialDelay");
ParameterValidator.validateDuration(increment, "increment");
return (error, attempt) -> {
if (attempt >= maxAttempts) {
return RetryDecision.fail();
}
var delay = initialDelay.plus(increment.multipliedBy(attempt - 1));
return RetryDecision.retry(delay);
};
}
/**
* Creates a simple retry strategy that retries a fixed number of times with a fixed delay.
*
* @param maxAttempts Maximum number of attempts (including initial attempt)
* @param fixedDelay Fixed delay between retries
* @return RetryStrategy with fixed delay
*/
public static RetryStrategy fixedDelay(int maxAttempts, Duration fixedDelay) {
if (maxAttempts <= 0) {
throw new IllegalArgumentException("maxAttempts must be positive");
}
ParameterValidator.validateDuration(fixedDelay, "fixedDelay");
return (error, attempt) -> {
if (attempt >= maxAttempts) {
return RetryDecision.fail();
}
return RetryDecision.retry(fixedDelay);
};
}
}