在Rails 5.x中扩展具有延迟作业队列的ActiveJob

问题描述 投票:0回答:1

似乎无法从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
ruby-on-rails ruby-on-rails-5 delayed-job rails-activejob
1个回答
0
投票

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.rbmonkey 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唯一性错误而失败,您可以在将任务入队的控制器中或从何处将其入队的异常处理。

© www.soinside.com 2019 - 2024. All rights reserved.