Repository navigation
expqueue 0.1.0
expqueue 0.1.0 (2026-10-11)
The first release: a generic, database-backed job queue for Exponential 6.
Added
- Added: Seven tables (job, group, event, resource, class, mutex, worker) for MySQL/MariaDB, PostgreSQL, SQLite,
Oracle and MongoDB from one definition, withext:expqueue:install-schema(install, upgrade, check, print,
write-files),share/db_schema.dbaandsql/<engine>/. - Added: The producer API
expQueue::enqueue()with class, priority, group, idempotency key, resource, not-before,
max attempts, timeout, dependency, user and site; groups; cancel; requeue; pause and resume per queue, class,
resource and group; purge. - Added: The handler contract (
expQueueHandler,expQueueHandlerBase,expQueueResult, retryable and permanent
exceptions) and the context: heartbeat and lease extension, cooperative cancellation, progress, the result
checkpoint, rate-limit hints, cost, log lines. - Added: The scheduler: stride scheduling over class weights, a reserved system class, aging, a starvation guard
across and within classes, MinShare, MaxRunning per class, quotas per user and site, concurrency limits per
resource that adapt to 429 / retry-after / remaining-requests hints, rules at enqueue time. - Added: Leases with a compare-and-set claim, a reaper, retries with exponential backoff and jitter that honour
retry-after, a dead letter, defer and hold. - Added: Workers:
ext:expqueue:work, the cron partexpqueue(maintenance, hourly purge, a worker slice when no
other worker is alive) andext:expqueue:service install|start|stop|status|uninstallfor systemd. Commands started
as root become the site user; jobs never run in a web request or a Velocity worker. - Added: The CLI
status,list,show,enqueue,cancel,pause,resume,retry,purge, and the test
job typesexpqueue.noop,expqueue.sleep,expqueue.fail. - Added: Setup > Job queue: dashboard, job list, job and group pages with controls; policies
expqueue/viewand
expqueue/manage; translations eng-US and ger-DE; the audit branchsystem.queue.*.
Measured before the release (sandbox, SQLite, 12-core host under load 20-45)
- Scale run: 990 jobs (900 translation_full of which half on a resource limited to 1, 50 editorial on a resource
limited to 2, 10 interactive, 10 failing jobs, 20 idempotency keys queued twice), 2 workers at once: queued in
6.5 s (6.5 ms per enqueue), worked in 83 s (1,004 runs including retries). The 10 interactive jobs ended by 2.0 s,
the 50 editorial ones by 7.8 s; 9 translation jobs ended while editorial ones still waited (no starvation). The
limited resources never ran more than 1 and 2 jobs at once. Every job ended exactly once; 20 duplicates were
returned; retryable failures went to the dead letter after 3 attempts with growing delays, a 429 with retry-after
3 s was never retried sooner, and the resource got the cooldown. - Fairness: 300 editorial, 100 bulk and 60 translation_full jobs at once, 1 worker: the first 150 starts were 76 %
editorial, 13.3 % translation_full and 10.7 % bulk (stride targets 77 / 12.8 / 10.3 %). A priority-0 bulk job
started after 18 s although 100 priority-100 bulk jobs waited (starvation guard). - Reaper: a worker killed with kill -9 in the middle of a 6 s job: the lease expired, a second worker ran the job once
more (events: enqueue, claim, reap, claim, done), attempts 2. - SQLite contention: 400 no-op jobs, 2 workers: 42 jobs per second, no lost claim and no busy error.