尽管使用锁,Rufus-scheduler 还是调度了两次
Rufus-scheduler scheduling twice despite using locks
我很清楚为什么会发生这种情况(两个 ruby 运行时),对于那些以前没有阅读 RS FAQ 或搜索过 SO 的人来说,这是一个常见问题,但我'我花了几天时间尝试了许多规定的解决方案,但我的 rufus-scheduler 继续调用两次。
这仅发生在生产中,运行 Rails 5.0.6,Puma 服务器,在 Heroku 上。
这是我的 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([=10=]).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
的新实例仍将被调用,而一个仍然是 运行。
我肯定遗漏了一些明显的东西,谢谢你的帮助。
所以,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 进程共享),但这对 [=15 没有帮助=] 和 blocking: true
.
如果您仍然想要 overlap: false
和 blocking: true
,您可以查看 https://devcenter.heroku.com/articles/scheduled-jobs-custom-clock-processes 并使用 rufus-scheduler 或在专用的 process/dyno 中进行调度发条,不需要时间表锁定。
我的其余回答是关于您的代码,而不是关于您正在经历的双重调度。
scheduler.down?
b_scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async unless b_scheduler.down?
end
如果 b_scheduler
关闭,为什么会有这个 unless b_scheduler.down?
块根本不会被执行。
这就足够了:
b_scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async
end
a_scheduler 对比 b_scheduler
您不需要为每项作业配备一个调度程序。你可以简单地写:
require 'rufus-scheduler'
#scheduler = Rufus::Scheduler.new(lockfile: '.rufus-scheduler.lock')
scheduler = Rufus::Scheduler.new
unless defined?(Rails::Console) || File.split([=12=]).last == 'rake' || !Rails.env.production?
scheduler.cron '0 21 * * *', overlap: false, blocking: true do
MySidekiqWorker.perform_async
end
scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async
end
end
我很清楚为什么会发生这种情况(两个 ruby 运行时),对于那些以前没有阅读 RS FAQ 或搜索过 SO 的人来说,这是一个常见问题,但我'我花了几天时间尝试了许多规定的解决方案,但我的 rufus-scheduler 继续调用两次。
这仅发生在生产中,运行 Rails 5.0.6,Puma 服务器,在 Heroku 上。
这是我的 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([=10=]).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
的新实例仍将被调用,而一个仍然是 运行。
我肯定遗漏了一些明显的东西,谢谢你的帮助。
所以,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 进程共享),但这对 [=15 没有帮助=] 和 blocking: true
.
如果您仍然想要 overlap: false
和 blocking: true
,您可以查看 https://devcenter.heroku.com/articles/scheduled-jobs-custom-clock-processes 并使用 rufus-scheduler 或在专用的 process/dyno 中进行调度发条,不需要时间表锁定。
我的其余回答是关于您的代码,而不是关于您正在经历的双重调度。
scheduler.down?
b_scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async unless b_scheduler.down?
end
如果 b_scheduler
关闭,为什么会有这个 unless b_scheduler.down?
块根本不会被执行。
这就足够了:
b_scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async
end
a_scheduler 对比 b_scheduler
您不需要为每项作业配备一个调度程序。你可以简单地写:
require 'rufus-scheduler'
#scheduler = Rufus::Scheduler.new(lockfile: '.rufus-scheduler.lock')
scheduler = Rufus::Scheduler.new
unless defined?(Rails::Console) || File.split([=12=]).last == 'rake' || !Rails.env.production?
scheduler.cron '0 21 * * *', overlap: false, blocking: true do
MySidekiqWorker.perform_async
end
scheduler.every '1h', overlap: false, blocking: true do
MyOtherSidekiqWorker.perform_async
end
end