Skip to content

Commit e78a925

Browse files
authored
fix: wait for pooler after init temp role (#4018)
* Revert "fix: retry pooler connection after password change (#3949)" This reverts commit 2b6e22b. * fix: wait for pooler after init temp role
1 parent 9d31bb1 commit e78a925

File tree

4 files changed

+52
-49
lines changed

4 files changed

+52
-49
lines changed

internal/bootstrap/bootstrap.go

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"os"
1010
"path/filepath"
1111
"strings"
12-
"time"
1312

1413
"github.com/cenkalti/backoff/v4"
1514
"github.com/go-errors/errors"
@@ -88,12 +87,12 @@ func Run(ctx context.Context, starter StarterTemplate, fsys afero.Fs, options ..
8887
}
8988
// 3. Get api keys
9089
var keys []api.ApiKeyResponse
91-
policy := newBackoffPolicy(ctx)
90+
policy := utils.NewBackoffPolicy(ctx)
9291
if err := backoff.RetryNotify(func() error {
9392
fmt.Fprintln(os.Stderr, "Linking project...")
9493
keys, err = apiKeys.RunGetApiKeys(ctx, flags.ProjectRef)
9594
return err
96-
}, policy, newErrorCallback()); err != nil {
95+
}, policy, utils.NewErrorCallback()); err != nil {
9796
return err
9897
}
9998
// 4. Link project
@@ -109,7 +108,7 @@ func Run(ctx context.Context, starter StarterTemplate, fsys afero.Fs, options ..
109108
if err := backoff.RetryNotify(func() error {
110109
fmt.Fprintln(os.Stderr, "Checking project health...")
111110
return checkProjectHealth(ctx)
112-
}, policy, newErrorCallback()); err != nil {
111+
}, policy, utils.NewErrorCallback()); err != nil {
113112
return err
114113
}
115114
// 6. Push migrations
@@ -120,7 +119,7 @@ func Run(ctx context.Context, starter StarterTemplate, fsys afero.Fs, options ..
120119
policy.Reset()
121120
if err := backoff.RetryNotify(func() error {
122121
return push.Run(ctx, false, false, true, true, config, fsys)
123-
}, policy, newErrorCallback()); err != nil {
122+
}, policy, utils.NewErrorCallback()); err != nil {
124123
return err
125124
}
126125
// 7. TODO: deploy functions
@@ -171,32 +170,6 @@ func checkProjectHealth(ctx context.Context) error {
171170
return nil
172171
}
173172

174-
const maxRetries = 8
175-
176-
func newBackoffPolicy(ctx context.Context) backoff.BackOffContext {
177-
b := backoff.ExponentialBackOff{
178-
InitialInterval: 3 * time.Second,
179-
RandomizationFactor: backoff.DefaultRandomizationFactor,
180-
Multiplier: backoff.DefaultMultiplier,
181-
MaxInterval: backoff.DefaultMaxInterval,
182-
MaxElapsedTime: backoff.DefaultMaxElapsedTime,
183-
Stop: backoff.Stop,
184-
Clock: backoff.SystemClock,
185-
}
186-
b.Reset()
187-
return backoff.WithContext(backoff.WithMaxRetries(&b, maxRetries), ctx)
188-
}
189-
190-
func newErrorCallback() backoff.Notify {
191-
failureCount := 0
192-
logger := utils.GetDebugLogger()
193-
return func(err error, d time.Duration) {
194-
failureCount += 1
195-
fmt.Fprintln(logger, err)
196-
fmt.Fprintf(os.Stderr, "Retry (%d/%d): ", failureCount, maxRetries)
197-
}
198-
}
199-
200173
const (
201174
SUPABASE_SERVICE_ROLE_KEY = "SUPABASE_SERVICE_ROLE_KEY"
202175
SUPABASE_ANON_KEY = "SUPABASE_ANON_KEY"

internal/utils/flags/db_url.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strings"
1313
"text/template"
1414

15+
"github.com/cenkalti/backoff/v4"
1516
"github.com/go-errors/errors"
1617
"github.com/jackc/pgconn"
1718
"github.com/spf13/afero"
@@ -133,6 +134,7 @@ func NewDbConfigWithPassword(ctx context.Context, projectRef string) pgconn.Conf
133134
// Special handling for pooler username
134135
if suffix := "." + projectRef; strings.HasSuffix(config.User, suffix) {
135136
newRole.User += suffix
137+
defer tryPooler(ctx, &config)
136138
}
137139
config.User = newRole.User
138140
return config
@@ -148,6 +150,18 @@ func NewDbConfigWithPassword(ctx context.Context, projectRef string) pgconn.Conf
148150
return config
149151
}
150152

153+
func tryPooler(ctx context.Context, config *pgconn.Config) {
154+
if err := backoff.RetryNotify(func() error {
155+
conn, err := pgconn.ConnectConfig(ctx, config)
156+
if err != nil {
157+
return errors.Errorf("failed to connect as temp role: %w", err)
158+
}
159+
return conn.Close(ctx)
160+
}, utils.NewBackoffPolicy(ctx), utils.NewErrorCallback()); err != nil {
161+
fmt.Fprintln(os.Stderr, err)
162+
}
163+
}
164+
151165
var (
152166
//go:embed queries/role.sql
153167
initRoleEmbed string

internal/utils/retry.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package utils
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"time"
8+
9+
"github.com/cenkalti/backoff/v4"
10+
)
11+
12+
const maxRetries = 8
13+
14+
func NewBackoffPolicy(ctx context.Context) backoff.BackOffContext {
15+
b := backoff.NewExponentialBackOff(backoff.WithInitialInterval(3 * time.Second))
16+
return backoff.WithContext(backoff.WithMaxRetries(b, maxRetries), ctx)
17+
}
18+
19+
func NewErrorCallback() backoff.Notify {
20+
failureCount := 0
21+
logger := GetDebugLogger()
22+
return func(err error, d time.Duration) {
23+
failureCount += 1
24+
if failureCount*3 > maxRetries {
25+
logger = os.Stderr
26+
}
27+
fmt.Fprintln(logger, err)
28+
fmt.Fprintf(logger, "Retry (%d/%d): ", failureCount, maxRetries)
29+
}
30+
}

pkg/pgxv5/connect.go

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import (
55
"fmt"
66
"os"
77
"strings"
8-
"time"
98

10-
"github.com/cenkalti/backoff/v4"
119
"github.com/go-errors/errors"
1210
"github.com/jackc/pgconn"
1311
"github.com/jackc/pgx/v4"
@@ -28,31 +26,19 @@ func Connect(ctx context.Context, connString string, options ...func(*pgx.ConnCo
2826
config.OnNotice = func(pc *pgconn.PgConn, n *pgconn.Notice) {
2927
fmt.Fprintf(os.Stderr, "%s (%s): %s\n", n.Severity, n.Code, n.Message)
3028
}
31-
maxRetries := uint64(0)
3229
if strings.HasPrefix(config.User, CLI_LOGIN_ROLE) {
3330
config.AfterConnect = func(ctx context.Context, pgconn *pgconn.PgConn) error {
3431
return pgconn.Exec(ctx, SET_SESSION_ROLE).Close()
3532
}
36-
// Add retry to allow enough time for password change to propagate to pooler
37-
if len(config.User) > len(CLI_LOGIN_ROLE) {
38-
maxRetries = 3
39-
}
4033
}
4134
// Apply config overrides
4235
for _, op := range options {
4336
op(config)
4437
}
4538
// Connect to database
46-
connect := func() (*pgx.Conn, error) {
47-
conn, err := pgx.ConnectConfig(ctx, config)
48-
if err != nil {
49-
return nil, errors.Errorf("failed to connect to postgres: %w", err)
50-
}
51-
return conn, nil
39+
conn, err := pgx.ConnectConfig(ctx, config)
40+
if err != nil {
41+
return nil, errors.Errorf("failed to connect to postgres: %w", err)
5242
}
53-
policy := backoff.WithContext(backoff.WithMaxRetries(backoff.NewExponentialBackOff(
54-
backoff.WithInitialInterval(3*time.Second)),
55-
maxRetries),
56-
ctx)
57-
return backoff.RetryWithData(connect, policy)
43+
return conn, nil
5844
}

0 commit comments

Comments
 (0)