1 | package fr.sii.ogham.core.builder.retry; | |
2 | ||
3 | import java.util.function.Predicate; | |
4 | import java.util.function.UnaryOperator; | |
5 | ||
6 | import fr.sii.ogham.core.async.Awaiter; | |
7 | import fr.sii.ogham.core.async.ThreadSleepAwaiter; | |
8 | import fr.sii.ogham.core.builder.Builder; | |
9 | import fr.sii.ogham.core.builder.context.BuildContext; | |
10 | import fr.sii.ogham.core.builder.env.EnvironmentBuilder; | |
11 | import fr.sii.ogham.core.condition.Condition; | |
12 | import fr.sii.ogham.core.fluent.AbstractParent; | |
13 | import fr.sii.ogham.core.retry.ExponentialDelayRetry; | |
14 | import fr.sii.ogham.core.retry.FixedDelayRetry; | |
15 | import fr.sii.ogham.core.retry.FixedIntervalRetry; | |
16 | import fr.sii.ogham.core.retry.PerExecutionDelayRetry; | |
17 | import fr.sii.ogham.core.retry.RetryExecutor; | |
18 | import fr.sii.ogham.core.retry.RetryStrategy; | |
19 | import fr.sii.ogham.core.retry.RetryStrategyProvider; | |
20 | import fr.sii.ogham.core.retry.SimpleRetryExecutor; | |
21 | ||
22 | /** | |
23 | * Configures retry handling. | |
24 | * | |
25 | * Ogham provides several strategies to handle retry: | |
26 | * | |
27 | * <ul> | |
28 | * <li>{@link FixedDelayRetry}: wait for a fixed delay after the last | |
29 | * failure</li> | |
30 | * <li>{@link FixedIntervalRetry}: wait for a fixed delay between executions (do | |
31 | * not wait for the end of the action)</li> | |
32 | * <li>{@link ExponentialDelayRetry}: start with a delay, the next delay will be | |
33 | * doubled on so on</li> | |
34 | * <li>{@link PerExecutionDelayRetry}: provide a custom delay for each | |
35 | * execution</li> | |
36 | * </ul> | |
37 | * | |
38 | * <p> | |
39 | * The {@link RetryExecutor} instance may be {@code null} if nothing has been | |
40 | * configured. | |
41 | * </p> | |
42 | * | |
43 | * @author Aurélien Baudet | |
44 | * | |
45 | * @param <P> | |
46 | * the type of the parent builder (when calling {@link #and()} | |
47 | * method) | |
48 | */ | |
49 | public class RetryBuilder<P> extends AbstractParent<P> implements Builder<RetryExecutor> { | |
50 | private final BuildContext buildContext; | |
51 | private FixedDelayBuilder<RetryBuilder<P>> fixedDelay; | |
52 | private ExponentialDelayBuilder<RetryBuilder<P>> exponentialDelay; | |
53 | private PerExecutionDelayBuilder<RetryBuilder<P>> perExecutionDelay; | |
54 | private FixedIntervalBuilder<RetryBuilder<P>> fixedInterval; | |
55 | private Awaiter awaiter; | |
56 | private RetryExecutor executor; | |
57 | private RetryExecutorFactory executorFactory; | |
58 | private Predicate<Throwable> retryable; | |
59 | ||
60 | /** | |
61 | * Initializes the builder with a parent builder. The parent builder is used | |
62 | * when calling {@link #and()} method. The {@link EnvironmentBuilder} is | |
63 | * used to evaluate properties when {@link #build()} method is called. | |
64 | * | |
65 | * @param parent | |
66 | * the parent builder | |
67 | * @param buildContext | |
68 | * for registering instances and property evaluation | |
69 | */ | |
70 | public RetryBuilder(P parent, BuildContext buildContext) { | |
71 | super(parent); | |
72 | this.buildContext = buildContext; | |
73 | } | |
74 | ||
75 | /** | |
76 | * Retry several times with a fixed delay between each try until the maximum | |
77 | * attempts is reached. | |
78 | * | |
79 | * For example: | |
80 | * | |
81 | * <pre> | |
82 | * .fixedDelay() | |
83 | * .delay(500) | |
84 | * .maxRetries(5) | |
85 | * </pre> | |
86 | * | |
87 | * Means that a retry will be attempted every 500ms until 5 attempts are | |
88 | * reached (inclusive). For example, you want to connect to an external | |
89 | * system at t1=0 and the connection timeout (100ms) is triggered at | |
90 | * t2=100ms. Using this retry will provide the following behavior: | |
91 | * | |
92 | * <ul> | |
93 | * <li>0: connect</li> | |
94 | * <li>100: timeout</li> | |
95 | * <li>600: connect</li> | |
96 | * <li>700: timeout</li> | |
97 | * <li>1200: connect</li> | |
98 | * <li>1300: timeout</li> | |
99 | * <li>1800: connect</li> | |
100 | * <li>1900: timeout</li> | |
101 | * <li>2400: connect</li> | |
102 | * <li>2500: timeout</li> | |
103 | * <li>3000: connect</li> | |
104 | * <li>3100: timeout</li> | |
105 | * <li>fail</li> | |
106 | * </ul> | |
107 | * | |
108 | * @return the builder to configure retry delay and maximum attempts | |
109 | */ | |
110 | public FixedDelayBuilder<RetryBuilder<P>> fixedDelay() { | |
111 |
8
1. fixedDelay : negated conditional → NO_COVERAGE 2. fixedDelay : negated conditional → KILLED 3. fixedDelay : negated conditional → KILLED 4. fixedDelay : negated conditional → KILLED 5. fixedDelay : negated conditional → KILLED 6. fixedDelay : negated conditional → KILLED 7. fixedDelay : negated conditional → KILLED 8. fixedDelay : negated conditional → KILLED |
if (fixedDelay == null) { |
112 | fixedDelay = new FixedDelayBuilder<>(this, buildContext); | |
113 | } | |
114 |
8
1. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → NO_COVERAGE 2. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → KILLED 3. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → KILLED 4. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → KILLED 5. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → KILLED 6. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → KILLED 7. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → KILLED 8. fixedDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedDelay → KILLED |
return fixedDelay; |
115 | } | |
116 | ||
117 | /** | |
118 | * Retry several times with a delay that is doubled between each try until | |
119 | * the maximum attempts is reached. | |
120 | * | |
121 | * For example: | |
122 | * | |
123 | * <pre> | |
124 | * .exponentialDelay() | |
125 | * .initialDelay(500) | |
126 | * .maxRetries(5) | |
127 | * </pre> | |
128 | * | |
129 | * Means that a retry will be attempted every 500ms until 5 attempts are | |
130 | * reached (inclusive). For example, you want to connect to an external | |
131 | * system at t1=0 and the connection timeout (100ms) is triggered at | |
132 | * t2=100ms. Using this retry will provide the following behavior: | |
133 | * | |
134 | * <ul> | |
135 | * <li>0: connect</li> | |
136 | * <li>100: timeout</li> | |
137 | * <li>600: connect</li> | |
138 | * <li>700: timeout</li> | |
139 | * <li>1700: connect</li> | |
140 | * <li>1800: timeout</li> | |
141 | * <li>3800: connect</li> | |
142 | * <li>3900: timeout</li> | |
143 | * <li>7900: connect</li> | |
144 | * <li>8000: timeout</li> | |
145 | * <li>16000: connect</li> | |
146 | * <li>16100: timeout</li> | |
147 | * <li>fail</li> | |
148 | * </ul> | |
149 | * | |
150 | * @return the builder to configure initial delay and maximum attempts | |
151 | */ | |
152 | public ExponentialDelayBuilder<RetryBuilder<P>> exponentialDelay() { | |
153 |
8
1. exponentialDelay : negated conditional → NO_COVERAGE 2. exponentialDelay : negated conditional → KILLED 3. exponentialDelay : negated conditional → KILLED 4. exponentialDelay : negated conditional → KILLED 5. exponentialDelay : negated conditional → KILLED 6. exponentialDelay : negated conditional → KILLED 7. exponentialDelay : negated conditional → KILLED 8. exponentialDelay : negated conditional → KILLED |
if (exponentialDelay == null) { |
154 | exponentialDelay = new ExponentialDelayBuilder<>(this, buildContext); | |
155 | } | |
156 |
8
1. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → NO_COVERAGE 2. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → KILLED 3. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → KILLED 4. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → KILLED 5. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → KILLED 6. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → KILLED 7. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → KILLED 8. exponentialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::exponentialDelay → KILLED |
return exponentialDelay; |
157 | } | |
158 | ||
159 | /** | |
160 | * Retry several times with a fixed delay to wait after the last execution | |
161 | * failure until the maximum attempts is reached. A specific delay is used | |
162 | * for each execution. If there are more attempts than the configured | |
163 | * delays, the last delays is used for remaining attempts. | |
164 | * | |
165 | * | |
166 | * For example: | |
167 | * | |
168 | * <pre> | |
169 | * .perExecutionDelay() | |
170 | * .delays(500, 750, 1800) | |
171 | * .maxRetries(5) | |
172 | * </pre> | |
173 | * | |
174 | * Means that a retry will be attempted with specified delays until 5 | |
175 | * attempts are reached (inclusive). For example, you want to connect to an | |
176 | * external system at t1=0 and the connection timeout (100ms) is triggered | |
177 | * at t2=100ms. Using this retry will provide the following behavior: | |
178 | * | |
179 | * <ul> | |
180 | * <li>0: connect</li> | |
181 | * <li>100: timeout</li> | |
182 | * <li>600: connect</li> | |
183 | * <li>700: timeout</li> | |
184 | * <li>1450: connect</li> | |
185 | * <li>1550: timeout</li> | |
186 | * <li>3350: connect</li> | |
187 | * <li>3450: timeout</li> | |
188 | * <li>5250: connect</li> | |
189 | * <li>5350: timeout</li> | |
190 | * <li>7150: connect</li> | |
191 | * <li>7250: timeout</li> | |
192 | * <li>fail</li> | |
193 | * </ul> | |
194 | * | |
195 | * @return the builder to configure retry delay and maximum attempts | |
196 | */ | |
197 | public PerExecutionDelayBuilder<RetryBuilder<P>> perExecutionDelay() { | |
198 |
8
1. perExecutionDelay : negated conditional → NO_COVERAGE 2. perExecutionDelay : negated conditional → KILLED 3. perExecutionDelay : negated conditional → KILLED 4. perExecutionDelay : negated conditional → KILLED 5. perExecutionDelay : negated conditional → KILLED 6. perExecutionDelay : negated conditional → KILLED 7. perExecutionDelay : negated conditional → KILLED 8. perExecutionDelay : negated conditional → KILLED |
if (perExecutionDelay == null) { |
199 | perExecutionDelay = new PerExecutionDelayBuilder<>(this, buildContext); | |
200 | } | |
201 |
8
1. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → NO_COVERAGE 2. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → KILLED 3. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → KILLED 4. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → KILLED 5. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → KILLED 6. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → KILLED 7. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → KILLED 8. perExecutionDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::perExecutionDelay → KILLED |
return perExecutionDelay; |
202 | } | |
203 | ||
204 | /** | |
205 | * Retry several times with a fixed delay between each try (no matter how | |
206 | * long the execution of the action lasts) until the maximum attempts is | |
207 | * reached. The next execution date is based on the execution start date of | |
208 | * the first execution. | |
209 | * | |
210 | * For example: | |
211 | * | |
212 | * <pre> | |
213 | * .fixedInterval() | |
214 | * .interval(500) | |
215 | * .maxRetries(5) | |
216 | * </pre> | |
217 | * | |
218 | * Means that a retry will be attempted every 500ms until 5 attempts are | |
219 | * reached (inclusive). For example, you want to connect to an external | |
220 | * system at t1=0 and the connection timeout (100ms) is triggered at | |
221 | * t2=100ms. Using this retry will provide the following behavior: | |
222 | * | |
223 | * | |
224 | * <ul> | |
225 | * <li>0: connect</li> | |
226 | * <li>100: timeout</li> | |
227 | * <li>500: connect</li> | |
228 | * <li>600: timeout</li> | |
229 | * <li>1000: connect</li> | |
230 | * <li>1100: timeout</li> | |
231 | * <li>1500: connect</li> | |
232 | * <li>1600: timeout</li> | |
233 | * <li>2000: connect</li> | |
234 | * <li>2100: timeout</li> | |
235 | * <li>2500: connect</li> | |
236 | * <li>2600: timeout</li> | |
237 | * <li>fail</li> | |
238 | * </ul> | |
239 | * | |
240 | * | |
241 | * <strong>NOTE:</strong> The provided date doesn't take the duration of the | |
242 | * execution in account. If an execution takes 1s to execute while retry | |
243 | * delay is set to 500ms, there may have several executions in parallel. | |
244 | * However, this totally depends on the {@link RetryExecutor} | |
245 | * implementation. For example {@link SimpleRetryExecutor} won't run several | |
246 | * executions in parallel. In this case, it will execute the action as soon | |
247 | * as the previous one has failed therefore the delay may not be complied. | |
248 | * | |
249 | * @return the builder to configure retry delay and maximum attempts | |
250 | */ | |
251 | public FixedIntervalBuilder<RetryBuilder<P>> fixedInterval() { | |
252 |
8
1. fixedInterval : negated conditional → NO_COVERAGE 2. fixedInterval : negated conditional → KILLED 3. fixedInterval : negated conditional → KILLED 4. fixedInterval : negated conditional → KILLED 5. fixedInterval : negated conditional → KILLED 6. fixedInterval : negated conditional → KILLED 7. fixedInterval : negated conditional → KILLED 8. fixedInterval : negated conditional → KILLED |
if (fixedInterval == null) { |
253 | fixedInterval = new FixedIntervalBuilder<>(this, buildContext); | |
254 | } | |
255 |
8
1. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → NO_COVERAGE 2. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → KILLED 3. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → KILLED 4. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → KILLED 5. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → KILLED 6. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → KILLED 7. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → KILLED 8. fixedInterval : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::fixedInterval → KILLED |
return fixedInterval; |
256 | } | |
257 | ||
258 | /** | |
259 | * Change implementation used to wait for some delay between retries. | |
260 | * | |
261 | * By default, {@link ThreadSleepAwaiter} is used (internally uses | |
262 | * {@link Thread#sleep(long)} to wait for some point in time. | |
263 | * | |
264 | * @param impl | |
265 | * the custom implementation | |
266 | * @return this instance for fluent chaining | |
267 | */ | |
268 | public RetryBuilder<P> awaiter(Awaiter impl) { | |
269 | this.awaiter = impl; | |
270 |
1
1. awaiter : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::awaiter → NO_COVERAGE |
return this; |
271 | } | |
272 | ||
273 | /** | |
274 | * Use custom executor instead of default one ({@link SimpleRetryExecutor}). | |
275 | * | |
276 | * <p> | |
277 | * <strong>NOTE:</strong> Using custom executor doesn't take retry | |
278 | * strategies into account. If you want to benefit from | |
279 | * {@link RetryStrategy}s, use {@link #executor(RetryExecutorFactory)} | |
280 | * instead. | |
281 | * | |
282 | * <p> | |
283 | * If {@link #executor(RetryExecutorFactory)} is also called, only the | |
284 | * executor defined by this method is used and the factory is not used. | |
285 | * | |
286 | * <p> | |
287 | * If this method is called several times, only the last value is used. | |
288 | * | |
289 | * <p> | |
290 | * If you call with {@code null}, it removes any previous custom executor. | |
291 | * | |
292 | * @param executor | |
293 | * the executor to use | |
294 | * @return this builder for fluent chaining | |
295 | */ | |
296 | public RetryBuilder<P> executor(RetryExecutor executor) { | |
297 | this.executor = executor; | |
298 |
1
1. executor : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::executor → NO_COVERAGE |
return this; |
299 | } | |
300 | ||
301 | /** | |
302 | * Use a factory to create an instance of {@link RetryExecutor} while | |
303 | * benefiting from configured {@link RetryStrategy}. | |
304 | * | |
305 | * <p> | |
306 | * The factory will receive the ready to use {@link RetryStrategyProvider} | |
307 | * and the built {@link Awaiter}. | |
308 | * | |
309 | * <p> | |
310 | * If {@link #executor(RetryExecutor)} is also configured, the factory is | |
311 | * not used. | |
312 | * | |
313 | * <p> | |
314 | * If this method is called several times, only the last factory is used. | |
315 | * | |
316 | * <p> | |
317 | * If you call with {@code null}, it removes any previous configured | |
318 | * factory. | |
319 | * | |
320 | * @param factory | |
321 | * the factory used to create the {@link RetryExecutor} instance | |
322 | * @return this instance for fluent chaining | |
323 | */ | |
324 | public RetryBuilder<P> executor(RetryExecutorFactory factory) { | |
325 | this.executorFactory = factory; | |
326 |
2
1. executor : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::executor → NO_COVERAGE 2. executor : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::executor → KILLED |
return this; |
327 | } | |
328 | ||
329 | /** | |
330 | * A predicate that checks if the raised error should allow another retry or | |
331 | * not. This is useful when an error is raised and the error is severe so it | |
332 | * should stop immediately. | |
333 | * | |
334 | * <p> | |
335 | * The predicate returns {@code true} if the exception is not fatal and a | |
336 | * retry may be attempted. It returns {@code false} if the exception is | |
337 | * fatal and no more attempt should be executed and retry must stop | |
338 | * immediately. | |
339 | * | |
340 | * <p> | |
341 | * If {@code null} is passed to this method, it removes any previously | |
342 | * defined predicate. Therefore the default predicate is used: all | |
343 | * {@link Exception}s are considered retryable but not {@link Error}s. | |
344 | * | |
345 | * @param retryable | |
346 | * the predicate that returns true if the exception is not fatal | |
347 | * and a retry can be attempted | |
348 | * @return this instance for fluent chaining | |
349 | */ | |
350 | public RetryBuilder<P> retryable(Predicate<Throwable> retryable) { | |
351 | this.retryable = retryable; | |
352 |
7
1. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → NO_COVERAGE 2. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → SURVIVED 3. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → KILLED 4. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → KILLED 5. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → KILLED 6. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → KILLED 7. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → KILLED |
return this; |
353 | } | |
354 | ||
355 | /** | |
356 | * Combine the current configured predicate with another. | |
357 | * | |
358 | * <p> | |
359 | * This may be useful when an implementation wants to add additional checks | |
360 | * to the ones configured by Ogham core or other implementations. | |
361 | * | |
362 | * <p> | |
363 | * If no predicate is currently configured, a predicate that accepts | |
364 | * everything is provided. | |
365 | * | |
366 | * <p> | |
367 | * <strong>NOTE:</strong> This is advanced usage mostly for developers that | |
368 | * extend Ogham with new implementations. | |
369 | * | |
370 | * @param merger | |
371 | * a function used to merge predicates | |
372 | * @return this instance for fluent chaining | |
373 | */ | |
374 | public RetryBuilder<P> retryable(UnaryOperator<Predicate<Throwable>> merger) { | |
375 |
5
1. lambda$retryable$0 : replaced boolean return with false for fr/sii/ogham/core/builder/retry/RetryBuilder::lambda$retryable$0 → NO_COVERAGE 2. retryable : negated conditional → SURVIVED 3. retryable : negated conditional → NO_COVERAGE 4. retryable : negated conditional → KILLED 5. retryable : negated conditional → KILLED |
retryable = merger.apply(retryable == null ? (error -> true) : retryable); |
376 |
2
1. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → NO_COVERAGE 2. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → SURVIVED |
return this; |
377 | } | |
378 | ||
379 | /** | |
380 | * A condition that checks if the raised error should allow another retry or | |
381 | * not. This is useful when an error is raised and the error is severe so it | |
382 | * should stop immediately. | |
383 | * | |
384 | * <p> | |
385 | * The condition returns {@code true} if the exception is not fatal and a | |
386 | * retry may be attempted. It returns {@code false} if the exception is | |
387 | * fatal and no more attempt should be executed and retry must stop | |
388 | * immediately. | |
389 | * | |
390 | * <p> | |
391 | * If {@code null} is passed to this method, it removes any previously | |
392 | * defined condition. Therefore the default condition is used: all | |
393 | * {@link Exception}s are considered retryable but not {@link Error}s. | |
394 | * | |
395 | * <p> | |
396 | * This method internally calls {@link #retryable(Predicate)}. | |
397 | * | |
398 | * @param retryable | |
399 | * the condition that returns true if the exception is not fatal | |
400 | * and a retry can be attempted | |
401 | * @return this instance for fluent chaining | |
402 | */ | |
403 | @SuppressWarnings("squid:S1905") | |
404 | public RetryBuilder<P> retryable(Condition<Throwable> retryable) { | |
405 |
2
1. retryable : negated conditional → NO_COVERAGE 2. retryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::retryable → NO_COVERAGE |
return retryable(retryable == null ? (Predicate<Throwable>) null : retryable::accept); |
406 | } | |
407 | ||
408 | @Override | |
409 | public RetryExecutor build() { | |
410 |
5
1. build : negated conditional → NO_COVERAGE 2. build : negated conditional → SURVIVED 3. build : negated conditional → KILLED 4. build : negated conditional → KILLED 5. build : negated conditional → KILLED |
if (executor != null) { |
411 |
1
1. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → NO_COVERAGE |
return executor; |
412 | } | |
413 | Builder<RetryStrategy> retryStrategy = buildRetryStrategy(); | |
414 |
8
1. build : negated conditional → NO_COVERAGE 2. build : negated conditional → SURVIVED 3. build : negated conditional → KILLED 4. build : negated conditional → KILLED 5. build : negated conditional → KILLED 6. build : negated conditional → KILLED 7. build : negated conditional → KILLED 8. build : negated conditional → KILLED |
if (retryStrategy == null) { |
415 | return null; | |
416 | } | |
417 | BuilderToRetryStrategyProviderBridge retryProvider = new BuilderToRetryStrategyProviderBridge(retryStrategy); | |
418 | Awaiter builtAwaiter = buildAwaiter(); | |
419 |
7
1. build : negated conditional → NO_COVERAGE 2. build : negated conditional → KILLED 3. build : negated conditional → KILLED 4. build : negated conditional → KILLED 5. build : negated conditional → KILLED 6. build : negated conditional → KILLED 7. build : negated conditional → KILLED |
if (executorFactory != null) { |
420 |
2
1. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → SURVIVED 2. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → NO_COVERAGE |
return executorFactory.create(retryProvider, builtAwaiter); |
421 | } | |
422 |
5
1. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → NO_COVERAGE 2. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → SURVIVED 3. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → KILLED 4. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → KILLED 5. build : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::build → KILLED |
return buildContext.register(new SimpleRetryExecutor(retryProvider, builtAwaiter, buildRetryable())); |
423 | } | |
424 | ||
425 | private Builder<RetryStrategy> buildRetryStrategy() { | |
426 |
6
1. buildRetryStrategy : negated conditional → NO_COVERAGE 2. buildRetryStrategy : negated conditional → SURVIVED 3. buildRetryStrategy : negated conditional → KILLED 4. buildRetryStrategy : negated conditional → KILLED 5. buildRetryStrategy : negated conditional → KILLED 6. buildRetryStrategy : negated conditional → KILLED |
if (isConfigured(perExecutionDelay)) { |
427 |
3
1. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → NO_COVERAGE 2. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → KILLED 3. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → KILLED |
return perExecutionDelay; |
428 | } | |
429 |
6
1. buildRetryStrategy : negated conditional → NO_COVERAGE 2. buildRetryStrategy : negated conditional → SURVIVED 3. buildRetryStrategy : negated conditional → KILLED 4. buildRetryStrategy : negated conditional → KILLED 5. buildRetryStrategy : negated conditional → KILLED 6. buildRetryStrategy : negated conditional → KILLED |
if (isConfigured(exponentialDelay)) { |
430 |
2
1. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → NO_COVERAGE 2. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → KILLED |
return exponentialDelay; |
431 | } | |
432 |
6
1. buildRetryStrategy : negated conditional → NO_COVERAGE 2. buildRetryStrategy : negated conditional → SURVIVED 3. buildRetryStrategy : negated conditional → KILLED 4. buildRetryStrategy : negated conditional → KILLED 5. buildRetryStrategy : negated conditional → KILLED 6. buildRetryStrategy : negated conditional → KILLED |
if (isConfigured(fixedInterval)) { |
433 |
2
1. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → NO_COVERAGE 2. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → KILLED |
return fixedInterval; |
434 | } | |
435 |
6
1. buildRetryStrategy : negated conditional → NO_COVERAGE 2. buildRetryStrategy : negated conditional → SURVIVED 3. buildRetryStrategy : negated conditional → KILLED 4. buildRetryStrategy : negated conditional → KILLED 5. buildRetryStrategy : negated conditional → KILLED 6. buildRetryStrategy : negated conditional → KILLED |
if (isConfigured(fixedDelay)) { |
436 |
5
1. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → SURVIVED 2. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → NO_COVERAGE 3. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → KILLED 4. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → KILLED 5. buildRetryStrategy : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryStrategy → KILLED |
return fixedDelay; |
437 | } | |
438 | return null; | |
439 | } | |
440 | ||
441 | private static boolean isConfigured(Builder<RetryStrategy> builder) { | |
442 |
5
1. isConfigured : negated conditional → SURVIVED 2. isConfigured : negated conditional → NO_COVERAGE 3. isConfigured : negated conditional → KILLED 4. isConfigured : negated conditional → KILLED 5. isConfigured : negated conditional → KILLED |
if (builder == null) { |
443 |
3
1. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → NO_COVERAGE 2. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → TIMED_OUT 3. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → KILLED |
return false; |
444 | } | |
445 |
12
1. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → SURVIVED 2. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → NO_COVERAGE 3. isConfigured : negated conditional → NO_COVERAGE 4. isConfigured : negated conditional → SURVIVED 5. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → KILLED 6. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → KILLED 7. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → KILLED 8. isConfigured : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::isConfigured → KILLED 9. isConfigured : negated conditional → KILLED 10. isConfigured : negated conditional → KILLED 11. isConfigured : negated conditional → KILLED 12. isConfigured : negated conditional → KILLED |
return builder.build() != null; |
446 | } | |
447 | ||
448 | private Awaiter buildAwaiter() { | |
449 |
5
1. buildAwaiter : negated conditional → NO_COVERAGE 2. buildAwaiter : negated conditional → SURVIVED 3. buildAwaiter : negated conditional → TIMED_OUT 4. buildAwaiter : negated conditional → KILLED 5. buildAwaiter : negated conditional → KILLED |
if (awaiter == null) { |
450 |
5
1. buildAwaiter : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildAwaiter → NO_COVERAGE 2. buildAwaiter : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildAwaiter → SURVIVED 3. buildAwaiter : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildAwaiter → TIMED_OUT 4. buildAwaiter : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildAwaiter → KILLED 5. buildAwaiter : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildAwaiter → KILLED |
return new ThreadSleepAwaiter(); |
451 | } | |
452 |
1
1. buildAwaiter : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildAwaiter → NO_COVERAGE |
return awaiter; |
453 | } | |
454 | ||
455 | private Predicate<Throwable> buildRetryable() { | |
456 |
5
1. buildRetryable : negated conditional → NO_COVERAGE 2. buildRetryable : negated conditional → SURVIVED 3. buildRetryable : negated conditional → KILLED 4. buildRetryable : negated conditional → KILLED 5. buildRetryable : negated conditional → KILLED |
if (retryable == null) { |
457 |
6
1. buildRetryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryable → NO_COVERAGE 2. lambda$buildRetryable$1 : replaced boolean return with false for fr/sii/ogham/core/builder/retry/RetryBuilder::lambda$buildRetryable$1 → NO_COVERAGE 3. lambda$buildRetryable$1 : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::lambda$buildRetryable$1 → SURVIVED 4. lambda$buildRetryable$1 : replaced boolean return with true for fr/sii/ogham/core/builder/retry/RetryBuilder::lambda$buildRetryable$1 → NO_COVERAGE 5. buildRetryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryable → TIMED_OUT 6. lambda$buildRetryable$1 : replaced boolean return with false for fr/sii/ogham/core/builder/retry/RetryBuilder::lambda$buildRetryable$1 → TIMED_OUT |
return e -> e instanceof Exception; |
458 | } | |
459 |
5
1. buildRetryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryable → NO_COVERAGE 2. buildRetryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryable → SURVIVED 3. buildRetryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryable → KILLED 4. buildRetryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryable → KILLED 5. buildRetryable : replaced return value with null for fr/sii/ogham/core/builder/retry/RetryBuilder::buildRetryable → KILLED |
return retryable; |
460 | } | |
461 | } | |
Mutations | ||
111 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
114 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
153 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
156 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
198 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
201 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
252 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
255 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
270 |
1.1 |
|
298 |
1.1 |
|
326 |
1.1 2.2 |
|
352 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
375 |
1.1 2.2 3.3 4.4 5.5 |
|
376 |
1.1 2.2 |
|
405 |
1.1 2.2 |
|
410 |
1.1 2.2 3.3 4.4 5.5 |
|
411 |
1.1 |
|
414 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
419 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
420 |
1.1 2.2 |
|
422 |
1.1 2.2 3.3 4.4 5.5 |
|
426 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
427 |
1.1 2.2 3.3 |
|
429 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
430 |
1.1 2.2 |
|
432 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
433 |
1.1 2.2 |
|
435 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
436 |
1.1 2.2 3.3 4.4 5.5 |
|
442 |
1.1 2.2 3.3 4.4 5.5 |
|
443 |
1.1 2.2 3.3 |
|
445 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.10 11.11 12.12 |
|
449 |
1.1 2.2 3.3 4.4 5.5 |
|
450 |
1.1 2.2 3.3 4.4 5.5 |
|
452 |
1.1 |
|
456 |
1.1 2.2 3.3 4.4 5.5 |
|
457 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
459 |
1.1 2.2 3.3 4.4 5.5 |