簡體   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