ruby-on-rails – 如何在ActiveJobs中检查队列?

在排队作业之前,我想检查队列,看看队列中是否已存在具有完全相同参数的作业,并且在这种情况下不会将作业排入队列.但我无法知道我应该如何做到这一点.可能吗?

我知道我可以通过使用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'])
点赞