Rails 4.2 从活动作业中获取延迟的作业ID
Rails 4.2 get delayed job id from active job
知道如何从 ActiveJob 排队中获取 Delayed::Job
id 吗?当我对一个作业进行排队时,我得到一个 ActiveJob::Base
的实例和一个 @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
但这似乎有点老套。有点惊讶 ActiveJob 没有从 Delayed::Job
返回 ID,特别是因为这是在作业入队时明确返回的内容。
== 编辑
看来我不是唯一一个(https://github.com/rails/rails/issues/18821)
如果作业被取消,您可以模拟作业本身的取消,而不是从队列中移除作业。
然后,当您到达运行 GenerateReportJob
时,您可以先检查是否取消了报告。如果有,那么您可以销毁取消记录并退出报告生成。如果没有取消,那么您可以照常进行。
以防将来有人发现:Rails 刚刚接受了一个补丁,允许您从 Rails 中的 provider_job_id 获取此 ID 5. 您可以让它工作像
这样的补丁
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)
我使用 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
受 Beguene 的回答和 Rails 5 ActiveJob 代码的一些逆向工程的启发,我通过
使其与 Rails 4.2 一起工作
1) 在 lib/active_job/queue_adapters/delayed_job_adapter.rb
或 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
attr_accessor :provider_job_id
语句在Rails4.2中是需要的,因为它是在enqueue方法中使用的,在4.2中还没有定义。
然后我们可以像下面这样使用它:
2) 定义我们自己的ActiveJob class:
# 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 的组成部分。
知道如何从 ActiveJob 排队中获取 Delayed::Job
id 吗?当我对一个作业进行排队时,我得到一个 ActiveJob::Base
的实例和一个 @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
但这似乎有点老套。有点惊讶 ActiveJob 没有从 Delayed::Job
返回 ID,特别是因为这是在作业入队时明确返回的内容。
== 编辑
看来我不是唯一一个(https://github.com/rails/rails/issues/18821)
如果作业被取消,您可以模拟作业本身的取消,而不是从队列中移除作业。
然后,当您到达运行 GenerateReportJob
时,您可以先检查是否取消了报告。如果有,那么您可以销毁取消记录并退出报告生成。如果没有取消,那么您可以照常进行。
以防将来有人发现:Rails 刚刚接受了一个补丁,允许您从 Rails 中的 provider_job_id 获取此 ID 5. 您可以让它工作像
这样的补丁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)
我使用 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
受 Beguene 的回答和 Rails 5 ActiveJob 代码的一些逆向工程的启发,我通过
使其与 Rails 4.2 一起工作1) 在 lib/active_job/queue_adapters/delayed_job_adapter.rb
或 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
attr_accessor :provider_job_id
语句在Rails4.2中是需要的,因为它是在enqueue方法中使用的,在4.2中还没有定义。
然后我们可以像下面这样使用它:
2) 定义我们自己的ActiveJob class:
# 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 的组成部分。