The reaped-row fallback renders the exact zero timestamp that #257 was filed against #298
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found by the review of #297, and created by that PR's own deliberate fallback.
#257 fixed the timestamp by reading
created_atfrom the stored event row. A read failure on that path is intentionally NON-fatal — the delivery still goes out — because the event row can be hard-deleted by retention while a queued delivery still holds its inlined body, and dropping a deliverable event to protect one metadata field is the worse failure. That trade is right and is not what this issue disputes.The problem is what the fallback renders.
FormatSlackMessage(internal/delivery/target_slack.go:236) emits the Timestamp line unconditionally, so a fallback delivery carries:— the exact string #257 was filed against. Verified end to end: row hard-deleted, delivery goes out, WARN logged, payload carries the zero stamp.
So a human reading that message cannot distinguish "the event row was reaped, which is expected and harmless" from "the bug is back". The fallback is correct behaviour wearing the costume of a known defect.
The reaped-row path is real, not theoretical:
reapExpired(internal/database/retention.go:273-320) hard-deletes events purely oncreated_at < cutoffwith no delivery-status guard. Retention is day-granular, so the realistic trigger is an operator LOWERING a webhook'sRetentionDays, not a slow queue.Definition of done
CreatedAt.IsZero(),FormatSlackMessageomits the Timestamp line, or marks it in a way that reads as "unknown" rather than as a date in the year 1. Either is fine; state which you chose.0001-01-01.logtarget formats event metadata too — if it prints a zero time in the same situation, it has the same problem for the same reason.Not milestoned: the delivery still goes out with its payload intact, which is what matters, and the trigger requires retention to reap a row while a delivery holding its body is still queued.