ActiveJob в Rails похож на ActiveRecord в том, что они оба предоставляют стабильный API для бэкэнда (в случае с DB в AR и для AJ в виде очереди). DelayedJob - это только один из бэкэндов AJ, так же как MySQL или Postgresql являются бэкэндами для AR.
Если вы копаетесь в коде DelayedJob (и вы используете ActiveRecord в качестве бэкэнда для DelayedJob через гем delayed_job_active_record), вы обнаружит, что Delayed :: Job - это просто еще один подкласс ActiveRecord :: Base, как и любая из ваших моделей.
Это означает, что у вас есть доступ ко всем объектам DelayedJob через Класс Delayed :: Job, со всеми методами поиска и проверки, которые вы можете ожидать от 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 при постановке в очередь. Таким образом, вы можете добавить любую информацию, которая сделает ваши работы уникальными, это может быть идентификатор какой-либо другой модели, параметры работы или все, что вам нужно. 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, которую вы можете обработать в контроллере, который поставил в очередь задание, или откуда вы ставите задание в очередь.