Limits and fair claim¶
Limits¶
A limit is a row in akadze.limits keyed by a string. Jobs opt in with limit_key; the policy never lives on the job row, so you can change it while jobs wait.
from datetime import timedelta
from akadze import set_limit
async with app.engine.begin() as connection:
# at most 4 running at once, cluster-wide
await set_limit(connection, "vendor-x", max_running=4)
# and at most 100 starts per minute
await set_limit(connection, "vendor-x", max_starts=100, window=timedelta(minutes=1))
await call_vendor.using(session=connection, limit_key="vendor-x").enqueue(item_id=7)
max_runningcaps how many jobs with the key may berunningacross all workers.max_startswithwindowcaps how many claims may start in a sliding window. Starts are tracked inakadze.limit_starts, not by scanning jobs.- One call may set either or both; omitted fields keep their values.
clear_limit(connection, key)deletes the row and its start marks; the key becomes unlimited. A laterset_limitcounts starts from zero.- A
limit_keywithout a limits row, and an empty key, have no limit.
Limits hold under concurrent claims: a claim locks the limits rows of the keys it considers and counts running jobs and starts only after it holds the lock.
list_limits(engine) returns the policies; on the CLI, akadze limits list and akadze limits clear KEY.
Limits are cluster-wide. Worker(slots=...) is a separate, per-process cap.
Fair claim¶
By default a worker claims by priority, then run_at, then id. A tenant that enqueued a million jobs then takes every free slot while another tenant's two jobs wait.
Fair claim fixes that within a priority:
akadze worker app:app --fair
Worker(app, fair=True)
Jobs are grouped by limit_key (jobs without a key form one group). A free slot goes to the group with the fewest jobs already running in that queue across the cluster; ties go to the oldest job. This holds when slots free up one at a time and across many workers. Priority still comes first, and limits still apply.
A claim on a 100 000-job backlog takes a few milliseconds in both orders; see How a claim works.