Wait Strategies¶
Wait strategies determine when a container is considered "ready" for use.
Overview¶
When you call startAndWait(), the template polls the container using the configured wait strategy until it succeeds or times out.
RedisTemplate("my-redis") {
waitStrategy = WaitStrategy.ForPort(6379)
waitTimeout = 60.seconds
waitPollInterval = 500.milliseconds
}.use { redis ->
redis.startAndWait() // Blocks until ready
}
Available Strategies¶
Running¶
Wait for the container to be in "running" state. This is the simplest strategy but doesn't guarantee the service is ready.
ForPort¶
Wait for a TCP port to accept connections.
This is the most common strategy and works for most services.
ForHttp¶
Wait for an HTTP endpoint to return an expected status code.
Useful for services with health check endpoints.
ForLogMessage¶
Wait for a specific message to appear in container logs.
// Match exact substring
waitStrategy = WaitStrategy.ForLogMessage("Server started")
// Match regex pattern
waitStrategy = WaitStrategy.ForLogMessage(Regex("Ready to accept connections.*"))
Useful when the service logs a specific message on startup.
ForCommand¶
Wait for a command to succeed inside the container.
// Simple command
waitStrategy = WaitStrategy.ForCommand("redis-cli", "ping")
// Command with expected output
waitStrategy = WaitStrategy.ForCommand(listOf("pg_isready", "-U", "postgres"))
Useful for database readiness checks.
Configuration¶
Timeout¶
Maximum time to wait for the container to be ready:
If the timeout is exceeded, a TemplateException.WaitTimeout is thrown.
Poll Interval¶
How often to check the container status:
Template Defaults¶
Each template provides a sensible default wait strategy:
| Template | Default Strategy |
|---|---|
RedisTemplate | ForCommand("redis-cli", "ping") |
PostgresTemplate | ForCommand("pg_isready", "-U", "postgres") |
MysqlTemplate | ForCommand("mysqladmin", "ping") |
MongodbTemplate | ForCommand("mongosh", "--eval", "db.runCommand('ping')") |
NginxTemplate | ForPort(80) |
Custom Wait Logic¶
For complex scenarios, override checkReady() in your template:
class MyTemplate(...) : AbstractTemplate(...) {
override suspend fun checkReady(): Boolean {
// Custom readiness check
val result = exec("my-health-check")
if (!result.success) return false
// Parse output
val status = parseStatus(result.stdout)
return status == "healthy"
}
}
Examples¶
Database with Authentication¶
PostgresTemplate("my-db") {
password("secret")
waitStrategy = WaitStrategy.ForCommand(
"pg_isready", "-U", "postgres", "-d", "mydb"
)
waitTimeout = 120.seconds
}
Web Service with Health Endpoint¶
MyWebService("my-service") {
waitStrategy = WaitStrategy.ForHttp(
path = "/api/health",
port = 8080,
statusCode = 200
)
}
Service with Startup Log¶
KafkaTemplate("my-kafka") {
waitStrategy = WaitStrategy.ForLogMessage(
Regex(".*Kafka Server.*started.*")
)
waitTimeout = 180.seconds
}
Multiple Conditions¶
For complex scenarios, implement custom logic:
override suspend fun checkReady(): Boolean {
// Check port first
if (!checkPortReady(8080)) return false
// Then check health endpoint
val health = exec("curl", "-sf", "http://localhost:8080/health")
if (!health.success) return false
// Parse health response
return health.stdout.contains("\"status\":\"up\"")
}
Troubleshooting¶
Timeout Errors¶
If containers frequently timeout:
-
Increase
waitTimeout: -
Check container logs:
-
Use a more appropriate strategy:
False Positives¶
If containers report ready but aren't:
-
Use a more specific strategy:
-
Add a startup delay in your container: