Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在工作中间重新启动SIDKIQ之前是否有运行代码的方法?_Ruby On Rails_Ruby_Sidekiq - Fatal编程技术网

Ruby on rails 在工作中间重新启动SIDKIQ之前是否有运行代码的方法?

Ruby on rails 在工作中间重新启动SIDKIQ之前是否有运行代码的方法?,ruby-on-rails,ruby,sidekiq,Ruby On Rails,Ruby,Sidekiq,我有一个每4分钟运行一次的Sidekiq作业 此作业在再次执行代码之前检查当前代码块是否正在执行 process = ProcessTime.where("name = 'ad_queue_process'").first # Return if job is running return if process.is_running == true 如果Sidekiq在代码块的中途重新启动,则更新作业状态的代码永远不会运行 # Done running, update the process

我有一个每4分钟运行一次的Sidekiq作业

此作业在再次执行代码之前检查当前代码块是否正在执行

process = ProcessTime.where("name = 'ad_queue_process'").first

# Return if job is running
return if process.is_running == true
如果Sidekiq在代码块的中途重新启动,则更新作业状态的代码永远不会运行

# Done running, update the process times and allow it to be ran again
process.update_attributes(is_running: false, last_execution_time: Time.now)
这导致作业永远不会运行,除非我运行update语句来设置
is\u 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,在我们的讨论(下面的评论)之后,
    sure
    块(由分叉的工作线程执行)只能在主线程强制终止这些工作线程之前运行几毫秒,以便主线程对异常堆栈进行一些“清理”,为了避免被希罗库杀死。因此,请确保您的
    确保
    代码应该非常快
    
TL;医生:

def perform(*args)
  # your code here
ensure
  process.update_attributes(is_running: false, last_execution_time: Time.now)
end
  • 无论方法是“成功”还是引发异常,都始终调用上面的
    确保
    。我测试了这个:看到这个,点击“运行”

  • 换句话说,即使信号是
    SIGTERM
    (正常关机信号),也总是在
    SignalException
    上调用此函数,但仅在
    SIGKILL
    上调用(强制不可提示关机)。您可以通过检查my来验证此行为,然后将
    Process.kill('TERM',Process.pid)
    更改为
    Process.kill('kill',Process.pid)
    ,然后再次单击“run”(您会注意到不会调用
    put

  • 看一看,我引述:

    当Heroku要关闭dyno(重新启动或新部署等)时,它首先向dyno中的进程发送SIGTERM信号

    Heroku向您的应用程序发送SIGTERM后,它将等待几秒钟,然后发送SIGKILL以强制其关闭,即使它尚未完成清理。在本例中,确保块根本没有被调用,程序只是退出

    。。。这意味着
    sure
    块将被调用,因为它是
    SIGTERM
    而不是
    SIGKILL
    ,除非关闭需要很长时间,这可能是由于(我认为是ATM的某些原因):

    • 您的
      执行
      代码(或堆栈中的任何ruby代码;甚至gems)中的某些操作,这些操作也拯救了
      SignalException
      ,甚至拯救了根
      Exception
      类,因为
      SignalException
      Exception
      的子类,但需要很长时间才能清理(即清理连接到DB或其他东西的
      连接,或挂起应用程序的i/O内容)

    • 或者,您自己的
      确保上面的
      块花费很长时间。例如,在执行
      过程时。更新\u属性(…)
      ,由于某种原因,DB临时挂起/网络延迟或超时,那么,
      更新
      可能根本不会成功!并且将耗尽时间,从我上面的引文中可以看出,在
      SIGTERM
      之后几秒钟,Heroku发送一个
      SIGKILL
      ,应用程序将被迫停止


…这一切都意味着我的解决方案仍然不完全可靠,但在正常情况下应该可以工作

您如何重新启动Sidekiq?它通常“优雅地”停止/重新启动这意味着它将在重新启动/停止之前完成所有运行的任务:但是如果您在开发中使用CTRL+C,是的,它将立即关闭,但这是在开发中。如果您想确保“更新”只在没有错误的情况下在DB中提交(也就是说,只有当Sidekiq在任务中间没有CTRL+C-ED在DEV Env中)时才可以完成。,然后您可以将整个作业包装在一个
ProcessTime.transaction do…end
blockside注意:这在任何情况下都是错误的方法,容易受到竞争条件的影响。一个应在作业完成后使用消息队列确认消息。另一个(低级别)选项是一个
Mutex
/
ConditionalVariable
。所有其他解决方案迟早会导致竞争条件和同时执行两个作业。@RickS哦,我知道了,你在Heroku中使用了Sidekiq。以前没有在那里使用过,但我发现了它中途关闭的原因(可能您的作业运行时间超过30秒?)。从中,它说,
“请记住,Heroku对进程重启设置了30秒的硬限制,-t25告诉Sidekiq在开始“强制关机”过程之前,给作业25秒的时间来完成”
@RickS看着,似乎Heroku向进程发送了一个“SIGTERM”(这可能也适用于sidekiq过程),因为它是一个“SIGTERM”而不是“SIGKILL”(不可提示的强制关机),那么我猜您仍然可以围绕
perform
方法(p.s.未测试)来拯救它,但您可以尝试:
def perform;#这里的代码…;rescue SignalException=>e;sure;process.update(…);end
@RickS尽管如此,请进一步阅读Heroku页面:
在Heroku向您的应用程序发送SIGTERM后,它将等待几秒钟,然后发送SIGKILL以强制关闭,即使它尚未完成清理。在本例中,确保块根本没有被调用,程序只会退出:
。因此,如果您的作业“挂起”/需要很长时间才能关闭,然后我的“rescue;SECURE”解决方案仍然不完全可靠,但希望不会花太长时间,因为您只是在
SECURE
块中执行
更新
;仍然不是100%可靠,即更新时的临时DB超时,根据该指南所述“回滚db事务时需要这样做,否则Ruby的线程#kill将提交……不要在工作中挽救此错误