1
15 package com.amazonaws.retry;
16
17 import com.amazonaws.retry.v2.BackoffStrategy;
18 import com.amazonaws.retry.v2.RetryPolicyContext;
19 import com.amazonaws.util.ValidationUtils;
20
21 import java.util.Random;
22
23
28 public class PredefinedBackoffStrategies {
29
30
33 private static final int SDK_DEFAULT_BASE_DELAY = 100;
34
35
38 static final int SDK_DEFAULT_THROTTLED_BASE_DELAY = 500;
39
40
43 static final int SDK_DEFAULT_MAX_BACKOFF_IN_MILLISECONDS = 20 * 1000;
44
45
48 static final int DYNAMODB_DEFAULT_BASE_DELAY = 25;
49
50
56 private static final int MAX_RETRIES = 30;
57
58 public static class FullJitterBackoffStrategy extends V2CompatibleBackoffStrategyAdapter {
59
60 private final int baseDelay;
61 private final int maxBackoffTime;
62 private final Random random = new Random();
63
64 public FullJitterBackoffStrategy(final int baseDelay,
65 final int maxBackoffTime) {
66 this.baseDelay = ValidationUtils.assertIsPositive(baseDelay, "Base delay");
67 this.maxBackoffTime = ValidationUtils.assertIsPositive(maxBackoffTime, "Max backoff");
68 }
69
70
71 @Override
72 public long computeDelayBeforeNextRetry(RetryPolicyContext context) {
73 int ceil = calculateExponentialDelay(context.retriesAttempted(), baseDelay, maxBackoffTime);
74 return random.nextInt(ceil);
75 }
76 }
77
78 public static class EqualJitterBackoffStrategy extends V2CompatibleBackoffStrategyAdapter {
79
80 private final int baseDelay;
81 private final int maxBackoffTime;
82 private final Random random = new Random();
83
84 public EqualJitterBackoffStrategy(final int baseDelay,
85 final int maxBackoffTime) {
86 this.baseDelay = ValidationUtils.assertIsPositive(baseDelay, "Base delay");
87 this.maxBackoffTime = ValidationUtils.assertIsPositive(maxBackoffTime, "Max backoff");
88 }
89
90 @Override
91 public long computeDelayBeforeNextRetry(RetryPolicyContext context) {
92 int ceil = calculateExponentialDelay(context.retriesAttempted(), baseDelay, maxBackoffTime);
93 return (ceil / 2) + random.nextInt((ceil / 2) + 1);
94 }
95 }
96
97 public static class ExponentialBackoffStrategy extends V2CompatibleBackoffStrategyAdapter {
98
99 private final int baseDelay;
100 private final int maxBackoffTime;
101
102 public ExponentialBackoffStrategy(final int baseDelay,
103 final int maxBackoffTime) {
104 this.baseDelay = ValidationUtils.assertIsPositive(baseDelay, "Base delay");
105 this.maxBackoffTime = ValidationUtils.assertIsPositive(maxBackoffTime, "Max backoff");
106 }
107
108 @Override
109 public long computeDelayBeforeNextRetry(RetryPolicyContext context) {
110 return calculateExponentialDelay(context.retriesAttempted(), baseDelay, maxBackoffTime);
111 }
112 }
113
114 private static int calculateExponentialDelay(int retriesAttempted, int baseDelay, int maxBackoffTime) {
115 int retries = Math.min(retriesAttempted, MAX_RETRIES);
116 return (int) Math.min((1L << retries) * baseDelay, maxBackoffTime);
117 }
118
119
120
123 public static class SDKDefaultBackoffStrategy extends V2CompatibleBackoffStrategyAdapter {
124
125 private final BackoffStrategy fullJitterBackoffStrategy;
126 private final BackoffStrategy equalJitterBackoffStrategy;
127
128 public SDKDefaultBackoffStrategy() {
129 fullJitterBackoffStrategy = new PredefinedBackoffStrategies.FullJitterBackoffStrategy(
130 SDK_DEFAULT_BASE_DELAY, SDK_DEFAULT_MAX_BACKOFF_IN_MILLISECONDS);
131 equalJitterBackoffStrategy = new PredefinedBackoffStrategies.EqualJitterBackoffStrategy(
132 SDK_DEFAULT_THROTTLED_BASE_DELAY, SDK_DEFAULT_MAX_BACKOFF_IN_MILLISECONDS);
133 }
134
135 public SDKDefaultBackoffStrategy(final int baseDelay, final int throttledBaseDelay, final int maxBackoff) {
136 fullJitterBackoffStrategy = new PredefinedBackoffStrategies.FullJitterBackoffStrategy(
137 baseDelay, maxBackoff);
138 equalJitterBackoffStrategy = new PredefinedBackoffStrategies.EqualJitterBackoffStrategy(
139 throttledBaseDelay, maxBackoff);
140 }
141
142 @Override
143 public long computeDelayBeforeNextRetry(RetryPolicyContext context) {
144
150 if (RetryUtils.isThrottlingException(context.exception())) {
151 return equalJitterBackoffStrategy.computeDelayBeforeNextRetry(context);
152 } else {
153 return fullJitterBackoffStrategy.computeDelayBeforeNextRetry(context);
154 }
155 }
156 }
157
158 }