在排队作业之前,我想检查队列,看看队列中是否已存在具有完全相同参数的作业,并且在这种情况下不会将作业排入队列.但我无法知道我应该如何做到这一点.可能吗?
我知道我可以通过使用TestHelper在我的测试中轻松完成. TestHelper依赖于TestAdapter,我们当然不会在生产环境中使用它.
多一点背景.在我们的API中,我们检索每个请求中的客户端版本号.我们使用Intercom提供支持,并希望在Intercom中展示应用版本,以便我们可以看到客户在解决支持问题时使用的版本.但是为了限制对内呼叫的呼叫次数,我将每个帖子延迟到内部通信几分钟,当一个帖子入队时,我不想将具有相同数据的新帖子排入队列.
我的问题与List queued tasks with ActiveJob AsyncAdapter有关,但这个问题只涉及入队工作的数量.
Efficiently reschedule ActiveJob (resque/sidekiq)表明这是不可能的,我需要单独实施解决方案.
我可以用ActiveJobs以某种方式检查队列及其中的作业,还是需要跟踪我排队的内容和执行的内容?
最佳答案 以下是未完成的实现.它目前仅支持Sidekiq(我假设您正在使用Sidekiq).
注意:只进行了部分测试,因此您可能需要更新以下内容.如果我有空的话,我会在以后完全检查.
class ActiveJob::Base
def self.where(jid: nil, arguments: [])
found_jobs = []
job_adapter = Rails.application.config.active_job.queue_adapter
case job_adapter
when :sidekiq
queue = Sidekiq::Queue.new(queue_name)
if jid.present?
job = queue.find_job(jid)
if job
# if arguments supplied, check also if args match
if arguments.present?
should_disregard_job_class = self == ActiveJob::Base
job_has_same_class = self.to_s == job.args[0]['job_class']
job_has_same_arguments = arguments == job.args[0]['arguments'][3..-1]
if (should_disregard_job_class || job_has_same_class) && job_has_same_arguments
found_jobs << job
end
else
found_jobs << job
end
end
else
# TODO: optimise below as it is slow
queue.each do |job|
should_disregard_job_class = self == ActiveJob::Base
job_has_same_class = self.to_s == job.args[0]['job_class']
job_has_same_arguments = arguments == job.args[0]['arguments'][3..-1]
if (should_disregard_job_class || job_has_same_class) && job_has_same_arguments
found_jobs << job
end
end
end
when :resque
# TODO
else
raise "TODO: missing Adapter implementation for #{job_adapter}"
end
found_jobs
end
end
用法
jobs = ActiveJob::Base.where(jid: '12345678abcdef')
jobs = MyCustomJob.where(jid: '12345678abcdef')
jobs = MyCustomJob.where(arguments: ['firstjobargumentvalue', 'secondjobargumentvalue'])