Skip to content

Commit 3fe0fe7

Browse files
fix(worker): populate forwarder_sent.audit_log_id for UUID-shaped audit_ids (mig 072)
Companion to api mig 072 (forwarder_sent.audit_log_id UUID FK column). markSent now includes audit_log_id in the INSERT column list and populates it via an inline CASE expression: CASE WHEN $1 ~* '^[0-9a-f]{8}-...-[0-9a-f]{12}$' THEN $1::uuid ELSE NULL END This means: - Real UUID audit_ids (post-mig-063 rows from audit_log-backed emitters) → audit_log_id set; the orphan-reconciler can JOIN on the typed UUID column instead of scanning with a regex over TEXT. - Placeholder IDs ("reminder-<resource_id>-<stage>", "provider-<grace_id>") → audit_log_id stays NULL; no behaviour change for those legacy emitters. Test update: TestForwarder_LedgerClaim_AllColumnsRoundtripThroughInsert updated to match the new column list + CASE expression in the INSERT regex.
1 parent e7d23c6 commit 3fe0fe7

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

internal/jobs/event_email_forwarder.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,21 @@ func (l *sqlSentLedger) isSent(ctx context.Context, auditID string) (bool, error
249249
// answer "what happened to email X" without log-spelunking. The caller
250250
// MUST pre-mask the recipient (see ledgerClaim doc).
251251
func (l *sqlSentLedger) markSent(ctx context.Context, c ledgerClaim) (bool, error) {
252+
// audit_log_id is the real UUID FK companion to the soft-FK audit_id TEXT
253+
// column (mig 072). Populate it when audit_id is UUID-shaped so the
254+
// orphan-reconciler and team-deletion cascade can use a typed JOIN.
255+
// Placeholder IDs ("reminder-<resource_id>-<stage>", "provider-<grace_id>")
256+
// leave audit_log_id NULL — the SQL CASE never casts them.
252257
res, err := l.db.ExecContext(ctx, `
253258
INSERT INTO forwarder_sent
254-
(audit_id, provider, provider_id, recipient, template_kind, classification)
255-
VALUES ($1, $2, $3, $4, $5, $6)
259+
(audit_id, provider, provider_id, recipient, template_kind, classification, audit_log_id)
260+
VALUES (
261+
$1, $2, $3, $4, $5, $6,
262+
CASE WHEN $1 ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
263+
THEN $1::uuid
264+
ELSE NULL
265+
END
266+
)
256267
ON CONFLICT (audit_id) DO NOTHING
257268
`, c.AuditID, c.Provider, c.ProviderID, c.Recipient, c.TemplateKind, c.Classification)
258269
if err != nil {

internal/jobs/event_email_forwarder_coverage_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,11 @@ func TestEventForwarder_CursorWriteErr_AfterPermanent(t *testing.T) {
938938
func TestForwarder_LedgerClaim_AllColumnsRoundtripThroughInsert(t *testing.T) {
939939
db, mock, _ := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
940940
defer db.Close()
941-
mock.ExpectExec(`INSERT INTO forwarder_sent\s*\(audit_id, provider, provider_id, recipient, template_kind, classification\)`).
941+
// SQL now includes audit_log_id (mig 072): the CASE expression sets it to
942+
// $1::uuid when audit_id is UUID-shaped, NULL otherwise. The regex matches
943+
// the new column list and the CASE expression so this test catches any
944+
// future column drift.
945+
mock.ExpectExec(`INSERT INTO forwarder_sent\s*\(audit_id, provider, provider_id, recipient, template_kind, classification, audit_log_id\)`).
942946
WithArgs("a1", providerNoneMissingRenderer, providerIDMissingRenderer, "a***@example.com", "anon.expiry_warning", ledgerClassPermanentDrop).
943947
WillReturnResult(sqlmock.NewResult(0, 1))
944948

0 commit comments

Comments
 (0)