Skip to content

Changelog

Version v0.15.1

What’s Changed

Bug Fixes

  • Saturated workers no longer busy-loop. A worker whose slots were all busy kept polling getNextJobAvailableInMs as fast as the event loop allowed: with a due job in the backlog the poll reported 0ms, so the wait returned immediately and the worker re-entered the loop without being able to take the work. Saturated in-process workers now wait for a slot to free (or for pollIntervalMs) instead of polling.

Performance

  • Postgres job acquisition now uses the acquisition index. acquireJob and getNextJobAvailableInMs matched jobs with type_name IN (...) ordered by scheduled_at, which Postgres cannot satisfy from the (type_name, scheduled_at) index for more than one job type — it fell back to scanning and sorting the entire pending backlog on every acquisition and every poll. Both queries are now per-job-type LATERAL lookups, turning a backlog scan into one index lookup per job type. Workers polling a large Postgres backlog should see a substantial drop in database load.
  • On Postgres, when several job types are polled together, acquisition now picks a job type at random and takes its oldest due job rather than always taking the globally oldest job. This keeps a backlogged job type from starving the others.
  • Postgres getNextJobAvailableInMs no longer takes row locks on jobs scheduled in the future.

Packages

All packages released at 0.15.1: queuert, @queuert/postgres, @queuert/sqlite, @queuert/redis, @queuert/nats, @queuert/otel, @queuert/dashboard.