14

知道如何Delayed::Job从 ActiveJob 排队中获取 id 吗?当我将作业排入队列时,我会返回一个ActiveJob::Base带有 a的实例@job_id,但该作业 ID 似乎是 ActiveJob 的内部。到目前为止,我最好的猜测是查看最近创建的工作:

active_job_id = GenerateReportJob.perform_later(self.id).job_id
delayed_job = Delayed::Job.order(id: :desc).limit(5).detect do |job|
  YAML.load(job.handler).job_data['job_id'] == active_job_id
end

但这似乎是各种hacky。有点惊讶 ActiveJob 没有从 中返回 ID Delayed::Job,尤其是因为这是在作业入队时显式返回的内容。

== 编辑

看起来我不是唯一一个(https://github.com/rails/rails/issues/18821

4

4 回答 4

12

万一将来有人发现:Rails 刚刚接受了一个补丁,允许您从 Rails 5 中的 provider_job_id 获取此 id。您可以使用类似补丁

ActiveJob::QueueAdapters::DelayedJobAdapter.singleton_class.prepend(Module.new do
  def enqueue(job)
    provider_job = super
    job.provider_job_id = provider_job.id
    provider_job
  end

  def enqueue_at(job, timestamp)
    provider_job = super
    job.provider_job_id = provider_job.id
    provider_job
  end
end)
于 2015-05-29T17:04:31.743 回答
4

受到 Beguene 的回答和 Rails 5 ActiveJob 代码的一些逆向工程的启发,我通过以下方式使其与 Rails 4.2 一起使用

lib/active_job/queue_adapters/delayed_job_adapter.rb1)在or中添加以下代码config/initializers/delayed_job.rb(两个位置都有效):

# file: lib/active_job/queue_adapters/delayed_job_adapter.rb
module ActiveJob
  module Core
    # ID optionally provided by adapter
    attr_accessor :provider_job_id
  end

  module QueueAdapters
    class DelayedJobAdapter
      class << self
        def enqueue(job) #:nodoc:
          delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name)
          job.provider_job_id = delayed_job.id
          delayed_job
        end

        def enqueue_at(job, timestamp) #:nodoc:
          delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp))
          job.provider_job_id = delayed_job.id
          delayed_job
        end
      end
      class JobWrapper #:nodoc:
        attr_accessor :job_data

        def initialize(job_data)
          @job_data = job_data
        end

        def perform
          Base.execute(job_data)
        end
      end
    end
  end
end

Rails 4.2 中需要该attr_accessor :provider_job_id语句,因为它在 enqueue 方法中使用,并且尚未在 4.2 中定义。

然后我们可以像下面这样使用它:

2)定义我们自己的ActiveJob类:

# file: app/jobs/my_job.rb
class MyJob < ActiveJob::Base
  queue_as :default

  def perform(object, performmethod = method(:method))
    # Do something later
      returnvalue = object.send(performmethod)
      returnvalue
    end

  end
end

3)现在我们可以在代码的任何地方创建一个新作业:

job = MyJob.perform_later(Myobject, "mymethod")

这会将方法Myobject.mymethod放入队列中。

4)1)中的代码帮助我们找到与我们的工作相关的延迟工作:

delayed_job = Delayed::Job.find(job.provider_job_id)

5) 最后,我们可以做任何我们需要对delayed_job 做的事情,例如删除它:

delayed_job.delete

注意:在 Rails 5 中,不再需要步骤 1),因为完全相同的代码是 Rails 5 的组成部分。

于 2016-02-01T00:36:44.343 回答
2

我使用 Rails 5 的新补丁使它在 Rails 4.2 中工作,如下所示:

创建文件lib/active_job/queue_adapters/delayed_job_adapter.rb

module ActiveJob
  module QueueAdapters
    class DelayedJobAdapter
      class << self
        def enqueue(job) #:nodoc:
          delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name)
          job.provider_job_id = delayed_job.id
          delayed_job
        end

        def enqueue_at(job, timestamp) #:nodoc:
          delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp))
          job.provider_job_id = delayed_job.id
          delayed_job
        end
      end

      class JobWrapper #:nodoc:
        attr_accessor :job_data

        def initialize(job_data)
          @job_data = job_data
        end

        def perform
          Base.execute(job_data)
        end
      end
    end
  end
end
于 2015-12-22T13:15:05.983 回答
0

如果作业被取消,您可以模拟作业本身的取消,而不是从队列中删除作业。

然后,当您开始运行时,GenerateReportJob您可以先检查是否取消了报告。如果有,那么您可以销毁取消记录并退出报告生成。如果没有取消,那么您可以照常进行。

于 2015-04-24T19:30:41.860 回答