Skip to content

Job retry WEBHOOK_DISPATCH branch passes a dict where a delivery id is expected, and no code ever creates such jobs #387

Description

@usmanimamu17-create

Problem

retry_job (app/api/v1/endpoints/jobs.py) has a webhook branch:

elif job.job_type == JobType.WEBHOOK_DISPATCH:
    from app.tasks.webhook_tasks import dispatch_webhook_delivery
    task_result = dispatch_webhook_delivery.delay(payload)   # payload is the parsed JSON dict

dispatch_webhook_delivery(self, delivery_id: str) (app/tasks/webhook_tasks.py) expects a delivery UUID string and immediately calls UUID(delivery_id) — passing the payload dict raises TypeError inside the task, which then retries 5 times and dies.

Separately, JobType.WEBHOOK_DISPATCH is referenced nowhere else: no code path creates a job with that type (app/tasks/sla_tasks.py only creates SLA_COMPUTATION/BULK_SLA_COMPUTATION), so the branch is unreachable today.

Consequences:

  • The branch is broken if ever reached: a manually-inserted or future webhook job retried through the API schedules a task that fails on UUID({...}) — the retry is silently doomed, and the audit event job_retry_initiated records a success that will never happen.
  • The dead branch is a trap for the webhook-dispatch work: when webhook dispatch jobs are introduced (the service already documents webhook delivery retry semantics), this path will mislead a contributor into thinking retry works.
  • The branch's payload semantics are undefined: a webhook job's payload should carry a delivery_id, not the raw event dict the SLA paths use — the two job types have different payload shapes and the retry code treats them the same.

Root cause

The retry branch was scaffolded to match the enum without the corresponding job-creating code path or a payload contract.

Why this is architecturally hard

  1. The fix requires defining what a WEBHOOK_DISPATCH job's payload is (the delivery id? the event?) and who creates such jobs — either remove the branch and the enum value, or implement the creator and a schema-validated retry.
  2. If kept, the branch must validate payload is a string delivery id before .delay(), mirroring dispatch_delivery(db, UUID(delivery_id))'s expectations.
  3. A test must create a WEBHOOK_DISPATCH job (or assert the branch is unreachable) — today the enum value and branch are completely untested.

Proposed design

Either delete the WEBHOOK_DISPATCH retry branch (and the enum value) until webhook jobs exist, or implement job creation for webhook dispatch with a delivery_id payload and fix the .delay(payload) call to pass the id. Add a test covering whichever path remains.

Acceptance criteria

Service

  • No retry path can schedule a task with an invalid delivery id.
  • WEBHOOK_DISPATCH jobs are either creatable with a validated payload or the branch is removed.

Tests

  • A test covers the remaining branch (valid retry or explicit rejection).
  • Existing job tests pass.

Out of scope

The duplicate-row retry bug (tracked separately) and webhook delivery semantics.

Getting started

pytest tests/test_payment_retry_queue_backoff.py -q
make typecheck

Good first files to read: app/api/v1/endpoints/jobs.py, app/tasks/webhook_tasks.py, app/models/job.py.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardStellar WaveIssues in the Stellar wave programThird CampaignCampaign: Third Campaignarea/jobsImported campaign issue labelpriority/highImportant; address in current quarter

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions