fix: add NOT EXISTS guard to stop notification_id_seq burn on repeated job runs - #1005
Open
dylanjeffers wants to merge 8 commits into
Open
fix: add NOT EXISTS guard to stop notification_id_seq burn on repeated job runs#1005dylanjeffers wants to merge 8 commits into
dylanjeffers wants to merge 8 commits into
Conversation
Add RunE method to execute the job once for CronJob.
Removed the Remix Contest Notifications job from the scheduler.
Implement main function for remix-contest-notifications job.
Updated Dockerfile to build and copy remix-contest-notifications.
This Kubernetes CronJob emits time-based remix-contest notifications at 20-minute intervals, reducing the scan frequency and preventing sequence ID burn in Postgres. It includes idempotency measures for safe concurrent execution.
Contributor
Author
Updated approach: CronJob as primary fixThis PR has been updated. The primary fix is now converting RemixContestNotificationsJob from a 30-second goroutine to a Kubernetes CronJob running every 20 minutes. The NOT EXISTS guard stays as belt-and-suspenders. Why CronJob instead of just NOT EXISTS? The NOT EXISTS guard fixes burn-per-run, but the job still polled every 30 seconds against the same 24-72h windows — 2,880 no-op queries/day per active contest. The CronJob cuts this to 72/day (40x reduction). What changed in this update:
Deploy note: Update namespace, image tag, and secretRef in the k8s manifest to match your cluster before applying. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
notification_id_seqcolumn hit INT max (2³¹−1) on July 29 because all four sub-steps inRemixContestNotificationsJobre-scan the same events on every 30-second tick and attempt duplicate INSERTs.Postgres allocates a sequence ID before checking
ON CONFLICT DO NOTHING, so every wasted attempt permanently burns an ID:fan_remix_contest_ending_soonartist_remix_contest_ending_soonfan_remix_contest_endedartist_remix_contest_endedJuly 29 spike: The Summer Cypher contest (1.97 M followers) entered the 72-hour ending-soon window. Each 30-second tick attempted 1.97 M INSERTs. After ~543 ticks (~4.5 h), ~1.07 B sequence IDs were burned — exhausting INT range and taking down notifications for all users.
Chronic baseline (~18 M IDs/day burned): Smaller active contests (combined fan audiences on the order of a few thousand) still burned millions of IDs daily through the same mechanism.
Fix
Add an event-level
NOT EXISTSguard to each of the four SQL blocks:Once any notification row exists for an event (i.e., after the first successful fan-out pass), subsequent job runs skip that event entirely. The per-recipient
ON CONFLICT DO NOTHINGis kept as a safety net for partial-failure retries.Effect: Each contest triggers at most one fan-out pass instead of thousands. Sequence consumption drops from O(recipients × job_runs_in_window) to O(recipients × 1) per event.
What this does NOT change
Testing
Existing
TestRemixContest_Endedalready asserts idempotency (runs the job twice and verifies the count stays the same).fanEndingSoonidempotency is implicitly covered: after the first run theNOT EXISTScheck short-circuits, so no inserts are attempted on re-runs.