Changelog¶
(unreleased)¶
Ci: bump checkout/setup-python to v6 (Node 24) [tobymao]
Clears the Node.js 20 deprecation warning; v2 actions run on Node 20 which GitHub forces to Node 24 starting June 2026.
Harden test_start timing against CI load. [tobymao]
Wait for terminal status via refresh(0) for the error job (FAILED), and use a longer-running sleeper plus more generous sleeps for the active/re-queue checks so they don’t race the worker under CI load.
Flaky test_start by waiting for in-flight job re-queue. [tobymao]
The in-flight job is re-queued in the worker’s CancelledError handler, which stop() only awaits up to cancellation_hard_deadline_s. For the HTTP proxy that re-queue crosses the network, so the new QUEUED status can land just after the worker task returns, causing test_start to read ACTIVE under CI load. Sleep briefly before refreshing.
v0.26.4 (2026-05-21)¶
V0.26.4. [tobymao]
KeyError on concurrent same-key job attempts in job_task_contexts. [Timothy Redaelli]
Job.hash is derived from .key, so two in-flight attempts of the same-key job (e.g. a sweep-driven retry of a job whose previous attempt is still winding down) share one slot in Worker.job_task_contexts. Whichever attempt’s finally pops the slot first leaves the other to raise KeyError at the completion check:
File ".../saq/worker.py", line 374, in process if self.job_task_contexts[job]["aborted"] is None: KeyError: Job<... key: chat:1, attempts: 2, error: cancelled, status: active>Keep the dict keyed by Job (i.e. by .key), but hold a local reference to the JobTaskContext inside process() and read “aborted” through it. In the finally, only remove the slot if it still holds our ctx – a successor attempt’s slot is preserved. abort() is unchanged.
Adds a regression test that reproduces the race by running two process() coroutines with same-key jobs and asserting both complete.
Allow redis-py 7.x (bump cap from <7.0 to <8.0) [taaacse4]
redis-py 7.0.0 breaking changes (type annotations, RLock, removed parse_list_to_dict) do not affect SAQ’s usage of the redis library. SAQ uses redis.asyncio, pipelines, basic commands, and pub/sub — all unchanged in 7.x.
Same analysis as the prior bump from <6.0 to <7.0 (cc8bef9).
Closes #291
v0.26.3 (2026-03-04)¶
V0.26.3. [tobymao]
Pandas serde closes #287. [tobymao]
v0.26.2 (2026-03-04)¶
V0.26.2. [tobymao]
Again. [tobymao]
Fix again. [tobymao]
3.9. [tobymao]
Support newer psycopg. [tobymao]
v0.26.1 (2026-01-08)¶
V0.26.1. [tobymao]
Remove signal handlers after stop. [Vikash]
Allow
redispackage version up to 6.x. [Malthe Jørgensen]Breaking changes and deprecations in 6.0.0 don’t affect how SAQ uses the
redislibrary, so we can allow its use. Similarly the later availableredis6.x versions: 6.1.0, 6.1.1, 6.2.0, 6.3.0, 6.4.0 adhere to semantic versioning (double checked, because packages don’t always follow semantic versioning) and don’t have breaking changes nor deprecations.redis6.x supports Python 3.9+ similarly to SAQ. Python 3.8 support was dropped in 6.2.0.Reference:
https://github.com/redis/redis-py/releases/tag/v6.0.0
https://github.com/redis/redis-py/tags
Style fix. [Simone Caldana]
Record worker_id in job metadata once a job is picked up. [Simone Caldana]
Try again. [tobymao]
Fix tests. [tobymao]
v0.26.0 (2025-10-14)¶
V0.26.0. [tobymao]
Global timeout for map function closes #270. [tobymao]
Chore: Avoid high cardinality job id in logger message. [ditsuke]
Do wait to cancel task in case of timeout. [ditsuke]
Avoid race in setting task status b/w process and abort. [ditsuke]
Tests: Small wait to let process() end. [ditsuke]
Chore:
Nonefor cancellation timeout (noop) [ditsuke]Tests: Assert that .abort blocks until the task stops. [ditsuke]
Chore: Log on failure to cancel in time. [ditsuke]
Chore: Remove job-level completion allowance. [ditsuke]
Feat: Graceful shutdown and cancellation controls. [ditsuke]
Fix(tests): Bump wait for task to get picked. [ditsuke]
Test: Add testcase for shutdown hook order. [ditsuke]
Refactor: Remove AsyncExitStack. [ditsuke]
Avoid race in stop() [ditsuke]
Allow tasks to stop before cleanup. [ditsuke]
Py39 type compat. [ditsuke]
Type qualifiers. [ditsuke]
Chore: Remove redundant type alias. [ditsuke]
Chore: Improve worker context typing. [ditsuke]
Style: add generic for context. [euri10]
Docs: Complete and expand documentation for Tasks section. [Rakesh Bhatia]
Refactor: extract runner from main function. [Ivan Koldakov]
Move the main execution logic into a separate run() function in saq.runner. It allows running the application programmatically without modifying sys.argv.
Set default port value. [Ivan Koldakov]
Avoid passing None to start() as it violates the signature.
Remove all signal handlers for windows as they don’t work. [tobymao]
v0.25.2 (2025-07-10)¶
V0.25.2. [tobymao]
Feat: add optional polling to postgres. [tobymao]
Drop 3.8/add 3.13. [eakmanrq]
Chore: type ignore aiosignal 1.4.0. [eakmanrq]
v0.25.1 (2025-07-03)¶
V0.25.1. [tobymao]
Feat: add retry to http calls. [eakmanrq]
v0.25.0 (2025-07-01)¶
V0.25.0. [tobymao]
Add test. [tobymao]
Refactor!: remove pg locks for stability. [tobymao]
v0.24.13 (2025-06-30)¶
V0.24.13. [tobymao]
Handle case where connection pool closes connection. [eakmanrq]
v0.24.12 (2025-06-24)¶
V0.24.12. [tobymao]
Ensure there’s no race condition in between dequeue and processing for sweeper. [tobymao]
v0.24.11 (2025-06-23)¶
V0.24.11. [tobymao]
Formatting. [Haukur Páll]
Add poll_interval test. [Haukur Páll]
Add poll_interval example to readme. [Haukur Páll]
Formatting. [Haukur Páll]
Making the poll_interval docstring consistent betwen methods. [Haukur Páll]
Add poll_interval to apply, edit docstring. [Haukur Páll]
v0.24.10 (2025-06-20)¶
V0.24.10. [tobymao]
Ensure db status is source of truth for pg jobs. [tobymao]
v0.24.9 (2025-06-10)¶
V0.24.9. [Iaroslav Zeigerman]
Acquiring an advisory lock for a job as part of a predicate. [Iaroslav Zeigerman]
v0.24.8 (2025-05-29)¶
V0.24.8. [tobymao]
Ensure retried jobs are unlocked. [tobymao]
V0.24.7. [tobymao]
Ensure that we filter locked objects before limits so that we actually return jobs. [tobymao]
v0.24.6 (2025-05-16)¶
V0.24.6. [tobymao]