Skip to content

Commit 80dcbac

Browse files
alnrory-bot
authored andcommitted
feat: automatic transaction retries for postgres
GitOrigin-RevId: e7d567988621937fb25e9f41af7892b6f0aad65d
1 parent aa3071f commit 80dcbac

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

oryx/popx/transaction.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ package popx
66
import (
77
"context"
88
"runtime"
9+
"strings"
910

1011
"github.com/cockroachdb/cockroach-go/v2/crdb"
12+
"github.com/jackc/pgconn"
13+
pgxconn "github.com/jackc/pgx/v5/pgconn"
1114
"github.com/jmoiron/sqlx"
1215
"github.com/pkg/errors"
1316
"github.com/prometheus/client_golang/prometheus"
@@ -53,6 +56,26 @@ func Transaction(ctx context.Context, connection *pop.Connection, callback func(
5356
}))
5457
})
5558
}
59+
if strings.HasPrefix(connection.Dialect.Name(), "postgres") {
60+
var err error
61+
for attempt := range 10 {
62+
_ = attempt
63+
err = connection.WithContext(ctx).Transaction(func(tx *pop.Connection) error {
64+
return callback(WithTransaction(ctx, tx), tx)
65+
})
66+
if err == nil {
67+
return nil
68+
}
69+
if e := new(pgconn.PgError); errors.As(err, &e) && e.Code == "40001" {
70+
continue
71+
}
72+
if e := new(pgxconn.PgError); errors.As(err, &e) && e.Code == "40001" {
73+
continue
74+
}
75+
return err
76+
}
77+
return err
78+
}
5679

5780
return errors.WithStack(connection.WithContext(ctx).Transaction(func(tx *pop.Connection) error {
5881
return errors.WithStack(callback(WithTransaction(ctx, tx), tx))

oryx/sqlcon/error.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77
"database/sql"
88
"net/http"
99

10-
"google.golang.org/grpc/codes"
11-
1210
"github.com/go-sql-driver/mysql"
1311
"github.com/jackc/pgconn"
12+
pgxconn "github.com/jackc/pgx/v5/pgconn"
1413
"github.com/lib/pq"
1514
"github.com/pkg/errors"
15+
"google.golang.org/grpc/codes"
1616

1717
"github.com/ory/herodot"
1818
)
@@ -87,6 +87,8 @@ func HandleError(err error) error {
8787
return errors.WithStack(handlePostgres(err, string(e.Code)))
8888
} else if e := new(pgconn.PgError); errors.As(err, &e) {
8989
return errors.WithStack(handlePostgres(err, e.Code))
90+
} else if e := new(pgxconn.PgError); errors.As(err, &e) {
91+
return errors.WithStack(handlePostgres(err, e.Code))
9092
} else if e := new(mysql.MySQLError); errors.As(err, &e) {
9193
switch e.Number {
9294
case 1062: // https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_dup_entry

0 commit comments

Comments
 (0)