-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Open
Labels
Description
Module
Core
Proposal
Currently
Lines 176 to 216 in 7d83019
| protected void waitUntilContainerStarted() { | |
| logger() | |
| .info( | |
| "Waiting for database connection to become available at {} using query '{}'", | |
| getJdbcUrl(), | |
| getTestQueryString() | |
| ); | |
| // Repeatedly try and open a connection to the DB and execute a test query | |
| long start = System.nanoTime(); | |
| Exception lastConnectionException = null; | |
| while ((System.nanoTime() - start) < TimeUnit.SECONDS.toNanos(startupTimeoutSeconds)) { | |
| if (!isRunning()) { | |
| Thread.sleep(100L); | |
| } else { | |
| try (Connection connection = createConnection(""); Statement statement = connection.createStatement()) { | |
| boolean testQuerySucceeded = statement.execute(this.getTestQueryString()); | |
| if (testQuerySucceeded) { | |
| return; | |
| } | |
| } catch (NoDriverFoundException e) { | |
| // we explicitly want this exception to fail fast without retries | |
| throw e; | |
| } catch (Exception e) { | |
| lastConnectionException = e; | |
| // ignore so that we can try again | |
| logger().debug("Failure when trying test query", e); | |
| Thread.sleep(100L); | |
| } | |
| } | |
| } | |
| throw new IllegalStateException( | |
| String.format( | |
| "Container is started, but cannot be accessed by (JDBC URL: %s), please check container logs", | |
| this.getJdbcUrl() | |
| ), | |
| lastConnectionException | |
| ); | |
| } |
- It doesn't utilize
WaitStrategyand completely ignores/overrides it - It constantly tries to query if the container is running or builds database connections (these are very costly in terms of CPU usage)
- These attempts use a hardcoded throttling value of 100ms and completely ignore the RateLimiter of
WaitStrategy
- These attempts use a hardcoded throttling value of 100ms and completely ignore the RateLimiter of
I would propose that you use - as in all other containers - the WaitStrategy.
- Remove the override/method
JdbcDatabaseContainer#waitUntilContainerStarted - Create a custom WaitStrategy called
JDBCWaitStrategy. It could look like this:class JDBCWaitStrategy extends AbstractWaitStrategy { @Override protected void waitUntilReady() { if(!(this.waitStrategyTarget instanceof final JdbcDatabaseContainer<?> container)) { throw new IllegalArgumentException( "Container must implement JdbcDatabaseContainer"); } try { Unreliables.retryUntilTrue( (int)this.startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> this.getRateLimiter().getWhenReady(() -> { try(final Connection connection = container.createConnection(""); final Statement statement = connection.createStatement()) { return statement.execute(container.getTestQueryString()); } }) ); } catch(final TimeoutException e) { throw new ContainerLaunchException( "JDBCContainer cannot be accessed by (JDBC URL: " + container.getJdbcUrl() + "), please check container logs"); } } }
- Use the following default WaitStrategy for JDBCDatabaseContainer:
new WaitAllStrategy() .withStrategy(Wait.defaultWaitStrategy()) .withStrategy(new JDBCWaitStrategy())
Full example implementation:
- https://github.com/xdev-software/tci-base/blob/13ca7984f6a732981cbd1912d9535076969004fa/tci-advanced-demo/tci-db/src/main/java/software/xdev/tci/demo/tci/db/containers/WaitableJDBCContainer.java
- https://github.com/xdev-software/tci-base/blob/13ca7984f6a732981cbd1912d9535076969004fa/tci-advanced-demo/tci-db/src/main/java/software/xdev/tci/demo/tci/db/containers/DBContainer.java