Skip to content

Commit ebdc30f

Browse files
Madhavanclaude
andcommitted
fix(backfill-ci): revert to CQL-log wait and make the c4 logback log to stdout
The host-side CQL-port probe regressed all 9 Kafka backfill jobs (c3/dse4 had passed with the log wait). A host-side TCP connect to a mapped port is unreliable: Docker's port forwarding can accept the connection before Cassandra has bound 9042, so the wait returns prematurely and getCqlSession() then fails -- across every family. Revert to the proven "Starting listening for CQL clients" log wait, and fix the actual c4 outlier: its config-override logback.xml had every root appender-ref (including STDOUT) commented out, so Cassandra 4.0.4 logged nothing to the container stdout and the log wait never matched. Re-enable the STDOUT appender so c4 emits the readiness line like c3/dse4 already do. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 7dd7f85 commit ebdc30f

2 files changed

Lines changed: 9 additions & 40 deletions

File tree

backfill-cli/src/test/resources/c4/logback.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ appender reference in the root level section below.
9090

9191
<root level="INFO">
9292
<!-- <appender-ref ref="SYSTEMLOG" />-->
93-
<!-- <appender-ref ref="STDOUT" />-->
93+
<appender-ref ref="STDOUT" />
9494
<!-- <appender-ref ref="DEBUGLOG" /> &lt;!&ndash; Comment this line to disable debug.log &ndash;&gt;-->
9595
<!--
9696
<appender-ref ref="LogbackMetrics" />

testcontainers/src/main/java/com/datastax/testcontainers/cassandra/CassandraContainer.java

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,13 @@
3030
import org.testcontainers.delegate.DatabaseDelegate;
3131
import org.testcontainers.ext.ScriptUtils;
3232
import org.testcontainers.ext.ScriptUtils.ScriptLoadException;
33-
import org.testcontainers.containers.ContainerLaunchException;
34-
import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy;
33+
import org.testcontainers.containers.wait.strategy.Wait;
3534
import org.testcontainers.utility.DockerImageName;
3635
import org.testcontainers.utility.MountableFile;
3736

3837
import javax.script.ScriptException;
3938
import java.io.IOException;
4039
import java.net.InetSocketAddress;
41-
import java.net.Socket;
4240
import java.net.URL;
4341
import java.nio.charset.StandardCharsets;
4442
import java.time.Duration;
@@ -275,12 +273,13 @@ public static CassandraContainer<?> createCassandraContainer(DockerImageName ima
275273
.withEnv("MAX_HEAP_SIZE", "1500m")
276274
.withEnv("HEAP_NEWSIZE", "300m")
277275
.withEnv("DS_LICENSE", "accept")
278-
// Wait only on the CQL port. The default strategy waits for ALL exposed ports,
279-
// including the debug port (8000) that the agent-based factories open via the JVM
280-
// debug agent but a no-agent node never does. A log-message strategy is also unusable
281-
// here because some config-override logback.xml files (e.g. c4) route Cassandra
282-
// output to file only, leaving stdout empty.
283-
.waitingFor(new CqlPortWaitStrategy().withStartupTimeout(Duration.ofSeconds(180)))
276+
// The base container exposes the debug port (8000) alongside CQL (9042) and JMX
277+
// (7199); the default strategy waits for ALL exposed ports, but a no-agent node never
278+
// opens 8000 (only the JVM debug agent does). Wait on the CQL-readiness log line
279+
// instead. This requires the mounted logback.xml to log to stdout (the c3/c4/dse4
280+
// config overrides all enable the STDOUT appender).
281+
.waitingFor(Wait.forLogMessage(".*Starting listening for CQL clients.*", 1)
282+
.withStartupTimeout(Duration.ofSeconds(180)))
284283
.withStartupTimeout(Duration.ofSeconds(180));
285284
if (nodeIndex > 1) {
286285
cassandraContainer.withEnv("CASSANDRA_SEEDS", "cassandra-1"); // for Cassandra
@@ -289,36 +288,6 @@ public static CassandraContainer<?> createCassandraContainer(DockerImageName ima
289288
return cassandraContainer;
290289
}
291290

292-
/**
293-
* Waits until the CQL native-transport port (9042) accepts TCP connections from the host.
294-
* Targets only the CQL port so it does not block on the always-exposed-but-unused debug port
295-
* (8000), and does not depend on Cassandra writing to stdout (some config-override logback.xml
296-
* files log to file only).
297-
*/
298-
private static class CqlPortWaitStrategy extends AbstractWaitStrategy {
299-
@Override
300-
protected void waitUntilReady() {
301-
final String host = waitStrategyTarget.getHost();
302-
final int port = waitStrategyTarget.getMappedPort(CQL_PORT);
303-
final long deadline = System.currentTimeMillis() + startupTimeout.toMillis();
304-
while (System.currentTimeMillis() < deadline) {
305-
try (Socket socket = new Socket()) {
306-
socket.connect(new InetSocketAddress(host, port), 2000);
307-
return;
308-
} catch (IOException notReadyYet) {
309-
try {
310-
Thread.sleep(1000);
311-
} catch (InterruptedException ie) {
312-
Thread.currentThread().interrupt();
313-
throw new ContainerLaunchException("Interrupted while waiting for the CQL port", ie);
314-
}
315-
}
316-
}
317-
throw new ContainerLaunchException(
318-
"Timed out waiting for the CQL port (" + CQL_PORT + ") to accept connections");
319-
}
320-
}
321-
322291
public static CassandraContainer<?> createCassandraContainerWithAgent(DockerImageName image,
323292
Network network,
324293
int nodeIndex,

0 commit comments

Comments
 (0)