package dbretry import ( "context" "fmt" "time" "github.com/jackc/pgx/v5/pgxpool" ) func Connect(ctx context.Context, databaseURL string, maxWait time.Duration) (*pgxpool.Pool, error) { deadline := time.Now().Add(maxWait) var lastErr error for attempt := 1; ; attempt++ { pool, err := pgxpool.New(ctx, databaseURL) if err == nil { if pingErr := pool.Ping(ctx); pingErr == nil { return pool, nil } else { err = fmt.Errorf("ping postgres: %w", pingErr) pool.Close() } } else { err = fmt.Errorf("connect postgres: %w", err) } lastErr = err if time.Now().After(deadline) { return nil, fmt.Errorf("connect postgres after retry: %w", lastErr) } sleep := time.Duration(attempt) * time.Second if sleep > 5*time.Second { sleep = 5 * time.Second } timer := time.NewTimer(sleep) select { case <-ctx.Done(): timer.Stop() return nil, fmt.Errorf("connect postgres cancelled: %w", ctx.Err()) case <-timer.C: } } }