Skip to content

fix(revoke): detach the Azure Return call once the claim is held, so a request timeout mid-Return can't lose the record #1527

Closed

Description

@IAmJSD

Problem

After #1526, the writes that follow an accepted Azure Return survive request cancellation, but the Return call itself still runs on the request context. The app's HTTP server gives every request a 30s deadline (internal/server/http.go). If that deadline or a client disconnect hits while the Return is in flight, Azure may still accept it, but the handler sees an error, nothing records the Return, and the in-flight flag stays set (clearing it uses the same dead context). The sweep then releases the row after 2h, so a refunded purchase reads as active. Azure refuses a second Return, so there is no double refund.

Elsewhere the repo does the opposite: the RI exchange handler (#790) and purchase/manager.go detach the provider call once the claim is held.

Proposal

  1. Once the in-flight claim is held, run the Azure Return call on a detached context (ctxutil.DetachedWithTimeout) with a bounded timeout, as RI exchange does. The claim itself stays on the request context, so a canceled request still never takes the claim or starts a Return.
  2. Make the retry waits after the Return respect the 30s budget (today the sleeps ignore it, so the worst case is about 43s), so that a hung first attempt doesn't use up the whole budget.
  3. Correct the comments in finalize_revocations.go and the revoke handler: they say Fargate and Container Apps don't cap request time, but the app's own server caps every request at 30s.

Acceptance criteria

  • A test where the request is canceled while the stub Azure Return is in flight and then accepted: the Return is recorded and the purchase is marked revoked.
  • A request canceled before the claim still takes no claim and posts no Return.

Refs #1523, #1525, #1526

Activity

  1. IAmJSD commented on Oct 27, 2026

    @IAmJSD
    CollaboratorAuthor

    Claiming: working on this

  2. self-assigned this
    on Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions