Skip to content

Commit 3fff974

Browse files
michael-simonskiview
authored andcommitted
Improve WaitAllStrategy (testcontainers#1272)
1 parent 2da17b9 commit 3fff974

File tree

4 files changed

+290
-78
lines changed

4 files changed

+290
-78
lines changed

core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ private String getServiceInstanceName(String serviceName) {
335335
*/
336336
private void addWaitStrategy(String serviceInstanceName, @NonNull WaitStrategy waitStrategy) {
337337
final WaitAllStrategy waitAllStrategy = waitStrategyMap.computeIfAbsent(serviceInstanceName, __ ->
338-
(WaitAllStrategy) new WaitAllStrategy().withStartupTimeout(Duration.ofMinutes(30)));
338+
new WaitAllStrategy(WaitAllStrategy.Mode.WITH_MAXIMUM_OUTER_TIMEOUT).withStartupTimeout(Duration.ofMinutes(30)));
339339
waitAllStrategy.withStrategy(waitStrategy);
340340
}
341341

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,91 @@
11
package org.testcontainers.containers.wait.strategy;
22

3-
import org.rnorth.ducttape.timeouts.Timeouts;
4-
53
import java.time.Duration;
64
import java.util.ArrayList;
75
import java.util.List;
86
import java.util.concurrent.TimeUnit;
97

8+
import org.rnorth.ducttape.timeouts.Timeouts;
9+
1010
public class WaitAllStrategy implements WaitStrategy {
1111

12+
public enum Mode {
13+
14+
/**
15+
* This is the default mode: The timeout of the {@link WaitAllStrategy strategy} is applied to each individual
16+
* strategy, so that the container waits maximum for
17+
* {@link org.testcontainers.containers.wait.strategy.WaitAllStrategy#timeout}.
18+
*/
19+
WITH_OUTER_TIMEOUT,
20+
21+
/**
22+
* Using this mode triggers the following behaviour: The outer timeout is disabled and the outer enclosing
23+
* strategy waits for all inner strategies according to their timeout. Once set, it disables
24+
* {@link org.testcontainers.containers.wait.strategy.WaitAllStrategy#withStartupTimeout(java.time.Duration)} method,
25+
* as it would overwrite inner timeouts.
26+
*/
27+
WITH_INDIVIDUAL_TIMEOUTS_ONLY,
28+
29+
/**
30+
* This is the original mode of this strategy: The inner strategies wait with their preconfigured timeout
31+
* individually and the wait all strategy kills them, if the outer limit is reached.
32+
*/
33+
WITH_MAXIMUM_OUTER_TIMEOUT
34+
}
35+
36+
private final Mode mode;
1237
private final List<WaitStrategy> strategies = new ArrayList<>();
1338
private Duration timeout = Duration.ofSeconds(30);
1439

40+
public WaitAllStrategy() {
41+
this(Mode.WITH_OUTER_TIMEOUT);
42+
}
43+
44+
public WaitAllStrategy(Mode mode) {
45+
this.mode = mode;
46+
}
47+
1548
@Override
1649
public void waitUntilReady(WaitStrategyTarget waitStrategyTarget) {
17-
Timeouts.doWithTimeout((int) timeout.toMillis(), TimeUnit.MILLISECONDS, () -> {
18-
for (WaitStrategy strategy : strategies) {
19-
strategy.waitUntilReady(waitStrategyTarget);
20-
}
21-
});
50+
if (mode == Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY) {
51+
waitUntilNestedStrategiesAreReady(waitStrategyTarget);
52+
} else {
53+
Timeouts.doWithTimeout((int) timeout.toMillis(), TimeUnit.MILLISECONDS, () -> {
54+
waitUntilNestedStrategiesAreReady(waitStrategyTarget);
55+
});
56+
}
57+
}
58+
59+
private void waitUntilNestedStrategiesAreReady(WaitStrategyTarget waitStrategyTarget) {
60+
for (WaitStrategy strategy : strategies) {
61+
strategy.waitUntilReady(waitStrategyTarget);
62+
}
2263
}
2364

2465
public WaitAllStrategy withStrategy(WaitStrategy strategy) {
66+
67+
if (mode == Mode.WITH_OUTER_TIMEOUT) {
68+
applyStartupTimeout(strategy);
69+
}
70+
2571
this.strategies.add(strategy);
2672
return this;
2773
}
2874

2975
@Override
30-
public WaitStrategy withStartupTimeout(Duration startupTimeout) {
76+
public WaitAllStrategy withStartupTimeout(Duration startupTimeout) {
77+
78+
if (mode == Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY) {
79+
throw new IllegalStateException(String.format(
80+
"Changing startup timeout is not supported with mode %s", Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY));
81+
}
82+
3183
this.timeout = startupTimeout;
84+
strategies.forEach(this::applyStartupTimeout);
3285
return this;
3386
}
87+
88+
private void applyStartupTimeout(WaitStrategy childStrategy) {
89+
childStrategy.withStartupTimeout(this.timeout);
90+
}
3491
}

core/src/test/java/org/testcontainers/containers/wait/WaitAllStrategyTest.java

Lines changed: 0 additions & 69 deletions
This file was deleted.

0 commit comments

Comments
 (0)