New Features:
- Added concurrency rate limits via
queue.enqueue(func, rate_limit=RateLimit(...)). Thanks @selwin! - You can now configure
RQ_KEY_PREFIXvia environment variable, making it possible to run RQ on Redis Cluster. Thanks @dmonroy and @paltman! - Workers can now track multiple executions, exposed via
worker.get_current_executions()andworker.current_execution_count. Thanks @selwin! - Added
send_stop_execution_command()to stop a single execution of a job. Thanks @selwin! Executionnow stores its job ID. Thanks @selwin!SpawnWorkernow works with Unix sockets. Thanks @zhechen-cs!- RQ will now retry connecting to Redis on
TimeoutError. Thanks @gotoUSA! - Officially support Python 3.15. Thanks @selwin!
rq worker-poolnow supports--queue-classargument. Thanks @LindseyZ1205!Workernow uses the more efficientclient_info()instead ofclient_list()when available. Thanks @kylejn27!Group.clean_registries()is now much more efficient. Thanks @kylejn27!
Breaking Changes:
SpawnWorkernow usesos.posix_spawn()and requires POSIX. Thanks @selwin!- RQ now requires
redis-py>= 5.0.1. Thanks @selwin! CronSchedulernow evaluates cron strings in local timezone instead of UTC (like system cron). Thanks @selwin!- Dependent jobs now pass through a new
READY_TO_ENQUEUEstatus andReadyJobRegistrybefore being enqueued. Thanks @selwin! - RQ now disables propagation on loggers it configures itself to prevent double logging when applications configure logging afterwards. Thanks @selwin!
Queue.enqueue_dependents()no longer acceptspipeline. Thanks @selwin!job.cancel(enqueue_dependents=True, pipeline=pipeline)requires a watched pipeline and no longer enqueues dependents. Thanks @selwin!rate_limitis now a reserved keyword argument ofqueue.enqueue(). Thanks @selwin!Worker.perform_job(),handle_job_success(),monitor_work_horse()andmaintain_heartbeats()now require anexecutionargument. Thanks @selwin!- Removed
worker.set_current_job_id(),worker.current_job_working_timeandworker.set_current_job_working_time(). Thanks @selwin! - Workers no longer store
current_jobin their Redis hash. Thanks @selwin! worker.get_current_job_id()no longer accepts apipelineargument. Thanks @selwin!Job.execute_success_callback(),execute_failure_callback()andexecute_stopped_callback()are replaced by functions of the same name inrq.callbacks. Thanks @selwin!- Failure callbacks and exception handlers invoked for abandoned jobs now receive
Noneas the traceback. Thanks @selwin! Job.perform()no longer removes the job key's TTL. Job key TTL changes are now handled by workers. Thanks @selwin!get_current_job()now usescontextvarsinstead of thread-locals; gevent-based custom workers needgreenlet>= 0.4.17. Thanks @selwin!
Bug Fixes:
Queue.get_job_ids()andQueue.get_jobs()now return an empty slice whenlength=0. Thanks @JackyHsu-X!Job.delete()andQueue.empty()now also remove the deleted jobs' stored execution results. Thanks @MokiMeow!enqueue_at()andenqueue_in()now honorunique=True. Thanks @jamalkamaladdin!- Job repeats are now scheduled against UTC instead of the local wall clock. Thanks @dylanpulver!
StartedJobRegistry.cleanup()no longer marks finished jobs as abandoned. Thanks @gyanu2507!StartedJobRegistry.cleanup()now sendsfailedwebhooks for abandoned jobs and no longer aborts when a failure callback raises. Thanks @selwin!- Event loops are now closed after coroutine jobs finish. Thanks @Kuang-xianxin!
- You can now pass in
Iterabletoqueue.enqueue_many(). Thanks @liuyinchu! - Fixed a bug where
enqueue_at_frontis not respected when job returnsRetryresult. Thanks @ericdelorefice! at_frontshould be respected when enqueueing jobs with met dependencies duringenqueue_many(). Thanks @ericdelorefice!rq enqueuenow properly handles--job-classargument. Thanks @LuisFigueroaG!rq enqueueCLI command now properly handles--at-frontwhen used in conjunction with--schedule-in. Thanks @ericdelorefice!- Fixed a bug where job result is not passed to success callbacks when jobs are synchronously with
result_ttl=0. Thanks @nk-batman21! - Fixed
at_frontandresult_ttlargument parsing when enqueueing a decorated function. Thanks @jipeng6036-del and @zhechen-cs! - Fixed a bug in repeat interval calculation when number of intervals is less than number of repeats. Thanks @zhechen-cs!
- Fixed a bug where
ttlis not expected when enqueueing a deferred job usingenqueue_many(). Thanks @LindseyZ1205! - Fixed DST handling when a naive datetime is passed into
enqueue_at(). Thanks @ericdelorefice! enqueue_at()now respects pipeline argument. Thanks @LindseyZ1205!- Enqueuing a job with a
Dependency(allow_failure=True)with an already failed dependency now works as expected. Thanks @LindseyZ1205! worker.maintain_heartbeats()will no longer recreate a worker hash without TTL. Thanks @diegopasqualin-beyond!queue.get_job_ids(length=0)now returns an empty list instead of all job IDs. Thanks @JackyHsu-X!- Fixed CronJob
kwargsparsing. Thanks @LindseyZ1205! - Fixed a bug where workers may lose jobs while waiting for schedulers to stop. Thanks @laulauraluo!
SpawnWorkernow works properly over SSL and Unix sockets. Thanks @LindseyZ1205 and @zhechen-cs!