在排队作业之前,我想检查队列,看看队列中是否已存在具有完全相同参数的作业,并且在这种情况下不会将作业排入队列。但我无法知道我应该如何做到这一点。可能吗?
我知道我可以在使用TestHelper的测试中轻松完成。 TestHelper依赖于TestAdapter,我们当然不会在生产环境中使用它。
多一点背景。在我们的API中,我们检索每个请求中的客户端版本号。我们使用Intercom提供支持,并希望在Intercom中展示应用版本,以便我们可以看到客户在解决支持问题时使用的版本。但是为了限制对内呼叫的呼叫次数,我将每个帖子延迟到内部通信几分钟,当一个帖子入队时,我不想将具有相同数据的新帖子排入队列。
我的问题与List queued tasks with ActiveJob AsyncAdapter有关,但该问题仅涉及入队作业的数量。
Efficiently reschedule ActiveJob (resque/sidekiq)表示这是不可能的,我需要单独实施解决方案。
我可以用ActiveJobs以某种方式检查队列及其中的作业,还是需要跟踪排队的内容和已执行的内容?
答案 0 :(得分:2)
以下是未完成的实施。它目前仅支持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'])