A PostgreSQL resource readiness assertion library built on top of the waitfor framework. This library allows you to wait for PostgreSQL databases to become available before proceeding with your application startup, making it ideal for containerized environments, integration tests, and service orchestration.
- PostgreSQL connectivity testing: Ping PostgreSQL databases to verify they're ready
- Multiple URL schemes: Supports both
postgres://andpostgresql://connection strings - Configurable retry logic: Customize attempts, intervals, and timeouts
- Context support: Full context cancellation and timeout support
- Integration ready: Built for Docker Compose, Kubernetes, and CI/CD pipelines
go get github.com/go-waitfor/waitfor-postgrespackage main
import (
"context"
"fmt"
"time"
"github.com/go-waitfor/waitfor"
"github.com/go-waitfor/waitfor-postgres"
)
func main() {
runner := waitfor.New(postgres.Use())
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := runner.Test(
ctx,
[]string{"postgres://user:password@localhost/mydb"},
waitfor.WithAttempts(10),
waitfor.WithInterval(2000), // 2000 milliseconds (2 seconds)
)
if err != nil {
fmt.Printf("PostgreSQL not ready: %v\n", err)
return
}
fmt.Println("PostgreSQL is ready!")
}runner := waitfor.New(postgres.Use())
err := runner.Test(
context.Background(),
[]string{"postgres://localhost/mydb"},
)databases := []string{
"postgres://user:pass@db1:5432/app_db",
"postgresql://user:pass@db2:5432/cache_db",
}
err := runner.Test(context.Background(), databases)ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
err := runner.Test(
ctx,
[]string{"postgres://user:pass@localhost/mydb"},
waitfor.WithAttempts(20), // Try up to 20 times
waitfor.WithInterval(5000), // Wait 5000 milliseconds (5 seconds) between attempts
)err := runner.Test(ctx, []string{"postgres://localhost/mydb"})
if err != nil {
// Handle different types of errors
fmt.Printf("Database connection failed: %v\n", err)
// Check if it's a timeout
if ctx.Err() == context.DeadlineExceeded {
fmt.Println("Timed out waiting for database")
}
}The library supports both PostgreSQL URL schemes:
postgres://user:password@host:port/dbname?sslmode=disablepostgresql://user:password@host:port/dbname?sslmode=require
postgresql://username:password@hostname:port/database?param1=value1¶m2=value2
- username: Database username (optional)
- password: Database password (optional)
- hostname: Database server hostname or IP
- port: Database server port (default: 5432)
- database: Database name (optional)
- parameters: Connection parameters like
sslmode,connect_timeout, etc.
The library uses the waitfor framework's configuration options:
| Option | Description | Default |
|---|---|---|
WithAttempts(n) |
Maximum number of connection attempts | 30 |
WithInterval(ms) |
Time between connection attempts in milliseconds | 1000 (1 second) |
Always use context with timeouts for production applications:
// Set overall timeout for the entire wait operation
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
// The Test method will respect the context deadline
err := runner.Test(ctx, []string{"postgres://localhost/mydb"}, waitfor.WithAttempts(20))
if errors.Is(err, context.DeadlineExceeded) {
log.Fatal("Timed out waiting for PostgreSQL to become ready")
}version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
app:
build: .
depends_on:
- postgres
environment:
DATABASE_URL: postgres://user:password@postgres:5432/myappinitContainers:
- name: wait-for-db
image: my-app:latest
command: ["/wait-for-postgres"]
env:
- name: DATABASE_URL
value: "postgres://user:pass@postgres-service:5432/mydb"- Connection refused: Check if PostgreSQL is running and accessible
- Authentication failed: Verify username and password
- Database not found: Ensure the database exists
- SSL/TLS issues: Check
sslmodeparameter in connection string
// Enable detailed logging (if using a logger)
log.Printf("Testing connection to: %s", databaseURL)
err := runner.Test(ctx, []string{databaseURL})
if err != nil {
log.Printf("Connection failed: %v", err)
}This project is licensed under the Apache License 2.0 - see the LICENSE file for details.