mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 18:31:34 +01:00
Delivery retries reloaded the connection's currently-enabled triggers, so a trigger added or re-enabled between attempts could receive an envelope for an event that predated it. Capture the enabled trigger set atomically with the delivery claim (written in the INSERT branch, never rebuilt on reclaim) and route every attempt to that stored snapshot, so recovery can never reconstruct it from current configuration. Dispatch also moved a delivery to `forwarded` before invoking any destination, but the reclaim path only matched `failed` rows. A crash while `forwarded` left the row stuck and every later connector attempt returned `duplicate`, silently dropping the remaining trigger work. Add a lease (`lease_expires_at`) set on claim and renewed on forward; a later attempt may reclaim an abandoned in-progress delivery only once its lease has expired, so it never races a live worker. Per-trigger idempotency keys remain the correctness backstop. Covered with embedded-postgres tests: retries honor the original snapshot and skip newly enabled triggers; an abandoned forwarded delivery is dropped as a duplicate while its lease is live, reclaimed once it expires, and a trigger enabled after the crash never receives the recovered envelope. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-Authored-By: Paperclip <noreply@paperclip.ing>