62 lines
1.7 KiB
Go
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
|
|
}
|