Skip to content

Commit 89e8bff

Browse files
committed
Replace duct-tape with resilience4j-backed internal utilities
Removes the dependency on org.rnorth.duct-tape:duct-tape:1.0.8 by re-implementing the small subset of duct-tape used by Testcontainers inside org.testcontainers.utility, backed by resilience4j modules per maintainer preference in #9241. New runtime dependencies (shaded): - io.github.resilience4j:resilience4j-timelimiter:1.7.1 - io.github.resilience4j:resilience4j-ratelimiter:1.7.1 Internal package additions (org.testcontainers.utility): - RateLimiter (interface) + RateLimiterBuilder: thin facade with the historical duct-tape method names doWhenReady / getWhenReady, backed by a resilience4j RateLimiter adapter. The shaded resilience4j type never leaks into the public API. - Timeouts.getWithTimeout / doWithTimeout: per-call ExecutorService with daemon worker thread, shutdownNow() in finally and resilience4j TimeLimiter (cancelRunningFuture=true) — fixes the duct-tape zombie-thread bug (#9227). - Unreliables.retryUntilSuccess / retryUntilTrue: retry loop wrapped in Timeouts.getWithTimeout. Interrupt-induced exceptions (resilience4j's AcquirePermissionCancelledException, etc.) are not allowed to overwrite the genuine last failure so callers diagnose the real cause (e.g. SSLHandshakeException). - TimeoutException, RetryCountExceededException: unchecked, matching duct-tape's semantics so existing callers compile unchanged. Message "Retry limit hit with exception" is preserved verbatim for GenericContainerTest's existing assertion. Public API impact: - AbstractWaitStrategy.getRateLimiter() and withRateLimiter() now take org.testcontainers.utility.RateLimiter instead of org.rnorth.ducttape.ratelimits.RateLimiter. Source-compat is preserved for callers that go through AbstractWaitStrategy; only callers that explicitly imported the duct-tape types break. - Both methods are added to japicmp's methodExcludes with a comment explaining the binary-breaking change. Callers updated to use the new types: GenericContainer, HttpWaitStrategy, ShellStrategy, DockerHealthcheckWaitStrategy, WaitAllStrategy, StartupCheckStrategy, DockerClientProviderStrategy, RyukResourceReaper, CassandraQueryWaitStrategy (both packages), YugabyteDBY{CQL,SQL}WaitStrategy, and the corresponding tests. Refs: #9241
1 parent 3878311 commit 89e8bff

39 files changed

Lines changed: 381 additions & 61 deletions

File tree

annotations/org/rnorth/ducttape/annotations.xml

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

config/checkstyle/checkstyle.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
org.mockito.ArgumentMatchers.*,
3636
org.mockserver.model.HttpRequest.*,
3737
org.mockserver.model.HttpResponse.*,
38-
org.rnorth.ducttape.unreliables.Unreliables.*,
38+
org.testcontainers.utility.Unreliables.*,
3939
"
4040
/>
4141
</module>

core/build.gradle

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,17 @@ tasks.japicmp {
4949

5050
classExcludes = []
5151

52-
methodExcludes = []
52+
// Binary-breaking changes introduced when replacing the ducttape RateLimiter
53+
// with org.testcontainers.utility.RateLimiter. getRateLimiter()'s return type
54+
// and withRateLimiter()'s parameter type both changed from
55+
// org.rnorth.ducttape.ratelimits.RateLimiter, so japicmp flags them against
56+
// the ducttape baseline. Source-compat is preserved for callers that go
57+
// through the AbstractWaitStrategy API; only users explicitly importing the
58+
// ducttape types break.
59+
methodExcludes = [
60+
"org.testcontainers.containers.wait.strategy.AbstractWaitStrategy#getRateLimiter()",
61+
"org.testcontainers.containers.wait.strategy.AbstractWaitStrategy#withRateLimiter(org.rnorth.ducttape.ratelimits.RateLimiter)",
62+
]
5363

5464
fieldExcludes = []
5565
}
@@ -66,10 +76,6 @@ dependencies {
6676
compileOnly 'org.jetbrains:annotations:26.1.0'
6777
testCompileOnly 'org.jetbrains:annotations:26.1.0'
6878
api 'org.apache.commons:commons-compress:1.28.0'
69-
api ('org.rnorth.duct-tape:duct-tape:1.0.8') {
70-
exclude(group: 'org.jetbrains', module: 'annotations')
71-
}
72-
7379
provided('com.google.cloud.tools:jib-core:0.28.1') {
7480
exclude group: 'com.google.guava', module: 'guava'
7581
exclude group: 'com.fasterxml.jackson.datatype', module: 'jackson-datatype-jsr310'
@@ -80,6 +86,9 @@ dependencies {
8086

8187
shaded 'org.awaitility:awaitility:4.3.0'
8288

89+
shaded 'io.github.resilience4j:resilience4j-timelimiter:1.7.1'
90+
shaded 'io.github.resilience4j:resilience4j-ratelimiter:1.7.1'
91+
8392
api platform('com.github.docker-java:docker-java-bom:3.7.1')
8493
shaded platform('com.github.docker-java:docker-java-bom:3.7.1')
8594

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.apache.commons.lang3.SystemUtils;
3333
import org.jetbrains.annotations.NotNull;
3434
import org.jetbrains.annotations.Nullable;
35-
import org.rnorth.ducttape.unreliables.Unreliables;
3635
import org.slf4j.Logger;
3736
import org.testcontainers.DockerClientFactory;
3837
import org.testcontainers.UnstableAPI;
@@ -60,6 +59,7 @@
6059
import org.testcontainers.utility.PathUtils;
6160
import org.testcontainers.utility.ResourceReaper;
6261
import org.testcontainers.utility.TestcontainersConfiguration;
62+
import org.testcontainers.utility.Unreliables;
6363

6464
import java.io.File;
6565
import java.lang.reflect.InvocationTargetException;

core/src/main/java/org/testcontainers/containers/startupcheck/StartupCheckStrategy.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import com.github.dockerjava.api.DockerClient;
44
import com.github.dockerjava.api.command.InspectContainerResponse;
5-
import org.rnorth.ducttape.ratelimits.RateLimiter;
6-
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
7-
import org.rnorth.ducttape.unreliables.Unreliables;
85
import org.testcontainers.containers.GenericContainer;
6+
import org.testcontainers.utility.RateLimiter;
7+
import org.testcontainers.utility.RateLimiterBuilder;
8+
import org.testcontainers.utility.Unreliables;
99

1010
import java.time.Duration;
1111
import java.util.concurrent.TimeUnit;

core/src/main/java/org/testcontainers/containers/wait/strategy/AbstractWaitStrategy.java

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

33
import lombok.NonNull;
4-
import org.rnorth.ducttape.ratelimits.RateLimiter;
5-
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
4+
import org.testcontainers.utility.RateLimiter;
5+
import org.testcontainers.utility.RateLimiterBuilder;
66

77
import java.time.Duration;
88
import java.util.Set;

core/src/main/java/org/testcontainers/containers/wait/strategy/DockerHealthcheckWaitStrategy.java

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

3-
import org.rnorth.ducttape.TimeoutException;
4-
import org.rnorth.ducttape.unreliables.Unreliables;
53
import org.testcontainers.containers.ContainerLaunchException;
4+
import org.testcontainers.utility.TimeoutException;
5+
import org.testcontainers.utility.Unreliables;
66

77
import java.util.concurrent.TimeUnit;
88

core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import com.google.common.base.Strings;
44
import com.google.common.io.BaseEncoding;
55
import lombok.extern.slf4j.Slf4j;
6-
import org.rnorth.ducttape.TimeoutException;
76
import org.testcontainers.containers.ContainerLaunchException;
7+
import org.testcontainers.utility.TimeoutException;
88

99
import java.io.BufferedReader;
1010
import java.io.IOException;
@@ -34,7 +34,7 @@
3434
import javax.net.ssl.TrustManager;
3535
import javax.net.ssl.X509ExtendedTrustManager;
3636

37-
import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess;
37+
import static org.testcontainers.utility.Unreliables.retryUntilSuccess;
3838

3939
@Slf4j
4040
public class HttpWaitStrategy extends AbstractWaitStrategy {

core/src/main/java/org/testcontainers/containers/wait/strategy/ShellStrategy.java

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

3-
import org.rnorth.ducttape.TimeoutException;
4-
import org.rnorth.ducttape.unreliables.Unreliables;
53
import org.testcontainers.containers.ContainerLaunchException;
4+
import org.testcontainers.utility.TimeoutException;
5+
import org.testcontainers.utility.Unreliables;
66

77
import java.util.concurrent.TimeUnit;
88

core/src/main/java/org/testcontainers/containers/wait/strategy/WaitAllStrategy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package org.testcontainers.containers.wait.strategy;
22

3-
import org.rnorth.ducttape.timeouts.Timeouts;
3+
import org.testcontainers.utility.Timeouts;
44

55
import java.time.Duration;
66
import java.util.ArrayList;

0 commit comments

Comments
 (0)