Files
galaxy-game/notification/internal/adapters/postgres/notificationstore/dead_letters.go
T
2026-04-26 20:34:39 +02:00

62 lines
1.7 KiB
Go

package notificationstore
import (
"context"
"database/sql"
"time"
pgtable "galaxy/notification/internal/adapters/postgres/jet/notification/table"
)
// deadLetterRow stores the column values written to one dead_letters row.
// Kept package-private because the public surface is the routestate
// CompleteRouteDeadLetterInput shape; this struct is only the on-disk
// projection.
type deadLetterRow struct {
NotificationID string
RouteID string
Channel string
RecipientRef string
FinalAttemptCount int
MaxAttempts int
FailureClassification string
FailureMessage string
RecoveryHint string
CreatedAt time.Time
}
// insertDeadLetter writes one dead-letter audit row inside an open
// transaction. The composite PRIMARY KEY guards against duplicate inserts
// for the same `(notification_id, route_id)` pair.
func insertDeadLetter(ctx context.Context, tx *sql.Tx, row deadLetterRow) error {
stmt := pgtable.DeadLetters.INSERT(
pgtable.DeadLetters.NotificationID,
pgtable.DeadLetters.RouteID,
pgtable.DeadLetters.Channel,
pgtable.DeadLetters.RecipientRef,
pgtable.DeadLetters.FinalAttemptCount,
pgtable.DeadLetters.MaxAttempts,
pgtable.DeadLetters.FailureClassification,
pgtable.DeadLetters.FailureMessage,
pgtable.DeadLetters.RecoveryHint,
pgtable.DeadLetters.CreatedAt,
).VALUES(
row.NotificationID,
row.RouteID,
row.Channel,
row.RecipientRef,
row.FinalAttemptCount,
row.MaxAttempts,
row.FailureClassification,
row.FailureMessage,
row.RecoveryHint,
row.CreatedAt.UTC(),
)
query, args := stmt.Sql()
if _, err := tx.ExecContext(ctx, query, args...); err != nil {
return err
}
return nil
}