Skip to content

Commit

Permalink
[Bug]: duct-tape:1.0.8 contains a Thread Leak
Browse files Browse the repository at this point in the history
1st step: move code from the archived repository

Related to testcontainers#9227.
  • Loading branch information
dadoonet committed Sep 16, 2024
1 parent 0217e78 commit 259ad3a
Show file tree
Hide file tree
Showing 45 changed files with 455 additions and 57 deletions.
3 changes: 0 additions & 3 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ dependencies {
compileOnly 'org.jetbrains:annotations:24.1.0'
testCompileOnly 'org.jetbrains:annotations:24.1.0'
api 'org.apache.commons:commons-compress:1.24.0'
api ('org.rnorth.duct-tape:duct-tape:1.0.8') {
exclude(group: 'org.jetbrains', module: 'annotations')
}

provided('com.google.cloud.tools:jib-core:0.23.0') {
exclude group: 'com.google.guava', module: 'guava'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@
import org.jetbrains.annotations.Nullable;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.rnorth.ducttape.ratelimits.RateLimiter;
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
import org.rnorth.ducttape.unreliables.Unreliables;
import org.slf4j.Logger;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.UnstableAPI;
Expand Down Expand Up @@ -66,6 +63,9 @@
import org.testcontainers.utility.PathUtils;
import org.testcontainers.utility.ResourceReaper;
import org.testcontainers.utility.TestcontainersConfiguration;
import org.testcontainers.utility.ducttape.RateLimiter;
import org.testcontainers.utility.ducttape.RateLimiterBuilder;
import org.testcontainers.utility.ducttape.Unreliables;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.InspectContainerResponse;
import org.rnorth.ducttape.ratelimits.RateLimiter;
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
import org.rnorth.ducttape.unreliables.Unreliables;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.ducttape.RateLimiter;
import org.testcontainers.utility.ducttape.RateLimiterBuilder;
import org.testcontainers.utility.ducttape.Unreliables;

import java.time.Duration;
import java.util.concurrent.TimeUnit;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.testcontainers.containers.wait.strategy;

import lombok.NonNull;
import org.rnorth.ducttape.ratelimits.RateLimiter;
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
import org.testcontainers.utility.ducttape.RateLimiter;
import org.testcontainers.utility.ducttape.RateLimiterBuilder;

import java.time.Duration;
import java.util.Set;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.testcontainers.containers.wait.strategy;

import org.rnorth.ducttape.TimeoutException;
import org.rnorth.ducttape.unreliables.Unreliables;
import org.testcontainers.utility.ducttape.TimeoutException;
import org.testcontainers.utility.ducttape.Unreliables;
import org.testcontainers.containers.ContainerLaunchException;

import java.util.concurrent.TimeUnit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.google.common.base.Strings;
import com.google.common.io.BaseEncoding;
import lombok.extern.slf4j.Slf4j;
import org.rnorth.ducttape.TimeoutException;
import org.testcontainers.utility.ducttape.TimeoutException;
import org.testcontainers.containers.ContainerLaunchException;

import java.io.BufferedReader;
Expand Down Expand Up @@ -34,7 +34,7 @@
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedTrustManager;

import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess;
import static org.testcontainers.utility.ducttape.Unreliables.retryUntilSuccess;

@Slf4j
public class HttpWaitStrategy extends AbstractWaitStrategy {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.testcontainers.containers.wait.strategy;

import org.rnorth.ducttape.TimeoutException;
import org.rnorth.ducttape.unreliables.Unreliables;
import org.testcontainers.utility.ducttape.TimeoutException;
import org.testcontainers.utility.ducttape.Unreliables;
import org.testcontainers.containers.ContainerLaunchException;

import java.util.concurrent.TimeUnit;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.testcontainers.containers.wait.strategy;

import org.rnorth.ducttape.timeouts.Timeouts;
import org.testcontainers.utility.ducttape.Timeouts;

import java.time.Duration;
import java.util.ArrayList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
import org.apache.commons.lang3.StringUtils;
import org.awaitility.Awaitility;
import org.jetbrains.annotations.Nullable;
import org.rnorth.ducttape.TimeoutException;
import org.rnorth.ducttape.ratelimits.RateLimiter;
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
import org.rnorth.ducttape.unreliables.Unreliables;
import org.testcontainers.utility.ducttape.TimeoutException;
import org.testcontainers.utility.ducttape.RateLimiter;
import org.testcontainers.utility.ducttape.RateLimiterBuilder;
import org.testcontainers.utility.ducttape.Unreliables;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.UnstableAPI;
import org.testcontainers.utility.TestcontainersConfiguration;
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/testcontainers/utility/LazyFuture.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import lombok.AccessLevel;
import lombok.Getter;
import org.rnorth.ducttape.timeouts.Timeouts;
import org.testcontainers.utility.ducttape.Timeouts;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -45,7 +45,7 @@ public T get() {
public T get(long timeout, TimeUnit unit) throws TimeoutException {
try {
return Timeouts.getWithTimeout((int) timeout, unit, this::get);
} catch (org.rnorth.ducttape.TimeoutException e) {
} catch (org.testcontainers.utility.ducttape.TimeoutException e) {
throw new TimeoutException(e.getMessage());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import com.github.dockerjava.api.command.CreateContainerCmd;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.rnorth.ducttape.ratelimits.RateLimiter;
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
import org.testcontainers.utility.ducttape.RateLimiter;
import org.testcontainers.utility.ducttape.RateLimiterBuilder;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.GenericContainer;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.testcontainers.utility.ducttape;

import org.jetbrains.annotations.NotNull;

import java.util.concurrent.TimeUnit;

/**
* A rate limiter that uses a simple 'run every n millis' strategy to achieve constant throughput.
* This code comes from <a href="https://github.com/rnorth/duct-tape/">rnorth/duct-tape</a>
*/
class ConstantThroughputRateLimiter extends RateLimiter {

private final long timeBetweenInvocations;

ConstantThroughputRateLimiter(@NotNull Integer rate, @NotNull TimeUnit perTimeUnit) {
this.timeBetweenInvocations = perTimeUnit.toMillis(1) / rate;
}

@Override
protected long getWaitBeforeNextInvocation() {

long timeToNextAllowed = (lastInvocation + timeBetweenInvocations) - System.currentTimeMillis();

// Clamp wait time to 0<
return Math.max(timeToNextAllowed, 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.testcontainers.utility.ducttape;

/**
* Simple Preconditions check implementation.
* This code comes from <a href="https://github.com/rnorth/duct-tape/">rnorth/duct-tape</a>
*/
public class Preconditions {

/**
* Check that a given condition is true. Will throw an IllegalArgumentException otherwise.
* @param message message to display if the precondition check fails
* @param condition the result of evaluating the condition
*/
public static void check(String message, boolean condition) {
if (!condition) {
throw new IllegalArgumentException("Precondition failed: " + message);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.testcontainers.utility.ducttape;

import org.jetbrains.annotations.NotNull;

import java.util.concurrent.Callable;

/**
* Base class for rate limiters. Use RateLimiterBuilder to build new instances.
* This code comes from <a href="https://github.com/rnorth/duct-tape/">rnorth/duct-tape</a>
*/
public abstract class RateLimiter {

protected long lastInvocation;

/**
* Invoke a lambda function, with Thread.sleep() being called to limit the execution rate if needed.
* @param lambda a Runnable lamda function to invoke
*/
public void doWhenReady(@NotNull final Runnable lambda) {

// Wait before proceeding, if needed
long waitBeforeNextInvocation = getWaitBeforeNextInvocation();
try {
Thread.sleep(waitBeforeNextInvocation);
} catch (InterruptedException ignored) { }

try {
lambda.run();
} finally {
lastInvocation = System.currentTimeMillis();
}
}

/**
*
* Invoke a lambda function and get the result, with Thread.sleep() being called to limit the execution rate
* if needed.
* @param lambda a Callable lamda function to invoke
* @param <T> return type of the lamda
* @throws Exception rethrown from lambda
* @return result of the lambda call
*/
public <T> T getWhenReady(@NotNull final Callable<T> lambda) throws Exception {

// Wait before proceeding, if needed
long waitBeforeNextInvocation = getWaitBeforeNextInvocation();
try {
Thread.sleep(waitBeforeNextInvocation);
} catch (InterruptedException ignored) { }

try {
return lambda.call();
} finally {
lastInvocation = System.currentTimeMillis();
}
}

protected abstract long getWaitBeforeNextInvocation();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.testcontainers.utility.ducttape;

import java.util.concurrent.TimeUnit;

import static org.testcontainers.utility.ducttape.Preconditions.check;

/**
* Builder for rate limiters.
* This code comes from <a href="https://github.com/rnorth/duct-tape/">rnorth/duct-tape</a>
*/
public class RateLimiterBuilder {

private Integer invocations;
private TimeUnit perTimeUnit;
private RateLimiterStrategy strategy;

private RateLimiterBuilder() { }

/**
* Obtain a new builder instance.
* @return a new builder
*/
public static RateLimiterBuilder newBuilder() {
return new RateLimiterBuilder();
}

/**
* Set the maximum rate that the limiter should allow, expressed as the number of invocations
* allowed in a given time period.
* @param invocations number of invocations
* @param perTimeUnit the time period in which this number of invocations are allowed
* @return the builder
*/
public RateLimiterBuilder withRate(final int invocations, final TimeUnit perTimeUnit) {
this.invocations = invocations;
this.perTimeUnit = perTimeUnit;
return this;
}

/**
* Configure the rate limiter to use a constant throughput strategy for rate limiting.
* @return the builder
*/
public RateLimiterBuilder withConstantThroughput() {
this.strategy = RateLimiterStrategy.CONSTANT_THROUGHPUT;
return this;
}

/**
* Build and obtain a configured rate limiter. A rate and rate limiting strategy must have been selected.
* @return the configured rate limiter instance
*/
public RateLimiter build() {
check("A rate must be set", invocations != null);
check("A rate must be set", perTimeUnit != null);
check("A rate limit strategy must be set", strategy != null);

if (strategy == RateLimiterStrategy.CONSTANT_THROUGHPUT) {
return new ConstantThroughputRateLimiter(invocations, perTimeUnit);
} else {
throw new IllegalStateException();
}
}

private enum RateLimiterStrategy {
CONSTANT_THROUGHPUT
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.testcontainers.utility.ducttape;

/**
* Indicates repeated failure of an UnreliableSupplier
* This code comes from <a href="https://github.com/rnorth/duct-tape/">rnorth/duct-tape</a>
*/
public class RetryCountExceededException extends RuntimeException {

public RetryCountExceededException(String message, Exception exception) {
super(message, exception);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.testcontainers.utility.ducttape;

/**
* Indicates timeout of an UnreliableSupplier
* This code comes from <a href="https://github.com/rnorth/duct-tape/">rnorth/duct-tape</a>
*/
public class TimeoutException extends RuntimeException {

public TimeoutException(String message, Exception exception) {
super(message, exception);
}

public TimeoutException(Exception e) {
super(e);
}
}
Loading

0 comments on commit 259ad3a

Please sign in to comment.