似乎无法从activeJob中访问delay_job对象。
到目前为止,我已经解决了这一问题,通过添加上下文作为额外的参数(并在调用时将其删除),这样我就可以添加所需的任何其他信息(例如,多租户)。 handler
列中的任何其他参数都将对此进行编码。
尽管我想查找重复项,但是使用这种方法时会遇到一些问题。因此,我想定义一个额外的作业ID j_id
列,该列将用于查找重复项。
由于我无法访问delay_job,因此找不到填充它的方法。
这是我到目前为止所做的:
# already added column j_id to delayed_job table in migration file
class ApplicationJob < ActiveJob::Base
before_enqueue :add_context
def add_context
# How can I set the j_id from here?
end
Rails的ActiveJob与ActiveRecord相似,因为它们都向后端(在AR情况下为DB,而对AJ则为队列后向)提供稳定的API。就像MySQL或Postgresql是AR的后端一样,DelayedJob只是AJ的后端之一。
[如果您深入研究DelayedJob的代码(并且您正在使用ActiveRecord作为通过delay_job_active_record gem到DelayedJob的后端),您会发现Delayed::Job就像另一个模型一样,只是另一个ActiveRecord :: Base子类。
这意味着您可以通过Delayed :: Job类访问所有DelayedJob对象,并具有ActiveRecord可能提供的所有查找和验证方法。
#<Delayed::Backend::ActiveRecord::Job:0x00007f00889c3210
id: 1,
priority: 0,
attempts: 0,
handler:
"--- !ruby/object:ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper\n" +
"job_data:\n" +
" job_class: ApplicationJob\n" +
" job_id: 5f7539a3-120a-45b4-a6d7-12ec8c6cad3d\n" +
" provider_job_id: \n" +
" queue_name: default\n" +
" priority: \n" +
" arguments: []\n" +
" executions: 0\n" +
" exception_executions: {}\n" +
" locale: en\n" +
" timezone: UTC\n" +
" enqueued_at: '2020-03-02T05:38:22Z'\n",
last_error: nil,
run_at: Mon, 02 Mar 2020 05:38:22 UTC +00:00,
locked_at: nil,
failed_at: nil,
locked_by: nil,
queue: "default",
created_at: Mon, 02 Mar 2020 05:38:22 UTC +00:00,
updated_at: Mon, 02 Mar 2020 05:38:22 UTC +00:00>
该类由名为delayed_jobs
的表支持,正如您从任何AR类中所期望的那样,因此您可以生成在该表上添加或更改列的迁移(添加j_id):
rails g migration AddJIdToDelayedJobs j:string
要添加验证,您可以创建config/initializers/delayed_job.rb
和monkey patch类。
module Delayed
class Job
validates :j_id, uniqueness: true
end
end
剩下的唯一一件事是在作业入队时将数据添加到j_id列。这样,您可以添加任何使您的工作独特的信息,也可以是其他模型的ID或工作参数或您需要的任何信息。 DelayedJob提供了一个很酷的plugin解决方案,因此我们可以使用它来插入作业生命周期,并在作业入队时将信息添加到j_id中。返回config/initializers/delayed_job.rb
,让我们添加新的插件类:
module Delayed
class UniqueJobsPlugin < Plugin
callbacks do |lifecycle|
lifecycle.before(:enqueue) do |job|
job.j_id = job #.anything inside the job, remember .handler is in YAML
end
end
end
end
Delayed::Worker.plugins << Delayed::UniqueJobsPlugin
要获取YAML处理程序属性内的任何信息,您可以执行handler_attributes = YAML.load(job.handler)
现在,如果j_id不是唯一的,入队将因通常的AR唯一性错误而失败,您可以在将任务入队的控制器中或从何处将其入队的异常处理。