Belay.Txn (Belay v2.0.0)

Copy Markdown View Source

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

insert(conn_or_repo, name, buildable)

@spec insert(term(), Belay.instance(), Belay.buildable()) :: {:ok, Belay.Job.t()}

Insert one job in the caller's transaction. Returns {:ok, job} (duplicates flagged).

insert_all(conn_or_repo, name, buildables)

@spec insert_all(term(), Belay.instance(), [Belay.buildable()]) :: [Belay.Job.t()]

Insert many jobs in the caller's transaction. Returns inserted jobs (dedupes skipped).