fix: preserve postgres storage error boundary

This commit is contained in:
youfak 2026-07-30 04:57:39 +08:00
parent 2be4eb23e3
commit 48682f0bfc
5 changed files with 22 additions and 16 deletions

View File

@ -12,14 +12,14 @@ import (
"proxy-pool/internal/domain/adminstate" "proxy-pool/internal/domain/adminstate"
) )
var _ adminstate.Store = (*Adapter)(nil) var _ adminstate.Store = (*adapter)(nil)
type transactionBeginner interface { type transactionBeginner interface {
BeginTx(context.Context, pgx.TxOptions) (pgx.Tx, error) BeginTx(context.Context, pgx.TxOptions) (pgx.Tx, error)
} }
// Adapter keeps all PostgreSQL transaction and SQL details behind adminstate.Store. // adapter keeps all PostgreSQL transaction and SQL details behind adminstate.Store.
type Adapter struct { type adapter struct {
pool transactionBeginner pool transactionBeginner
} }
@ -28,7 +28,7 @@ func New(pool transactionBeginner) (adminstate.Store, error) {
if isNil(pool) { if isNil(pool) {
return nil, adminstate.ErrInvalidCommand return nil, adminstate.ErrInvalidCommand
} }
return &Adapter{pool: pool}, nil return &adapter{pool: pool}, nil
} }
func isNil(value any) bool { func isNil(value any) bool {
@ -48,11 +48,11 @@ func contextError(ctx context.Context) error {
return ctx.Err() return ctx.Err()
} }
func (adapter *Adapter) valid() bool { func (adapter *adapter) valid() bool {
return adapter != nil && !isNil(adapter.pool) return adapter != nil && !isNil(adapter.pool)
} }
func (adapter *Adapter) begin(ctx context.Context, options pgx.TxOptions, operation string) (pgx.Tx, error) { func (adapter *adapter) begin(ctx context.Context, options pgx.TxOptions, operation string) (pgx.Tx, error) {
tx, err := adapter.pool.BeginTx(ctx, options) tx, err := adapter.pool.BeginTx(ctx, options)
if err != nil { if err != nil {
return nil, databaseError(ctx, operation, err) return nil, databaseError(ctx, operation, err)
@ -93,8 +93,6 @@ func databaseError(ctx context.Context, operation string, err error) error {
switch postgresError.Code { switch postgresError.Code {
case "23505": case "23505":
sentinel = adminstate.ErrConflict sentinel = adminstate.ErrConflict
case "22001", "22003", "22P02":
sentinel = adminstate.ErrInvalidCommand
} }
} }
return fmt.Errorf("postgresadmin: %s: %w", operation, sentinel) return fmt.Errorf("postgresadmin: %s: %w", operation, sentinel)

View File

@ -181,6 +181,14 @@ func TestDatabaseErrorsAreMappedAndRedacted(t *testing.T) {
}, },
want: adminstate.ErrUnavailable, want: adminstate.ErrUnavailable,
}, },
{
name: "value too long",
err: &pgconn.PgError{
Code: "22001",
Message: "backend encoding failed with secret details",
},
want: adminstate.ErrUnavailable,
},
} }
for _, test := range tests { for _, test := range tests {
test := test test := test

View File

@ -30,7 +30,7 @@ const (
) VALUES ($1, $2, $3, $4, $5, $6)` ) VALUES ($1, $2, $3, $4, $5, $6)`
) )
func (adapter *Adapter) CommitConfig( func (adapter *adapter) CommitConfig(
ctx context.Context, ctx context.Context,
command adminstate.CommitConfigCommand, command adminstate.CommitConfigCommand,
) (adminstate.MutationResult, error) { ) (adminstate.MutationResult, error) {
@ -125,7 +125,7 @@ func (adapter *Adapter) CommitConfig(
}, nil }, nil
} }
func (adapter *Adapter) SetUpstreamEnabled( func (adapter *adapter) SetUpstreamEnabled(
ctx context.Context, ctx context.Context,
command adminstate.SetUpstreamCommand, command adminstate.SetUpstreamCommand,
) (adminstate.MutationResult, error) { ) (adminstate.MutationResult, error) {
@ -208,7 +208,7 @@ func (adapter *Adapter) SetUpstreamEnabled(
}, nil }, nil
} }
func (adapter *Adapter) SwitchRouting( func (adapter *adapter) SwitchRouting(
ctx context.Context, ctx context.Context,
command adminstate.SwitchRoutingCommand, command adminstate.SwitchRoutingCommand,
) (adminstate.MutationResult, error) { ) (adminstate.MutationResult, error) {
@ -301,7 +301,7 @@ func (adapter *Adapter) SwitchRouting(
}, nil }, nil
} }
func (adapter *Adapter) beginMutation(ctx context.Context, operation string) (pgx.Tx, int64, error) { func (adapter *adapter) beginMutation(ctx context.Context, operation string) (pgx.Tx, int64, error) {
tx, err := adapter.begin(ctx, pgx.TxOptions{AccessMode: pgx.ReadWrite}, operation) tx, err := adapter.begin(ctx, pgx.TxOptions{AccessMode: pgx.ReadWrite}, operation)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err

View File

@ -10,7 +10,7 @@ import (
"proxy-pool/internal/domain/adminstate" "proxy-pool/internal/domain/adminstate"
) )
func (adapter *Adapter) Claim( func (adapter *adapter) Claim(
ctx context.Context, ctx context.Context,
command adminstate.ClaimCommand, command adminstate.ClaimCommand,
) ([]adminstate.Event, error) { ) ([]adminstate.Event, error) {
@ -106,7 +106,7 @@ func (adapter *Adapter) Claim(
return events, nil return events, nil
} }
func (adapter *Adapter) Acknowledge( func (adapter *adapter) Acknowledge(
ctx context.Context, ctx context.Context,
command adminstate.AcknowledgeCommand, command adminstate.AcknowledgeCommand,
) error { ) error {

View File

@ -9,7 +9,7 @@ import (
"proxy-pool/internal/domain/adminstate" "proxy-pool/internal/domain/adminstate"
) )
func (adapter *Adapter) Snapshot(ctx context.Context) (adminstate.Snapshot, error) { func (adapter *adapter) Snapshot(ctx context.Context) (adminstate.Snapshot, error) {
if err := contextError(ctx); err != nil { if err := contextError(ctx); err != nil {
return adminstate.Snapshot{}, err return adminstate.Snapshot{}, err
} }
@ -78,7 +78,7 @@ func (adapter *Adapter) Snapshot(ctx context.Context) (adminstate.Snapshot, erro
return snapshot, nil return snapshot, nil
} }
func (adapter *Adapter) ReadAudit( func (adapter *adapter) ReadAudit(
ctx context.Context, ctx context.Context,
query adminstate.AuditQuery, query adminstate.AuditQuery,
) ([]adminstate.AuditRecord, error) { ) ([]adminstate.AuditRecord, error) {