`Ec2Client` from `AwsEc2.aws()` is never closed; AWS SDK v2 connections leak in `StartsInstance` and `TerminatesInstance`
#2,322 opened on May 11, 2026
Repository metrics
- Stars
- (575 stars)
- PR merge metrics
- (PR metrics pending)
Description
What happens
In src/main/java/com/rultor/agents/aws/AwsEc2.java, the method aws() builds and returns a fresh Ec2Client on every invocation:
public Ec2Client aws() {
return Ec2Client.builder()
.region(Region.of(this.region))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(this.key, this.secret)
))
.build();
}
software.amazon.awssdk.services.ec2.Ec2Client (AWS SDK v2) extends SdkAutoCloseable. Each instance owns an Apache or Netty HTTP client, a thread pool, and a connection pool, and the SDK documentation explicitly states clients are expensive and must be closed.
The two call sites in the same package never close the returned client:
StartsInstance.java:161-162—this.api.aws().runInstances(request)TerminatesInstance.java:47—this.api.aws().terminateInstances(...)
Each agent tick that starts or terminates an EC2 instance therefore leaks one full AWS SDK client. Over a long-running rultor deployment that processes many builds, the leaked threads and connection pools accumulate.
What should happen
Either cache a single Ec2Client as a field on AwsEc2 and reuse it across calls (the SDK v2 client is thread-safe), or wrap each call site in a try-with-resources:
try (Ec2Client client = this.api.aws()) {
client.runInstances(request);
}
The choice depends on how @Immutable is intended to constrain AwsEc2. Either fix eliminates the per-call leak.