Oban Chore provides an Oban plugin to generate a dashboard to run Oban jobs
Motivation
In previous jobs, I often had to run Oban jobs manually for things like backfills or specific support actions. Doing this meant SSH-ing into production and manually typing commands to run the job, which carries inherent security risks.
Additionally, direct access to the Elixir node isn’t always available. While we could use the Oban dashboard, we often don’t want to give full access to this dashboard to non-technical staff. This unfortunately turns developers into a bottleneck for customer support and operations teams.
Oban Chore solves this by giving you a visual interface to handle these tasks directly from the browser, empowering non-technical users to safely run jobs.
Highlights
• Zero-Boilerplate UI Generation: Define input schemas directly inside your worker, and let ObanChore generate the form components automatically.
• Live Execution Streaming: Leveraging Phoenix PubSub and Telemetry, the dashboard streams logs and status updates from the process directly to the user’s browser in real-time.
• Idempotency Check: Automatically detects if a job with the same arguments is already running.
• Unique Execution Toggle: Manually enforce single-job execution via the dashboard UI. (you can override this from the job definition)
• Validation: Full Ecto-backed validation for all chore arguments.
Quick Example
- Configure Oban
# config/config.exs
config :my_app, Oban,
repo: MyApp.Repo,
plugins: [
{ObanChore.Plugin, otp_app: :my_app, pubsub_server: MyApp.PubSub}
],
queues: [default: 10]
- Define your Chore Worker:
defmodule MyApp.Chores.UserBackfill do
use ObanChore.Worker,
name: "User Data Backfill",
description: "Backfills historical data for a specific user.",
fields: [
user_id: [type: :integer, required: true, label: "Target User ID"],
reason: [type: :string, default: "Manual correction", label: "Reason"]
]
@impl Oban.Worker
def perform(%Oban.Job{args: %{"user_id" => user_id, "reason" => reason}} = job) do
ObanChore.log(job, "Starting user backfill for user #{user_id}")
# Your execution logic here...
ObanChore.log(job, "Done!")
:ok
end
# Optional: Customize changeset validation
@impl ObanChore.Worker
def custom_changeset(changeset) do
Ecto.Changeset.validate_number(changeset, :user_id, greater_than: 0)
end
end
- Mount the Dashboard:
# lib/my_app_web/router.ex
defmodule MyAppWeb.Router do
use MyAppWeb, :router
import ObanChore.Router
scope "/" do
pipe_through :browser
oban_chore_dashboard "/ops/chores"
end
end
Status & Feedback
Please note that this library is currently under active development. As this is an early release, any feedback, architecture suggestions, or ideas for new use cases are welcome!
Links
• Hex Package: oban_chore | Hex
• Documentation: ObanChore 🎭 — ObanChore v0.3.3
























