繁体   English   中英

如何确保相同的延迟作业不会同时两次(互斥)

[英]How can I make sure that the same delayed job does not twice at the same time (mutually exclusive)

对于一个项目,我想确保某个作业不会同时运行两次。 此作业是一个导入程序,如果它仍在运行,则再次运行是没有意义的。 如果我们检测到作业已经在运行,我想引发异常,以便我收到有关长时间运行的作业的警报。

我找到了解决这个问题的方法。 我们引入了一个新的自定义作业 执行作业时,我们检查是否已经有另一个作业在运行:

# checks if the job is already running when it is supposed to be performed.
# if it is already running, then we raise an error
# jobs with different arguments but same object and method raise an error.
class ExclusiveJob < Struct.new(:object, :meth, :args)
  class ExclusiveJobError < RuntimeError; end

  def initialize(object, meth, *args)
    super(object, meth, args)
  end

  def perform
    same_and_current_jobs = Delayed::Job
      .where(last_error: nil)
      .where.not(locked_at: nil)
      .collect { |job| YAML.load(job.handler) }
      .select { |handler| handler.is_a?(self.class) && handler.object == object && handler.meth == meth }
    
    raise ExclusiveJobError, "Tried to perform \"#{identifier}\", but it is already running" if same_and_current_jobs.count > 1 # we have more than this job in the pipeline

    object.send(meth, *args)
  end

  protected

  # just for display purposes
  def identifier
    "#{object}##{meth}"
  end
end

请注意,这段代码并不理想,因为我们依赖于延迟作业的内部数据模型(但它有官方文档)。 另外,请注意该类不考虑方法参数,即如果找到具有相同接收器和方法的另一个作业,我们将跳过该作业。 而且,我们没有使用 ActiveJob,可能有使用回调解决这个问题的方法。

排入这样一个排他性的工作:

Delayed::Job.enqueue ExclusiveJob.new(MySuperService, :run, 'arg1', :arg2)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM