如何确保同一工作不会同时运行两次?

时间:2017-03-09 20:55:42

标签: ruby-on-rails ruby sidekiq clockwork

我有一个简单的sidekiq工作,我已设置使用发条每5分钟运行一次。我担心的是,如果工作时间超过5分钟,它将再次运行,如果它与原始工作同时运行,可能会导致一些问题。

有没有办法锁定发条,只有在前一次运行完成后才会运行?

4 个答案:

答案 0 :(得分:2)

我使用Sidekiq Unique Jobs gem来完成此任务。它有各种防止重复工作的策略。

答案 1 :(得分:0)

一个选项是在作业启动时创建一个带有进程PID的文件,并在作业结束时将其删除,如果PID文件已经存在,则在开始时中止作业。

虽然我的应用程序的这个特殊部分没有使用sidekiq,但这个想法是一样的。以下是我的应用的执行方式:https://github.com/WikiEducationFoundation/WikiEduDashboard/blob/master/lib/data_cycle/constant_update.rb

答案 2 :(得分:0)

Sidekiq允许您通过API查询队列。

您可以在任务运行时查询sidekiq队列。检查队列和/或作业是否仍然存在。如果是的话,什么都不做。如果不是,请将工作排入队列。

我不知道你的工作是否位于一个单独的队列中,这可能是最好的。这样你就可以查看队列大小,如果是0则启动另一个进程。

Sidekiq API

答案 3 :(得分:0)

Sidekiq Enterprise包括对unique jobs的支持。使用worker类中的选项定义唯一作业:

# app/workers/my_worker.rb
class MyWorker
  include Sidekiq::Worker
  sidekiq_options unique_for: 10.minutes

  def perform(...)
  end
end

必须在Sidekiq初始化程序中启用它们:

# config/initializers/sidekiq.rb
Sidekiq::Enterprise.unique! unless Rails.env.test?

时间窗口仅在作业运行时适用,例如,如果它在10分钟内是唯一的,并且作业在6分钟内完成,那么Sidekiq将立即允许其他作业入队;您不必再等待4分钟就可以删除唯一性锁定。

所有Sidekiq Enterprise节点都强制执行唯一性约束。

您可能需要调整retries选项,因为失败的作业只要处于重试状态就会继续保持锁定状态。 (即使它没有积极执行)

相关问题