fix: land the stranded inbound-webhook + broadcast reliability work on main - #449
Open
ArnasDon wants to merge 1 commit into
Open
fix: land the stranded inbound-webhook + broadcast reliability work on main#449ArnasDon wants to merge 1 commit into
ArnasDon wants to merge 1 commit into
Conversation
…es, and partial failure Addresses four reliability bugs (#367, #368, #369, #370). Each pairs a DB-level guarantee (new migration 037) with the corresponding code change, since the application layer alone can't make these operations atomic. downstream side effect. Adds a unique index on (conversation_id, message_id) — the correctly-scoped idempotency key — and turns the message INSERT into an ON CONFLICT DO NOTHING upsert. An empty result means "replay": acknowledged as a no-op before the unread bump and all fan-out. after(), so a serverless freeze could interrupt them. They are now awaited via Promise.all; each keeps its own .catch so one failure neither blocks the others nor becomes an unhandled rejection. read-modify-write. Replaced with a DB-side atomic increment (bump_conversation_on_inbound RPC), mirroring migration 007. no recipients. Parent + recipients are now inserted in one transaction (create_broadcast_with_recipients RPC); a recipient failure rolls the parent back. Adds regression tests for all four (webhook route + broadcast-core). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Updates to Preview Branch (fix/webhook-broadcast-reliability-replay) ↗︎
Tasks are run on every commit but only new migration files are pushed.
❌ Branch Error • Wed, 29 Jul 2026 20:16:17 UTC View logs for this Workflow Run ↗︎. |
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.
Re-lands commit
e6e34bd— the work reviewed and approved in #388 — whichnever reached
main.What happened
#388 was opened with
fix/duplicate-conversationsas its base rather thanmain. That branch had already merged tomainvia #364, so when #388 mergedon 2026-07-14 its content went into a branch that was already spent.
mainhas been missing all of it since:
supabase/migrations/037_webhook_broadcast_reliability.sql(conversation_id, message_id)unique index and the idempotentupsert(..., { ignoreDuplicates: true })that is the inbound webhook's onlyreplay boundary ([BUG] Replayed inbound WhatsApp webhook duplicates messages and downstream side effects #367)
bump_conversation_on_inboundRPC that makes the unread bump atomicinstead of a lost-update read-modify-write ([BUG] Concurrent inbound WhatsApp messages can lose unread-count increments #369)
create_broadcast_with_recipients, which makes broadcast creationtransactional so a failed recipient insert can't orphan a parent row ([BUG] Failed broadcast recipient insertion leaves an orphaned sending broadcast #370)
webhook/route.test.tsandbroadcast-core.test.tscoverageSo on
maintoday, a Meta webhook retry still double-counts unread andre-fires automations, flows, and AI auto-reply for the same message.
Side effect worth noting: migration number
037has been sitting free, andopen PR #403 has claimed it for
037_agent_templates_permission.sql. One ofthe two will need renumbering.
One conflict, resolved toward main
mainhas since gained59dbf27(#409), which made the automation-triggerdispatch inside
after()sequential.e6e34bdhad made the same dispatchconcurrent via
Promise.all(#368). Both fix the same underlying hazard —a detached promise being frozen when the
after()callback resolves — so Ikept
main's sequential version, which is the newer and more conservative ofthe two and avoids concurrent automations racing on the same log row. Nothing
e6e34bdneeded is lost.Verification
eslint39 warnings / 0 errors (unchanged frommain),tsc --noEmitclean,658 tests pass,
next buildexits 0.Not exercised against a live Supabase — the migration is unchanged from the
version already reviewed in #388, but it has never actually been applied to a
database on the
mainline, so it deserves a look before deploy.🤖 Generated with Claude Code