如何在Ruby on Rails 7.0中当表dateto等于当前日期时执行Worker?
实现当draws表dateto等于当前日期时自动触发Worker
1. 创建处理抽奖逻辑的Worker
先生成一个负责执行抽奖核心逻辑的Worker:
# app/workers/draw_processing_worker.rb class DrawProcessingWorker include Sidekiq::Worker def perform(draw_id) draw = Draw.find(draw_id) return if draw.has_winners? # 避免重复执行已处理的抽奖 # 在这里编写你的抽奖逻辑,比如: # 抽取获奖者ID、更新draw的first_winner/second_winner字段、标记has_winners为true # draw.update!(first_winner: selected_user_id, second_winner: another_user_id, has_winners: true) end end
2. 创建定时检查的调度Worker
这个Worker负责定时扫描到期且未处理的抽奖记录,触发上面的处理Worker:
# app/workers/draw_scheduler_worker.rb class DrawSchedulerWorker include Sidekiq::Worker def perform # 查询dateto日期等于今天、且未生成获奖者的抽奖记录 Draw.where( "DATE(dateto) = DATE(?)", Date.today ).where(has_winners: false).each do |draw| DrawProcessingWorker.perform_async(draw.id) end end end
3. 配置Sidekiq Schedule定时任务
在config/sidekiq_schedule.yml中添加定时规则,设置任务执行频率:
draw_scheduler: cron: "0 0 * * *" # 每天凌晨0点执行一次 class: "DrawSchedulerWorker" queue: default
如果需要更频繁的检查(比如每分钟扫描一次),可以把cron改为:
draw_scheduler: cron: "* * * * *" # 每分钟执行一次 class: "DrawSchedulerWorker" queue: default
4. 让Sidekiq加载定时任务配置
在config/initializers/sidekiq.rb中添加配置,确保Sidekiq启动时加载定时任务:
Sidekiq.configure_server do |config| config.on(:startup) do Sidekiq.schedule = YAML.load_file(File.expand_path("../sidekiq_schedule.yml", __dir__)) Sidekiq::Scheduler.reload_schedule! end end
5. 关键注意事项
- 重复执行防护:利用
has_winners字段判断抽奖是否已处理,避免同一记录被多次触发 - 时间精度调整:如果需要精确到时分秒的触发,可将查询条件改为
dateto <= Time.current,同时搭配更高频率的cron规则 - 异常处理:可在Worker中添加
rescue块捕获异常,防止单个抽奖处理失败导致整个调度任务中断 - 时区一致性:确保Rails应用时区与Sidekiq运行时区一致,避免时间判断偏差
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

