Skip to content

Commit c00f5e4

Browse files
authored
fix(server): retry initial connection to postgres (#7325)
1 parent a2ff674 commit c00f5e4

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

cli/server.go

+38-12
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import (
8888
"github.com/coder/coder/provisionersdk"
8989
sdkproto "github.com/coder/coder/provisionersdk/proto"
9090
"github.com/coder/coder/tailnet"
91+
"github.com/coder/retry"
9192
"github.com/coder/wgtunnel/tunnelsdk"
9293
)
9394

@@ -1733,24 +1734,43 @@ func BuildLogger(inv *clibase.Invocation, cfg *codersdk.DeploymentValues) (slog.
17331734

17341735
func connectToPostgres(ctx context.Context, logger slog.Logger, driver string, dbURL string) (*sql.DB, error) {
17351736
logger.Debug(ctx, "connecting to postgresql")
1736-
sqlDB, err := sql.Open(driver, dbURL)
1737-
if err != nil {
1738-
return nil, xerrors.Errorf("dial postgres: %w", err)
1739-
}
17401737

1741-
ok := false
1738+
// Try to connect for 30 seconds.
1739+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
1740+
defer cancel()
1741+
1742+
var (
1743+
sqlDB *sql.DB
1744+
err error
1745+
ok = false
1746+
tries int
1747+
)
1748+
for r := retry.New(time.Second, 3*time.Second); r.Wait(ctx); {
1749+
tries++
1750+
1751+
sqlDB, err = sql.Open(driver, dbURL)
1752+
if err != nil {
1753+
logger.Warn(ctx, "connect to postgres; retrying", slog.Error(err), slog.F("try", tries))
1754+
continue
1755+
}
1756+
1757+
err = pingPostgres(ctx, sqlDB)
1758+
if err != nil {
1759+
logger.Warn(ctx, "ping postgres; retrying", slog.Error(err), slog.F("try", tries))
1760+
continue
1761+
}
1762+
1763+
break
1764+
}
1765+
// Make sure we close the DB in case it opened but the ping failed for some
1766+
// reason.
17421767
defer func() {
1743-
if !ok {
1768+
if !ok && sqlDB != nil {
17441769
_ = sqlDB.Close()
17451770
}
17461771
}()
1747-
1748-
pingCtx, pingCancel := context.WithTimeout(ctx, 15*time.Second)
1749-
defer pingCancel()
1750-
1751-
err = sqlDB.PingContext(pingCtx)
17521772
if err != nil {
1753-
return nil, xerrors.Errorf("ping postgres: %w", err)
1773+
return nil, xerrors.Errorf("connect to postgres; tries %d; last error: %w", tries, err)
17541774
}
17551775

17561776
// Ensure the PostgreSQL version is >=13.0.0!
@@ -1799,6 +1819,12 @@ func connectToPostgres(ctx context.Context, logger slog.Logger, driver string, d
17991819
return sqlDB, nil
18001820
}
18011821

1822+
func pingPostgres(ctx context.Context, db *sql.DB) error {
1823+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
1824+
defer cancel()
1825+
return db.PingContext(ctx)
1826+
}
1827+
18021828
type HTTPServers struct {
18031829
HTTPUrl *url.URL
18041830
HTTPListener net.Listener

0 commit comments

Comments
 (0)