Add webhook-event retention job, schema, and testdb pre-flight hint
square_webhook_events is now CREATE TABLE IF NOT EXISTS, registered as the 24th maintenance job (sweep-square-webhook-events, daily 2:30am) pruning rows older than 90 days, and testdb gives a clear docker compose hint when the admin DB connection fails.
This commit is contained in:
@@ -1,14 +1,21 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"crussell/auth"
|
||||
"crussell/db"
|
||||
authHandlers "crussell/handlers/auth"
|
||||
"crussell/handlers/payments"
|
||||
"crussell/handlers/scheduling"
|
||||
"crussell/handlers/user"
|
||||
"crussell/mw"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
// RegisterAll registers every background maintenance job on the scheduler.
|
||||
@@ -214,4 +221,41 @@ func RegisterAll(s *Scheduler) {
|
||||
Concurrency: 1,
|
||||
Handler: scheduling.CleanupExpiredRefreshTokens,
|
||||
})
|
||||
|
||||
// Staggered from cleanup-verification-codes / cleanup-refresh-tokens
|
||||
// (both at 0 2 * * *) to avoid DB contention.
|
||||
s.Register(Job{
|
||||
Name: "sweep-square-webhook-events",
|
||||
Schedule: "30 2 * * *", // Daily at 2:30am
|
||||
Timeout: 30 * time.Second,
|
||||
Concurrency: 1,
|
||||
Handler: SweepSquareWebhookEvents,
|
||||
})
|
||||
}
|
||||
|
||||
// SweepSquareWebhookEvents deletes square_webhook_events rows older than 90
|
||||
// days. Every accepted webhook event_id is stored permanently for restart-safe
|
||||
// dedup (payment.updated fires on every payment update), so without retention
|
||||
// the table would grow without bound. 90 days comfortably exceeds Square's
|
||||
// webhook replay window while keeping the table bounded.
|
||||
func SweepSquareWebhookEvents(ctx context.Context) (int, error) {
|
||||
tx, err := db.Conn.Begin(ctx)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to begin transaction: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
tag, err := tx.Exec(ctx, `
|
||||
DELETE FROM square_webhook_events
|
||||
WHERE received_at < NOW() - INTERVAL '90 days'
|
||||
`)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to sweep square webhook events: %w", err)
|
||||
}
|
||||
|
||||
return int(tag.RowsAffected()), tx.Commit(ctx)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user