Timeout issue with Testcontainers JDBC support

Timeout issue with Testcontainers JDBC support

After upgrading Quarkus to 2.8.2 for my project, the GitHub Actions build failed. Below is the stacktrace.

java.lang.RuntimeException: java.lang.RuntimeException: Failed to start quarkus
Caused by: java.lang.RuntimeException: Failed to start quarkus
Caused by: org.flywaydb.core.internal.exception.FlywaySqlException: 
Unable to obtain connection from database: Acquisition timeout while waiting for new connection
-----------------------------------------------------------------------------------------------
SQL State  : null
Error Code : 0
Message    : Acquisition timeout while waiting for new connection

Caused by: java.sql.SQLException: Acquisition timeout while waiting for new connection
Caused by: java.util.concurrent.TimeoutException

From the message, we can know that Flyway couldn't connect to the PostgreSQL database started by Testcontainers.

PostgreSQL containers were started using Testcontainers JDBC support. When using this approach, the container startup timeout cannot be configured. When running with GitHub Actions, container images need to be pulled down first, so the default timeout duration was not long enough for the container to finish startup.

"%test":
  quarkus:
    datasource:
      jdbc:
        driver: org.testcontainers.jdbc.ContainerDatabaseDriver
        url: jdbc:tc:postgresql:12:///

To solve this issue, a Quarkus test resource for PostgreSQL is added. withStartupTimeout(Duration.ofMinutes(5)) is used to set the startup timeout to 5 minutes. @QuarkusTestResource(PostgreSQLResource.class) needs to be added to the test class.

import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import java.time.Duration;
import java.util.Map;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;

public class PostgreSQLResource implements QuarkusTestResourceLifecycleManager {

  private final PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>(
      DockerImageName.parse("postgres:12")
  ).withStartupTimeout(Duration.ofMinutes(5));

  @Override
  public Map<String, String> start() {
    this.postgres.start();
    return Map.of(
        "quarkus.datasource.jdbc.url", this.postgres.getJdbcUrl(),
        "quarkus.datasource.username", this.postgres.getUsername(),
        "quarkus.datasource.password", this.postgres.getPassword()
    );
  }

  @Override
  public void stop() {

  }
}

With this new Quarkus test resource, GitHub Actions builds can pass.

© 2022 VividCode