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