Rails 6中如何获取并展示指定Sidekiq任务上次成功完成时间
实现方案
Sidekiq 默认不会持久化存储已成功执行的任务记录,官方API本身不提供成功历史查询能力,要获取指定Worker上次成功执行的时间,最稳妥可控的方式是自行持久化执行状态,无需依赖任何第三方插件。
方案1:直接在Worker内埋点(最快实现,适配单Worker场景)
只需要在任务执行成功的节点,把成功时间写入数据库即可,注意要正确利用异常中断逻辑,避免任务报错时误记成功状态:
- 先生成存任务执行状态的表迁移:
rails generate model WorkerExecutionRecord worker_class:string:index last_success_at:datetime rails db:migrate
- 给模型加便捷查询方法,修改
app/models/worker_execution_record.rb:
class WorkerExecutionRecord < ApplicationRecord validates :worker_class, presence: true, uniqueness: true def self.last_success_for(worker_class) find_by(worker_class: worker_class.name)&.last_success_at end end
- 修改现有
FetchAllProductsWorker,在所有业务逻辑执行完成后更新记录:
module Imports class FetchAllProductsWorker include Sidekiq::Worker sidekiq_options queue: 'imports_fetch_all', retry: 0 def perform # 原有产品拉取、数据库同步业务逻辑 # (...) # 所有逻辑无异常执行到末尾时,更新上次成功时间 WorkerExecutionRecord.upsert( { worker_class: self.class.name, last_success_at: Time.current }, unique_by: :worker_class ) end end end
前端需要展示同步状态时,直接调用WorkerExecutionRecord.last_success_for(Imports::FetchAllProductsWorker)即可拿到时间,返回空值说明从来没有成功执行过同步任务。
只要把更新时间的代码放在
perform方法最末尾,就不需要额外加异常捕获:前面的业务逻辑只要抛错,代码就不会走到更新步骤,完全不会出现误报成功的问题。
方案2:用Sidekiq服务端中间件统一埋点(更易维护,适合后续扩展)
如果后续其他Worker也需要记录执行状态,可以写Sidekiq服务端中间件统一处理结果记录,不用在每个Worker里重复写逻辑:
- 新建中间件文件
app/sidekiq/middleware/worker_execution_tracker.rb:
module Sidekiq module Middleware module Server class WorkerExecutionTracker def call(worker, job, queue) yield # 代码走到此处说明任务无异常执行完成 WorkerExecutionRecord.upsert( { worker_class: worker.class.name, last_success_at: Time.current }, unique_by: :worker_class ) end end end end end
- 在Sidekiq初始化文件
config/initializers/sidekiq.rb中注册中间件:
Sidekiq.configure_server do |config| config.server_middleware do |chain| chain.add Sidekiq::Middleware::Server::WorkerExecutionTracker end end
这种方式不需要修改任何Worker的业务代码,所有Worker执行成功后都会自动记录时间,查询方式和方案1完全一致。
注意事项
- 如果
FetchAllProductsWorker可能被并发触发,建议搭配任务去重配置避免重复执行,防止并发写入导致的时间记录不准确 - 可以按需扩展
WorkerExecutionRecord表字段,比如增加last_failed_at、last_error字段,在任务执行抛错时记录失败原因和时间,方便排查同步问题 - 功能首次上线时,如果历史上已经有过成功执行的同步任务,可以手动在Rails控制台补写一条记录,避免前端首次加载时无数据展示
- 不推荐使用第三方Sidekiq统计插件,这类插件大多把历史存在Redis中,既会额外占用内存,查询也不如直接读业务库灵活,对于单Worker状态记录的场景完全没有必要
内容的提问来源于stack exchange,提问作者mr_muscle
相关产品推荐
相关产品推荐

