Claude-elixir-phoenix oban
Oban job processing — workers, perform/1 (OSS) and process/1 (Pro), queues, cron, retries, unique jobs, idempotency, Oban Pro (Workflow, Batch, Chunk, Smart Engine), Testing. Use when writing Oban workers, queue config, or debugging jobs.
install
source · Clone the upstream repo
git clone https://github.com/oliver-kriska/claude-elixir-phoenix
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/oliver-kriska/claude-elixir-phoenix "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/elixir-phoenix/skills/oban" ~/.claude/skills/oliver-kriska-claude-elixir-phoenix-oban && rm -rf "$T"
manifest:
plugins/elixir-phoenix/skills/oban/SKILL.mdsource content
Oban Background Jobs Reference
Quick reference for Elixir Oban patterns.
Oban Pro Detection
Before applying patterns, check for Oban Pro:
grep -E "oban_pro|oban_web" mix.exs grep -r "use Oban.Pro.Worker" lib/ grep -r "Oban.Pro.Engines.Smart" config/
If Oban Pro detected, use Pro patterns for ALL new workers:
| Standard Oban | Oban Pro |
|---|---|
| |
| |
| |
| Advisory lock engine | |
Pro features (all optional):
args_schema (typed args), Workflows, Batches, Chunks,
Relay, hooks, encryption, deadlines, chaining, Smart Engine (global concurrency + rate limiting).
Pro plugins (DynamicCron, DynamicLifeline, DynamicPruner) enhance OSS equivalents — swap module, don't run both.
See ${CLAUDE_SKILL_DIR}/references/oban-pro-basics.md for all patterns and migration guide.
Iron Laws — Never Violate These
- JOBS MUST BE IDEMPOTENT — Safe to retry. Use idempotency keys for payments
- JOBS MUST STORE IDs, NOT STRUCTS — JSON serialization.
not%{user_id: 1}%{user: %User{}} - JOBS MUST HANDLE ALL RETURN VALUES —
,:ok
,{:error, _}
,{:cancel, _}{:snooze, _} - ARGS USE STRING KEYS — Pattern match
not%{"user_id" => id}%{user_id: id} - UNIQUE CONSTRAINTS FOR USER ACTIONS — Prevent double-click duplicates
- NEVER STORE LARGE DATA IN ARGS — Store references (IDs, paths), not content
- SMART ENGINE: NEVER USE
TO LIMIT SNOOZES — Snooze rolls back attempt counter. Useattempt
instead. Causes infinite loopsmeta["snoozed"]
Quick Worker Template
defmodule MyApp.Workers.ExampleWorker do use Oban.Worker, queue: :default, max_attempts: 5, unique: [period: {5, :minutes}, keys: [:entity_id]] @impl Oban.Worker def perform(%Oban.Job{args: %{"entity_id" => id}}) do case process(id) do {:ok, _} -> :ok {:error, :not_found} -> {:cancel, "Entity not found"} {:error, :rate_limited} -> {:snooze, {5, :minutes}} {:error, reason} -> {:error, reason} end end end
Return Value Meanings
| Return | State | Behavior |
|---|---|---|
| | Success |
| | Success with value |
| | Retry with backoff |
| | Stop permanently |
| | Delay and retry |
Quick Decisions
Which Queue?
- Critical operations → High concurrency (20+)
- Mailers/Webhooks (I/O) → Medium concurrency (30-50)
- CPU-intensive → Low concurrency (3-5)
- External APIs → Use
for rate limitingdispatch_cooldown
Testing Pattern
use Oban.Testing, repo: MyApp.Repo # Assert enqueued assert_enqueued worker: MyApp.Worker, args: %{id: 1} # Execute and verify assert :ok = perform_job(MyApp.Worker, %{id: 1})
Common Anti-patterns
| Wrong | Right |
|---|---|
pattern match | (string keys) |
in args | (IDs only) |
| No idempotency for payments | Use idempotency keys |
| Ignoring return values | Handle all outcomes explicitly |
References
For detailed patterns, see:
- Worker options, backoff, timeout${CLAUDE_SKILL_DIR}/references/worker-patterns.md
- Queue design, pool sizing, cron, Smart Engine${CLAUDE_SKILL_DIR}/references/queue-config.md
- Testing, assertions, drain (OSS + Pro)${CLAUDE_SKILL_DIR}/references/testing-patterns.md
- Pro.Worker, Workflow, Batch, Chunk, Relay, plugins${CLAUDE_SKILL_DIR}/references/oban-pro-basics.md