[英]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.