Transactional enqueue: insert jobs inside your database transaction, so a job exists if and only if the business write committed.
Postgrex.transaction(MyApp.Pool, fn conn ->
create_order!(conn, order)
{:ok, _job} =
Belay.Txn.insert(conn, MyApp.Belay, MyApp.FulfillOrder.new(%{"id" => order.id}))
end)Works identically with an Ecto repo (anything exporting query!/2):
MyApp.Repo.transaction(fn ->
order = MyApp.Repo.insert!(changeset)
{:ok, _job} =
Belay.Txn.insert(MyApp.Repo, MyApp.Belay, MyApp.FulfillOrder.new(%{"id" => order.id}))
end)Belay itself takes no Ecto dependency — the bridge is duck-typed over
query!, and the SQL is exactly what the Postgres storage adapter runs.
Wake-ups are transactional too. When the instance has the :postgres
notifier configured, the poke is issued with pg_notify inside the same
transaction — Postgres delivers notifications only on commit, so workers
wake at the exact moment the job becomes real, and a rollback wakes nobody.
Without that notifier, committed jobs are picked up by the adaptive polling
floor (busy_poll..poll_interval).
Requires the named Belay instance to be running in this VM (it supplies worker defaults, the clock, and notifier configuration), and Postgres storage.
Summary
Functions
Insert one job in the caller's transaction. Returns {:ok, job} (duplicates flagged).
Insert many jobs in the caller's transaction. Returns inserted jobs (dedupes skipped).
Functions
@spec insert(term(), Belay.instance(), Belay.buildable()) :: {:ok, Belay.Job.t()}
Insert one job in the caller's transaction. Returns {:ok, job} (duplicates flagged).
@spec insert_all(term(), Belay.instance(), [Belay.buildable()]) :: [Belay.Job.t()]
Insert many jobs in the caller's transaction. Returns inserted jobs (dedupes skipped).