Move an Oban installation's pending work into Belay.
Converts available, scheduled, and retryable rows from oban_jobs
into ready Belay jobs (scheduled/retryable keep their scheduled_at
as ready_at). Everything else is deliberately left alone:
executingrows are flagged, never migrated — they may be mid-run on a live Oban node. Stop or drain Oban first.Terminal rows (
completed,discarded,cancelled) are history, not work. Migrating them would produce journal-less, cost-less rows that pollute Belay's metrics while buying nothing. Keep the old table read-only until your retention window lapses, then drop it:ALTER TABLE oban_jobs RENAME TO oban_jobs_archive;
Runs are idempotent: each migrated row carries
meta.migrated_from_oban_id, and re-runs skip ids already present.
Uniqueness cannot be inferred — Oban stores unique policy on the worker,
Belay stores unique keys on rows. The analyzer lists workers whose
pending rows may need unique: re-declared at their insert sites.
Used by mix belay.migrate_oban; callable directly:
{:ok, conn} = Postgrex.start_link(...)
report = Belay.Migrate.Oban.analyze(conn)
Belay.Migrate.Oban.execute(conn, report)
Summary
Functions
@spec analyze( GenServer.server(), keyword() ) :: map()
Inspect oban_jobs and return a migration report (no writes).
Options: :mapping — %{"Old.Worker" => "New.Worker"} kind renames.
@spec execute(GenServer.server(), map(), keyword()) :: %{ migrated: non_neg_integer(), skipped_existing: non_neg_integer() }
Migrate the pending rows described by analyze/2's report. Returns
%{migrated: n, skipped_existing: n}. Only workers that resolve to a
Belay worker module are migrated unless force: true.