ExponentialDelayBuilder.java

1
package fr.sii.ogham.core.builder.retry;
2
3
import fr.sii.ogham.core.builder.Builder;
4
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilder;
5
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilderHelper;
6
import fr.sii.ogham.core.builder.configurer.Configurer;
7
import fr.sii.ogham.core.builder.context.BuildContext;
8
import fr.sii.ogham.core.builder.env.EnvironmentBuilder;
9
import fr.sii.ogham.core.fluent.AbstractParent;
10
import fr.sii.ogham.core.retry.ExponentialDelayRetry;
11
import fr.sii.ogham.core.retry.RetryStrategy;
12
13
/**
14
 * Configures retry handling based on an exponential delay.
15
 * 
16
 * Retry several times with a delay that is doubled between each try until the
17
 * maximum attempts is reached.
18
 * 
19
 * For example:
20
 * 
21
 * <pre>
22
 * .initialDelay(500)
23
 * .maxRetries(5)
24
 * </pre>
25
 * 
26
 * 
27
 * Means that a retry will be attempted every 500ms until 5 attempts are reached
28
 * (inclusive). For example, you want to connect to an external system at t1=0
29
 * and the connection timeout (100ms) is triggered at t2=100ms. Using this retry
30
 * will provide the following behavior:
31
 * 
32
 * <ul>
33
 * <li>0: connect</li>
34
 * <li>100: timeout</li>
35
 * <li>600: connect</li>
36
 * <li>700: timeout</li>
37
 * <li>1700: connect</li>
38
 * <li>1800: timeout</li>
39
 * <li>3800: connect</li>
40
 * <li>3900: timeout</li>
41
 * <li>7900: connect</li>
42
 * <li>8000: timeout</li>
43
 * <li>16000: connect</li>
44
 * <li>16100: timeout</li>
45
 * <li>fail</li>
46
 * </ul>
47
 * 
48
 * 
49
 * @author Aurélien Baudet
50
 *
51
 * @param <P>
52
 *            the type of the parent builder (when calling {@link #and()}
53
 *            method)
54
 */
55
public class ExponentialDelayBuilder<P> extends AbstractParent<P> implements Builder<RetryStrategy> {
56
	private final BuildContext buildContext;
57
	private final ConfigurationValueBuilderHelper<ExponentialDelayBuilder<P>, Integer> maxRetriesValueBuilder;
58
	private final ConfigurationValueBuilderHelper<ExponentialDelayBuilder<P>, Long> initialDelayValueBuilder;
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 ExponentialDelayBuilder(P parent, BuildContext buildContext) {
71
		super(parent);
72
		this.buildContext = buildContext;
73
		maxRetriesValueBuilder = buildContext.newConfigurationValueBuilder(this, Integer.class);
74
		initialDelayValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
75
	}
76
77
	/**
78
	 * Set the maximum number of attempts.
79
	 * 
80
	 * <p>
81
	 * The value set using this method takes precedence over any property and
82
	 * default value configured using {@link #maxRetries()}.
83
	 * 
84
	 * <pre>
85
	 * .maxRetries(10)
86
	 * .maxRetries()
87
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
88
	 *   .defaultValue(5)
89
	 * </pre>
90
	 * 
91
	 * <pre>
92
	 * .maxRetries(10)
93
	 * .maxRetries()
94
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
95
	 *   .defaultValue(5)
96
	 * </pre>
97
	 * 
98
	 * In both cases, {@code maxRetries(10)} is used.
99
	 * 
100
	 * <p>
101
	 * If this method is called several times, only the last value is used.
102
	 * 
103
	 * <p>
104
	 * If {@code null} value is set, it is like not setting a value at all. The
105
	 * property/default value configuration is applied.
106
	 * 
107
	 * @param maxRetries
108
	 *            the maximum number of attempts
109
	 * @return this instance for fluent chaining
110
	 */
111
	public ExponentialDelayBuilder<P> maxRetries(Integer maxRetries) {
112 2 1. maxRetries : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → NO_COVERAGE
2. maxRetries : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → KILLED
		this.maxRetriesValueBuilder.setValue(maxRetries);
113 2 1. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → NO_COVERAGE
2. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
		return this;
114
	}
115
116
	/**
117
	 * Set the maximum number of attempts.
118
	 * 
119
	 * <p>
120
	 * This method is mainly used by {@link Configurer}s to register some
121
	 * property keys and/or a default value. The aim is to let developer be able
122
	 * to externalize its configuration (using system properties, configuration
123
	 * file or anything else). If the developer doesn't configure any value for
124
	 * the registered properties, the default value is used (if set).
125
	 * 
126
	 * <pre>
127
	 * .maxRetries()
128
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
129
	 *   .defaultValue(5)
130
	 * </pre>
131
	 * 
132
	 * <p>
133
	 * Non-null value set using {@link #maxRetries(Integer)} takes precedence
134
	 * over property values and default value.
135
	 * 
136
	 * <pre>
137
	 * .maxRetries(10)
138
	 * .maxRetries()
139
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
140
	 *   .defaultValue(5)
141
	 * </pre>
142
	 * 
143
	 * The value {@code 10} is used regardless of the value of the properties
144
	 * and default value.
145
	 * 
146
	 * <p>
147
	 * See {@link ConfigurationValueBuilder} for more information.
148
	 * 
149
	 * 
150
	 * @return the builder to configure property keys/default value
151
	 */
152
	public ConfigurationValueBuilder<ExponentialDelayBuilder<P>, Integer> maxRetries() {
153 8 1. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → NO_COVERAGE
2. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
3. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
4. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
5. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
6. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
7. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
8. maxRetries : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED
		return maxRetriesValueBuilder;
154
	}
155
156
	/**
157
	 * Set the initial delay between two executions (in milliseconds). It will be doubled
158
	 * for each try.
159
	 * 
160
	 * <p>
161
	 * The value set using this method takes precedence over any property and
162
	 * default value configured using {@link #initialDelay()}.
163
	 * 
164
	 * <pre>
165
	 * .initialDelay(5000L)
166
	 * .initialDelay()
167
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
168
	 *   .defaultValue(10000L)
169
	 * </pre>
170
	 * 
171
	 * <pre>
172
	 * .initialDelay(5000L)
173
	 * .initialDelay()
174
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
175
	 *   .defaultValue(10000L)
176
	 * </pre>
177
	 * 
178
	 * In both cases, {@code initialDelay(5000L)} is used.
179
	 * 
180
	 * <p>
181
	 * If this method is called several times, only the last value is used.
182
	 * 
183
	 * <p>
184
	 * If {@code null} value is set, it is like not setting a value at all. The
185
	 * property/default value configuration is applied.
186
	 * 
187
	 * @param initialDelay
188
	 *            the time between two attempts
189
	 * @return this instance for fluent chaining
190
	 */
191
	public ExponentialDelayBuilder<P> initialDelay(Long initialDelay) {
192 2 1. initialDelay : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → NO_COVERAGE
2. initialDelay : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → KILLED
		initialDelayValueBuilder.setValue(initialDelay);
193 2 1. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → NO_COVERAGE
2. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
		return this;
194
	}
195
196
	/**
197
	 * Set the initial delay between two executions (in milliseconds). It will be doubled
198
	 * for each try.
199
	 * 
200
	 * <p>
201
	 * This method is mainly used by {@link Configurer}s to register some
202
	 * property keys and/or a default value. The aim is to let developer be able
203
	 * to externalize its configuration (using system properties, configuration
204
	 * file or anything else). If the developer doesn't configure any value for
205
	 * the registered properties, the default value is used (if set).
206
	 * 
207
	 * <pre>
208
	 * .initialDelay()
209
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
210
	 *   .defaultValue(10000L)
211
	 * </pre>
212
	 * 
213
	 * <p>
214
	 * Non-null value set using {@link #initialDelay(Long)} takes precedence over
215
	 * property values and default value.
216
	 * 
217
	 * <pre>
218
	 * .initialDelay(5000L)
219
	 * .initialDelay()
220
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
221
	 *   .defaultValue(10000L)
222
	 * </pre>
223
	 * 
224
	 * The value {@code 5000L} is used regardless of the value of the properties
225
	 * and default value.
226
	 * 
227
	 * <p>
228
	 * See {@link ConfigurationValueBuilder} for more information.
229
	 * 
230
	 * 
231
	 * @return the builder to configure property keys/default value
232
	 */
233
	public ConfigurationValueBuilder<ExponentialDelayBuilder<P>, Long> initialDelay() {
234 8 1. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → NO_COVERAGE
2. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
3. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
4. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
5. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
6. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
7. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
8. initialDelay : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED
		return initialDelayValueBuilder;
235
	}
236
237
	@Override
238
	public RetryStrategy build() {
239
		int evaluatedMaxRetries = buildMaxRetries();
240
		long evaluatedInitialDelay = buildInitialDelay();
241 7 1. build : negated conditional → SURVIVED
2. build : negated conditional → NO_COVERAGE
3. build : negated conditional → NO_COVERAGE
4. build : negated conditional → SURVIVED
5. build : negated conditional → TIMED_OUT
6. build : negated conditional → KILLED
7. build : negated conditional → KILLED
		if (evaluatedMaxRetries == 0 || evaluatedInitialDelay == 0) {
242
			return null;
243
		}
244 2 1. build : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::build → NO_COVERAGE
2. build : replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::build → KILLED
		return buildContext.register(new ExponentialDelayRetry(evaluatedMaxRetries, evaluatedInitialDelay));
245
	}
246
247
	private int buildMaxRetries() {
248 3 1. buildMaxRetries : replaced int return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildMaxRetries → SURVIVED
2. buildMaxRetries : replaced int return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildMaxRetries → NO_COVERAGE
3. buildMaxRetries : replaced int return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildMaxRetries → KILLED
		return maxRetriesValueBuilder.getValue(0);
249
	}
250
251
	private long buildInitialDelay() {
252 3 1. buildInitialDelay : replaced long return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildInitialDelay → NO_COVERAGE
2. buildInitialDelay : replaced long return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildInitialDelay → SURVIVED
3. buildInitialDelay : replaced long return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildInitialDelay → KILLED
		return initialDelayValueBuilder.getValue(0L);
253
	}
254
}

Mutations

112

1.1
Location : maxRetries
Killed by : none
removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → NO_COVERAGE

2.2
Location : maxRetries
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → KILLED

113

1.1
Location : maxRetries
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → NO_COVERAGE

2.2
Location : maxRetries
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

153

1.1
Location : maxRetries
Killed by : oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests.oghamAloneShouldUseOghamProperties(oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

2.2
Location : maxRetries
Killed by : oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests.oghamPropertiesWithSpringPropsShouldUseOghamPropertiesPrecedence(oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

3.3
Location : maxRetries
Killed by : oghamcloudhopper.it.AutoRetryExtensionTest.smsNotRetriedDueToCloudhopperError(oghamcloudhopper.it.AutoRetryExtensionTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

4.4
Location : maxRetries
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → NO_COVERAGE

5.5
Location : maxRetries
Killed by : oghamcore.it.core.service.CleanupTest.manualCleanupShouldAutomaticallyCleanTheSenders(oghamcore.it.core.service.CleanupTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

6.6
Location : maxRetries
Killed by : oghamjavamail.it.UnreadableAttachmentTest.attachmentUnreadable(oghamjavamail.it.UnreadableAttachmentTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

7.7
Location : maxRetries
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

8.8
Location : maxRetries
Killed by : oghamall.it.html.translator.JsoupInlineCssTranslatorTest.notHtml(oghamall.it.html.translator.JsoupInlineCssTranslatorTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::maxRetries → KILLED

192

1.1
Location : initialDelay
Killed by : none
removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → NO_COVERAGE

2.2
Location : initialDelay
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → KILLED

193

1.1
Location : initialDelay
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → NO_COVERAGE

2.2
Location : initialDelay
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

234

1.1
Location : initialDelay
Killed by : oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests.oghamPropertiesWithSpringPropsShouldUseOghamPropertiesPrecedence(oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

2.2
Location : initialDelay
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → NO_COVERAGE

3.3
Location : initialDelay
Killed by : oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests.oghamAloneShouldUseOghamProperties(oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

4.4
Location : initialDelay
Killed by : oghamcloudhopper.it.AutoRetryExtensionTest.smsNotRetriedDueToCloudhopperError(oghamcloudhopper.it.AutoRetryExtensionTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

5.5
Location : initialDelay
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

6.6
Location : initialDelay
Killed by : oghamall.it.html.translator.JsoupInlineCssTranslatorTest.notHtml(oghamall.it.html.translator.JsoupInlineCssTranslatorTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

7.7
Location : initialDelay
Killed by : oghamcore.it.core.service.CleanupTest.manualCleanupShouldAutomaticallyCleanTheSenders(oghamcore.it.core.service.CleanupTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

8.8
Location : initialDelay
Killed by : oghamjavamail.it.UnreadableAttachmentTest.attachmentUnreadable(oghamjavamail.it.UnreadableAttachmentTest)
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::initialDelay → KILLED

241

1.1
Location : build
Killed by : none
negated conditional → SURVIVED

2.2
Location : build
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : build
Killed by : none
negated conditional → TIMED_OUT

4.4
Location : build
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
negated conditional → KILLED

5.5
Location : build
Killed by : none
negated conditional → NO_COVERAGE

6.6
Location : build
Killed by : none
negated conditional → SURVIVED

7.7
Location : build
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
negated conditional → KILLED

244

1.1
Location : build
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::build → NO_COVERAGE

2.2
Location : build
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
replaced return value with null for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::build → KILLED

248

1.1
Location : buildMaxRetries
Killed by : none
replaced int return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildMaxRetries → SURVIVED

2.2
Location : buildMaxRetries
Killed by : none
replaced int return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildMaxRetries → NO_COVERAGE

3.3
Location : buildMaxRetries
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
replaced int return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildMaxRetries → KILLED

252

1.1
Location : buildInitialDelay
Killed by : none
replaced long return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildInitialDelay → NO_COVERAGE

2.2
Location : buildInitialDelay
Killed by : oghamcore.it.core.builder.retry.RetryBuilderSpec
replaced long return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildInitialDelay → KILLED

3.3
Location : buildInitialDelay
Killed by : none
replaced long return with 0 for fr/sii/ogham/core/builder/retry/ExponentialDelayBuilder::buildInitialDelay → SURVIVED

Active mutators

Tests examined


Report generated by PIT OGHAM