Skip to content

expqueue 0.1.0

Choose a tag to compare

@se7enxweb se7enxweb released this 11 Oct 18:02
· 69 commits to main since this release

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, with ext:expqueue:install-schema (install, upgrade, check, print,
    write-files), share/db_schema.dba and sql/<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 part expqueue (maintenance, hourly purge, a worker slice when no
    other worker is alive) and ext:expqueue:service install|start|stop|status|uninstall for 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 types expqueue.noop, expqueue.sleep, expqueue.fail.
  • Added: Setup > Job queue: dashboard, job list, job and group pages with controls; policies expqueue/view and
    expqueue/manage; translations eng-US and ger-DE; the audit branch system.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.