Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

chore: retry postgres connection on reset by peer in tests#18632

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
spikecurtis merged 2 commits intomainfromspike/internal-695-retry-pg-reset-by-peer
Jun 27, 2025
Merged
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 43 additions & 16 deletionscoderd/database/dbtestutil/postgres.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,6 +45,13 @@ var (
connectionParamsInitOnce sync.Once
defaultConnectionParams ConnectionParams
errDefaultConnectionParamsInit error
retryableErrSubstrings = []string{
"connection reset by peer",
}
noPostgresRunningErrSubstrings = []string{
"connection refused", // nothing is listening on the port
"No connection could be made", // Windows variant of the above
}
)

// initDefaultConnection initializes the default postgres connection parameters.
Expand All@@ -59,28 +66,38 @@ func initDefaultConnection(t TBSubset) error {
DBName: "postgres",
}
dsn := params.DSN()
db, dbErr := sql.Open("postgres", dsn)
if dbErr == nil {
dbErr = db.Ping()
if closeErr := db.Close(); closeErr != nil {
return xerrors.Errorf("close db: %w", closeErr)

// Helper closure to try opening and pinging the default Postgres instance.
// Used within a single retry loop that handles both retryable and permanent errors.
attemptConn := func() error {
db, err := sql.Open("postgres", dsn)
if err == nil {
err = db.Ping()
if closeErr := db.Close(); closeErr != nil {
return xerrors.Errorf("close db: %w", closeErr)
}
}
return err
}
shouldOpenContainer := false
if dbErr != nil {
errSubstrings := []string{
"connection refused", // this happens on Linux when there's nothing listening on the port
"No connection could be made", // like above but Windows

var dbErr error
// Retry up to 3 seconds for temporary errors.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
for r := retry.New(10*time.Millisecond, 500*time.Millisecond); r.Wait(ctx); {
dbErr = attemptConn()
if dbErr == nil {
break
}
errString := dbErr.Error()
for _, errSubstring := range errSubstrings {
if strings.Contains(errString, errSubstring) {
shouldOpenContainer = true
break
}
if !containsAnySubstring(errString, retryableErrSubstrings) {
break
}
t.Logf("failed to connect to postgres, retrying: %s", errString)
}
if dbErr != nil && shouldOpenContainer {

// After the loop dbErr is the last connection error (if any).
if dbErr != nil && containsAnySubstring(dbErr.Error(), noPostgresRunningErrSubstrings) {
// If there's no database running on the default port, we'll start a
// postgres container. We won't be cleaning it up so it can be reused
// by subsequent tests. It'll keep on running until the user terminates
Expand DownExpand Up@@ -110,6 +127,7 @@ func initDefaultConnection(t TBSubset) error {
if connErr == nil {
break
}
t.Logf("failed to connect to postgres after starting container, may retry: %s", connErr.Error())
}
} else if dbErr != nil {
return xerrors.Errorf("open postgres connection: %w", dbErr)
Expand DownExpand Up@@ -523,3 +541,12 @@ func OpenContainerized(t TBSubset, opts DBContainerOptions) (string, func(), err

return dbURL, containerCleanup, nil
}

func containsAnySubstring(s string, substrings []string) bool {
for _, substr := range substrings {
if strings.Contains(s, substr) {
return true
}
}
return false
}
Loading

[8]ページ先頭

©2009-2025 Movatter.jp