我很清楚为什么会发生这种情况(两个ruby运行时),对于那些以前没有阅读过RS FAQ或在SO上进行过搜索的人来说,这是一个常见问题,但是我花了几天的时间尝试许多规定的解决方案,但我的rufus-scheduler继续调用两次。
这仅发生在在Heroku上运行Rails 5.0.6,Puma服务器的生产环境中。
这是我的scheduler.rb:
require 'rufus-scheduler'
a_scheduler = Rufus::Scheduler.new(:lockfile => ".rufus-scheduler-a.lock")
b_scheduler = Rufus::Scheduler.new(:lockfile => ".rufus-scheduler-b.lock")
unless defined?(Rails::Console) || File.split($0).last == 'rake' || !Rails.env.production?
a_scheduler.cron '0 21 * * *', overlap: false, blocking: true do
MySidekiqWorker.perform_async unless a_scheduler.down?
end
b_scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async unless b_scheduler.down?
end
end
我尝试了锁定文件,配置了自己的scheduler_lock,为.every
和.cron
使用了不同的参数。而且,即使我有overlap: false
和blocking: true
,似乎MyOtherSidekiqWorker
的新实例仍会在运行时被调用。
我肯定想念一些明显的东西,谢谢您的帮助。
答案 0 :(得分:1)
所以Heroku dynos not sharing the file system
在dyno d0上看到的.rufus-scheduler-a.lock
不是在dyno d1上看到的.rufus-scheduler-a.lock
。
您的Heroku dynos不共享相同的文件系统,并且它们也不共享相同的Ruby进程,因此也不是相同的rufus-scheduler实例。因此overlap: false
,blocking: true
从dyno d0到dyno d1不会有任何影响。
您可以为rufus-scheduler实现自定义锁定机制,以从https://github.com/jmettraux/rufus-scheduler#advanced-lock-schemes中汲取灵感(可能是通过数据库,因为它已由Ruby进程共享),但这对overlap: false
和{{1 }}。
如果您仍然希望拥有blocking: true
和overlap: false
,则可以查看https://devcenter.heroku.com/articles/scheduled-jobs-custom-clock-processes并使用rufus-scheduler或Clockwork在专用的进程/ dyno中进行调度,而没有需要计划锁定。
我剩下的答案是关于您的代码的,而不是关于您正在经历的双重计划。
scheduler.down?
blocking: true
如果b_scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async unless b_scheduler.down?
end
降下,为什么会有这个unless b_scheduler.down?
呢?根本不会执行该块。
这就足够了:
b_scheduler
a_scheduler与b_scheduler
您不需要为每个作业使用一个调度程序。您可以简单地写:
b_scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async
end