有没有办法在 Sidekiq 在工作中重新启动之前编写 运行 代码?
Is there way to run code before Sidekiq is restarted in the middle of a job?
我有一个 Sidekiq 作业,每 4 分钟 运行s。
此作业在再次执行代码之前检查当前代码块是否正在执行
process = ProcessTime.where("name = 'ad_queue_process'").first
# Return if job is running
return if process.is_running == true
如果 Sidekiq 在代码块中途重启,更新作业状态的代码永远不会 运行s
# Done running, update the process times and allow it to be ran again
process.update_attributes(is_running: false, last_execution_time: Time.now)
这导致作业永远不会 运行ning 除非我 运行 更新语句设置 is_running = false
有什么方法可以在 Sidekiq 重启之前执行代码吗?
处理sidekiq关闭异常
class SomeWorker
include Sidekiq::Worker
sidekiq_options queue: :default
def perform(params)
...
rescue Sidekiq::Shutdown
SomeWorker.perform_async(params)
end
end
更新:
- 感谢@Aaron,在我们的讨论(下面的评论)之后,
ensure
块(由分叉的工作线程执行)只能 运行 一些 ungua运行teed 毫秒前主线程强行终止这些工作线程,以便主线程做一些“清理”异常堆栈,以避免被 Heroku 发出 SIGKILL。因此,请确保您的 ensure
代码应该非常快!
TL;DR:
def perform(*args)
# your code here
ensure
process.update_attributes(is_running: false, last_execution_time: Time.now)
end
上面的 ensure
总是被调用,不管方法是“成功”还是抛出异常。我对此进行了测试:查看此 repl code,然后单击“运行”
换句话说,即使信号是 SIGTERM
(正常关闭信号),也总是在 SignalException
上调用,但是 ONLY SIGKILL
上的 EXCEPT(强制无法挽救的关机)。您可以通过检查我的 repl code 来验证此行为,然后将 Process.kill('TERM', Process.pid)
更改为 Process.kill('KILL', Process.pid)
,然后再次单击“运行”(您会注意到 puts
不会被调用)
看着Heroku docs,我引用:
When Heroku is going to shut down a dyno (for a restart or a new deploy, etc.), it first sends a SIGTERM signal to the processes in the dyno.
After Heroku sends SIGTERM to your application, it will wait a few seconds and then send SIGKILL to force it to shut down, even if it has not finished cleaning up. In this example, the ensure block does not get called at all, the program simply exits
... 这意味着 ensure
块将被调用,因为它是 SIGTERM
而不是 SIGKILL
,除非关闭需要很长时间,这可能是由于(我能想到 ATM 的某些原因):
您的 perform
代码(或堆栈中的任何 ruby 代码;甚至是 gems)中的某些东西也拯救了 SignalException
,甚至拯救了根Exception
class 因为 SignalException
是 Exception
的子 class)但需要很长时间清理(即清理 connections
到 DB 或一些东西,或者 I/O 挂起你的应用程序的东西)
或者,您自己上面的 ensure
块需要很长时间。 I.E 在执行 process.update_attributes(...)
时,由于某种原因数据库临时挂起/网络延迟或超时,那么 update
可能根本不会成功!并且 运行 会超时,其中从我上面的引用中,在 SIGTERM
几秒钟后,应用程序将被 Heroku 发送 SIGKILL
.[= 强制停止38=]
...这都意味着我的解决方案仍然不完全可靠,但在正常情况下应该可以工作
我有一个 Sidekiq 作业,每 4 分钟 运行s。
此作业在再次执行代码之前检查当前代码块是否正在执行
process = ProcessTime.where("name = 'ad_queue_process'").first
# Return if job is running
return if process.is_running == true
如果 Sidekiq 在代码块中途重启,更新作业状态的代码永远不会 运行s
# Done running, update the process times and allow it to be ran again
process.update_attributes(is_running: false, last_execution_time: Time.now)
这导致作业永远不会 运行ning 除非我 运行 更新语句设置 is_running = false
有什么方法可以在 Sidekiq 重启之前执行代码吗?
处理sidekiq关闭异常
class SomeWorker
include Sidekiq::Worker
sidekiq_options queue: :default
def perform(params)
...
rescue Sidekiq::Shutdown
SomeWorker.perform_async(params)
end
end
更新:
- 感谢@Aaron,在我们的讨论(下面的评论)之后,
ensure
块(由分叉的工作线程执行)只能 运行 一些 ungua运行teed 毫秒前主线程强行终止这些工作线程,以便主线程做一些“清理”异常堆栈,以避免被 Heroku 发出 SIGKILL。因此,请确保您的ensure
代码应该非常快!
TL;DR:
def perform(*args)
# your code here
ensure
process.update_attributes(is_running: false, last_execution_time: Time.now)
end
上面的
ensure
总是被调用,不管方法是“成功”还是抛出异常。我对此进行了测试:查看此 repl code,然后单击“运行”换句话说,即使信号是
SIGTERM
(正常关闭信号),也总是在SignalException
上调用,但是 ONLYSIGKILL
上的 EXCEPT(强制无法挽救的关机)。您可以通过检查我的 repl code 来验证此行为,然后将Process.kill('TERM', Process.pid)
更改为Process.kill('KILL', Process.pid)
,然后再次单击“运行”(您会注意到puts
不会被调用)看着Heroku docs,我引用:
When Heroku is going to shut down a dyno (for a restart or a new deploy, etc.), it first sends a SIGTERM signal to the processes in the dyno.
After Heroku sends SIGTERM to your application, it will wait a few seconds and then send SIGKILL to force it to shut down, even if it has not finished cleaning up. In this example, the ensure block does not get called at all, the program simply exits
... 这意味着
ensure
块将被调用,因为它是SIGTERM
而不是SIGKILL
,除非关闭需要很长时间,这可能是由于(我能想到 ATM 的某些原因):您的
perform
代码(或堆栈中的任何 ruby 代码;甚至是 gems)中的某些东西也拯救了SignalException
,甚至拯救了根Exception
class 因为SignalException
是Exception
的子 class)但需要很长时间清理(即清理connections
到 DB 或一些东西,或者 I/O 挂起你的应用程序的东西)或者,您自己上面的
ensure
块需要很长时间。 I.E 在执行process.update_attributes(...)
时,由于某种原因数据库临时挂起/网络延迟或超时,那么update
可能根本不会成功!并且 运行 会超时,其中从我上面的引用中,在SIGTERM
几秒钟后,应用程序将被 Heroku 发送SIGKILL
.[= 强制停止38=]
...这都意味着我的解决方案仍然不完全可靠,但在正常情况下应该可以工作