Problem
A verification poll is only queued when a webhook is persisted in internal/webhook/handler.go:159. internal/hold/store.go:35 creates the hold but does not create any verification work.
If the webhook never arrives, the transaction can sit in PENDING until the TTL scanner runs a final check. That is too late. Missing webhooks are normal gateway behavior and should be handled by the poll schedule.
Scope
- Queue the first
verification_polls row when a hold is created.
- Make the hold insert and initial poll insert atomic, or make retry behavior explicit and tested.
- Keep webhook-triggered polling useful, but prevent duplicate attempt 1 rows when both hold creation and webhook receipt happen.
- Add a uniqueness guard for poll attempts, for example one row per
txn_id and attempt_number, if that is the chosen approach.
- Use the existing lag schedule for later attempts. Do not invent a second schedule in the hold package.
- Decide whether the first poll is immediate or scheduled after the first configured delay, then test that decision.
Acceptance criteria
- Creating a hold creates one pending verification poll without waiting for a webhook.
- Receiving a webhook for that hold does not create a duplicate attempt 1 poll.
- A hold with no webhook gets at least one gateway status check before TTL expiry.
- Duplicate identical hold create requests do not create extra polls.
- Tests cover create only, webhook only, create then webhook, and duplicate create cases.
Problem
A verification poll is only queued when a webhook is persisted in
internal/webhook/handler.go:159.internal/hold/store.go:35creates the hold but does not create any verification work.If the webhook never arrives, the transaction can sit in
PENDINGuntil the TTL scanner runs a final check. That is too late. Missing webhooks are normal gateway behavior and should be handled by the poll schedule.Scope
verification_pollsrow when a hold is created.txn_idandattempt_number, if that is the chosen approach.Acceptance criteria