在sidekiq或activejob执行方法中使用超时

时间:2015-08-06 15:01:18

标签: ruby concurrency sidekiq rails-activejob

我打算使用发条宝石从Heroku Scheduler转移到自定义时钟进程。如果在下一个相同类型的计划之前没有完成,Heroku Scheduler将终止任务。 我如何在Sidekiq实现这一目标?

鉴于Timeout不是线程安全的。在Sidekiq工作人员这样做是不是一个坏主意?

class RunsTooLongWorker
  include Sidekiq::Worker

  sidekiq_options :retry => false

  def perform(*args)
    Timeout::timeout(2.hours) do
      # do possibly long running task
    end
  end
end

如果没有替代方案?假设我想每10分钟运行一次工作,但我不希望同时运行相同的工作。我该如何处理?

2 个答案:

答案 0 :(得分:0)

回答你问题的这一部分:

  

鉴于Timeout不是线程安全的。在Sidekiq工作人员这样做是不是一个坏主意?

这是Mike Perham写的一篇很棒的博客文章 why you shouldn't use Ruby's timeout module in sidekiq jobs

至于替代方案......听起来你最需要的是确保你的工作不会相互绊倒。为此,我可以想到两种方法:

  • 穷人的做法:创造一个排队的'属于您正在处理的对象模型的属性。当您开始处理您正在进行的任何处理时,请将该项目标记为已排队,并在完成后将其标记为“未排队”#39;。为那些没有入队的人提供每十分钟的工作范围。或者,使用您的作业名称及其状态字段创建一个新表格,并在重新执行处理之前查询其可用性。

  • 如果你有更复杂的事情,这听起来像是Sidekiq Unique Jobs gem.的一个很好的例子。我认为在执行时会有'方法就是你想要的方法。

答案 1 :(得分:-3)

我想您的任务的解决方案是使用whenever gem,因为它是在Sidekiq wiki建议的,这是安装后whenever的{​​{3}}将创建config/schedule.rb文件,您可以在其中定义作业的计划,例如

every 3.hours do
  runner "MyModel.some_process"
  rake "my:rake:task"
  command "/usr/bin/my_great_command"
end

它有三种内置类型,您可以从代码段runner, rake and command看到,但您也可以定义自己的内容,并在wiki中进行了解释。