A job's claim on a budget: which budget, and what it costs to dispatch.
Zizq.BudgetBinding.new!(key: "emails", cost: 2)Bindings are passed to the server as part of the enqueue operation, and so usually declared on a job module:
defmodule MyApp.SendEmail do
use Zizq.JobKind,
type: "send_email",
queue: "emails",
budgets: [[key: "emails", cost: 2]]
@impl Zizq.JobKind
def perform(payload), do: MyApp.Mailer.deliver(payload)
end:cost
How many tokens one job debits from the budget when it dispatches,
defaulting to 1. Jobs can therefore weigh differently against the
same budget — a bulk send costing 10 against an allocation of 100
leaves room for 90 more single sends.
A cost has to fit inside the budget's Zizq.Budget.capacity/1, or the
job would forever be held back from dispatching. The server refuses a
binding that does not satisfy the invariant.
:create_with
Declares the budget's policy should it not exist yet, so binding and creating happen in one atomic request rather than over two:
Zizq.BudgetBinding.new!(
key: "emails",
cost: 2,
create_with: [
allocation: 100,
strategy: :time_based,
duration: :timer.minutes(1)
]
)The key comes from the binding, so it is not repeated. It is ignored when the budget already exists — the server stays authoritative.
Without it, the budget has to exist before a job can bind to it.
Summary
Functions
Build a binding from a keyword list or map. Raises on invalid input.
Types
@type t() :: %Zizq.BudgetBinding{ cost: pos_integer() | nil, create_with: Zizq.Budget.t() | nil, key: String.t() }