Background Job Playbook
HARD-GATE
- Idempotency key and error classification are documented before implementation.
- A failing worker test exists and fails for the right reason before
perform/1is written. perform/1is a thin edge: fetch IDs → pure core → return tagged tuple.- Failure paths are tested; user approves the worker design.
mix format --check-formatted,mix credo --strict, and the fullmix testsuite are green before the PR is opened.
When to use
Adding or hardening Oban (or similar) background workers.
Atomic skills this playbook loads
| Skill | Path | Role |
|---|---|---|
oban-essentials |
skills/oban-essentials/ |
Worker patterns |
testing-essentials |
skills/testing-essentials/ |
Oban.Testing |
elixir-essentials |
skills/elixir-essentials/ |
FCIS |
telemetry-essentials |
skills/telemetry-essentials/ |
Metrics |
Flow
flowchart TD
A[Idempotency + error classes] --> B[Failing perform test]
B --> C[HITL: approve worker design]
C --> D[Thin perform/1 + context]
D --> E[Retry discard unique tests]
E --> F[Telemetry optional]
Agent Phases
Phase 1 — Design
Document: queue, args (IDs only), idempotency key, transient vs permanent errors.
HARD GATE — Idempotency and error classification:
- Queue, args (IDs only), idempotency key, and error classes are documented.
- Transient vs permanent errors are classified.
If gate fails: Revisit the design doc; do not write perform/1 until the contract is clear.
Phase 2 — RED
Worker test expecting success/cancel/error paths; must fail until implemented.
HARD GATE — Failing worker test:
- A worker test exists for success, cancel, and error paths.
- The test fails for the right reason before
perform/1is written.
If gate fails: Adjust the test so it exercises missing behaviour, not a syntax/config mistake.
Phase 3 — HITL impl
- Propose
perform/1as edge: fetch → domain → tuple. - HUMAN-IN-THE-LOOP: approve.
- Implement; enqueue from context, not LiveView.
HARD GATE — Thin perform/1:
-
perform/1fetches IDs, delegates to a pure core/domain function, and returns a tagged tuple. - User approves the worker design before implementation.
- Enqueue happens from context, not LiveView.
If gate fails: Extract logic into a context or pure function; re-HITL the design.
Phase 4 — Failure paths
Cover: not found → cancel; transient → error/retry; duplicate → unique.
HARD GATE — Failure paths tested:
-
not_foundpath returns{:cancel, _}or equivalent. - Transient errors are retried; permanent errors are discarded.
- Duplicate jobs are handled via
uniqueoptions or idempotency key.
If gate fails: Add missing tests and handling for each failure class.
Phase 5 — Monitor
Attach telemetry/logging for failures if production-bound.
HARD GATE — User approval and green suite:
- User approves the final worker design.
-
mix format --check-formatted,mix credo --strict, andmix testpass. - Telemetry/logging is attached for production failures.
If gate fails: Fix formatting, Credo, or test failures; re-HITL if the design changed.
Verification checklist
- Idempotency plan
- Tests for success and failure classes
- HITL approval
- No large payloads in args
- Enqueue from context
Error Recovery
Non-idempotent side effects → add guards/unique; re-test double perform.
Output Style
## Background Job Report
**Design:** <queue, args, idempotency key, error classes>
**Test command:** `<mix test command>`
**HARD-GATE results:**
- Idempotency and error classification: PASS / FAIL
- Failing worker test: PASS / FAIL
- Thin perform/1: PASS / FAIL
- Failure paths tested: PASS / FAIL
- User approval and green suite: PASS / FAIL
**Verdict:** APPROVE / REQUEST_CHANGES