delayed_job の plugin
知っていたかもしれないけど、記憶に無かったので調べてまとめてみる。
tl;dr
こんな感じかな?
- delayed_job にはプラグイン機構がある
- プラグインは
Delayed::Plugin
を継承して実装する - プラグインによってワーカーのイベントコールバックを登録できる
- プラグインの仕事は二つ
- イベントコールバックを登録する
- イベントハンドラを実装する
Delayed::Worker.plugins
Delayed::Worker.plugins
はプラグインクラスの配列で、初期値は [Delayed::Plugins::ClearLocks]
となっている。
Delayed::Worker.setup_lifecycle
プラグインは Delayed::Worker.setup_lifecycle
メソッドの中で plugins.each { |klass| klass.new }
のようにして初期化されている。
Delayed::Plugin
プラグインクラスは Delayed::Plugin
を継承する前提となっている。
Delayed::Plugin#initialize
の中で self.class.callback_block.call(Delayed::Worker.lifecycle)
が実行されている。
callback_block
は class_attribute :callback_block
の様に宣言されている。
Declare a class-level attribute whose value is inheritable by subclasses. Subclasses can change their own value and it will not impact parent class. http://apidock.com/rails/Class/class_attribute
Delayed::Lifecycle
Delayed::Lifecycle#initialize
は以下の様に定義されている。
module Delayed class InvalidCallback < Exception; end class Lifecycle EVENTS = { :enqueue => [:job], :execute => [:worker], :loop => [:worker], :perform => [:worker, :job], :error => [:worker, :job], :failure => [:worker, :job], :invoke_job => [:job] } def initialize @callbacks = EVENTS.keys.each_with_object({}) do |e, hash| hash[e] = Callback.new end end
Delayed::Lifecycle
クラスには以下の様なメソッドでコールバックを登録する事ができる。
Delayed::Lifecycle#before
Delayed::Lifecycle#after
Delayed::Lifecycle#around
プラグインでコールバックを登録することで、delayed_job のワーカーライフサイクルを拡張する、という感じ。
Delayed::Plugins::ClearLocks
delayed_job 組み込みのプラグイン Delayed::Plugins::ClearLocks
を見てみる。
module Delayed module Plugins class ClearLocks < Plugin callbacks do |lifecycle| lifecycle.around(:execute) do |worker, &block| begin block.call(worker) ensure Delayed::Job.clear_locks!(worker.name) end end end end end end
callbacks
は Delayed::Plugin.callbacks
で、以下の様な実装になっている。
module Delayed class Plugin class_attribute :callback_block def self.callbacks(&block) self.callback_block = block end
プラグインはワーカーのライフサイクルを拡張する処理を実装し、その実装がライフサイクルのコールバックで実行される様に登録するのが仕事。
きっかけ
delayed_job のプラグインについて調べようと思ったきっかけは以下の gem。