如何使用Sidekiq限制任务仅在48小时内重试,超时取消?
实现Sidekiq任务48小时内重试、超时自动取消
Sidekiq没有直接提供按时间窗口限制重试的配置,不过可以通过自定义重试逻辑实现需求:
核心实现方案
在Worker类中通过sidekiq_retry_in方法控制重试时机,同时判断任务是否已超过48小时阈值,一旦超时就终止重试。
代码示例
class MyWorker include Sidekiq::Worker # 设置足够多的重试次数(覆盖48小时内的指数退避重试需求,20次足够) sidekiq_options retry: 20 def perform(args) # 你的任务执行逻辑 end def sidekiq_retry_in(exponent) # 获取任务创建时间戳,Sidekiq自动存入job字段 created_at = job["created_at"] || Time.now.to_f elapsed_time = Time.now.to_f - created_at max_allowed_time = 48 * 3600 # 48小时转换为秒 if elapsed_time >= max_allowed_time # 超过时间阈值,返回false终止重试 false else # 沿用Sidekiq默认指数退避间隔,也可自定义固定间隔 (exponent ** 4) + rand(1..30) end end end
关键说明
job["created_at"]是Sidekiq为每个任务自动记录的创建时间(时间戳格式),用于计算任务已耗时。- 将
retry设为较大数值,是为了避免在48小时内提前耗尽重试次数,确保时间判断逻辑优先生效。 - 若需要固定重试间隔,直接修改
sidekiq_retry_in的返回值即可,比如固定1小时重试一次:3600。
兜底方案:结合重试耗尽回调
如果担心重试次数设置不足导致提前终止,可添加兜底回调,在重试次数耗尽时二次检查时间阈值:
class MyWorker include Sidekiq::Worker sidekiq_options retry: 20 def perform(args) # 任务执行逻辑 end def sidekiq_retry_in(exponent) created_at = job["created_at"] || Time.now.to_f elapsed_time = Time.now.to_f - created_at max_allowed_time = 48 * 3600 elapsed_time >= max_allowed_time ? false : (exponent **4) + rand(1..30) end sidekiq_retries_exhausted do |job, error| created_at = job["created_at"] || Time.now.to_f elapsed_time = Time.now.to_f - created_at max_allowed_time = 48 * 3600 if elapsed_time < max_allowed_time # 特殊情况:重试次数耗尽但未超时,可手动重新入队(可选) MyWorker.perform_async(job["args"]) else # 超时且重试耗尽,记录日志或执行清理逻辑 Rails.logger.info("任务#{job["jid"]}超时48小时,终止重试") end end end
内容的提问来源于stack exchange,提问作者Piyush Singhania
相关产品推荐
相关产品推荐

