Skip to content

Commit

Permalink
fix: databasetesting.CreateForDevel() now tries to connect for 10s
Browse files Browse the repository at this point in the history
There seems to be a race between when the Docker PG healthcheck passes,
and when the Docker port becomes available:

    trace: exec: cd . && docker inspect --format \{\{.State.Health.Status}} ftl-db-1
    debug: Postgres DSN: ***localhost:54320/ftl?sslmode=disable
    ftl: error: failed to connect to `host=localhost user=postgres database=`: failed to receive message (unexpected EOF)

It's not clear if that's a deficiency in Docker, or perhaps pg_isready
is only checking the Unix socket and not the TCP port, and there's some
delay between the two becoming available. Either way, this should solve
it.
  • Loading branch information
alecthomas committed Feb 7, 2024
1 parent 2142e19 commit 986c915
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions backend/controller/sql/databasetesting/devel.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,45 @@ package databasetesting
import (
"context"
"fmt"
"time"

"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"

"github.com/TBD54566975/ftl/backend/common/log"
"github.com/TBD54566975/ftl/backend/controller/sql"
)

// CreateForDevel creates and migrates a new database for development or testing.
//
// If "recreate" is true, the database will be dropped and recreated.
func CreateForDevel(ctx context.Context, dsn string, recreate bool) (*pgxpool.Pool, error) {
logger := log.FromContext(ctx)
config, err := pgx.ParseConfig(dsn)
if err != nil {
return nil, err
}

noDBDSN := config.Copy()
noDBDSN.Database = ""
conn, err := pgx.ConnectConfig(ctx, noDBDSN)
if err != nil {
return nil, err
var conn *pgx.Conn
for i := 0; i < 10; i++ {
conn, err = pgx.ConnectConfig(ctx, noDBDSN)
if err == nil {
defer conn.Close(ctx)
break
}
logger.Debugf("Waiting for database to be ready: %v", err)
select {
case <-ctx.Done():
return nil, ctx.Err()

case <-time.After(1 * time.Second):
}
}
if conn == nil {
return nil, fmt.Errorf("database not ready after 10 tries: %w", err)
}
defer conn.Close(ctx)

if recreate {
// Terminate any dangling connections.
Expand Down

0 comments on commit 986c915

Please sign in to comment.