読者です 読者をやめる 読者になる 読者になる

こしごぇ(B)

旧:http://d.hatena.ne.jp/koshigoeb/

delayed_job の plugin

知っていたかもしれないけど、記憶に無かったので調べてまとめてみる。

tl;dr

こんな感じかな?

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_blockclass_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

callbacksDelayed::Plugin.callbacks で、以下の様な実装になっている。

module Delayed
  class Plugin
    class_attribute :callback_block

    def self.callbacks(&block)
      self.callback_block = block
    end

プラグインはワーカーのライフサイクルを拡張する処理を実装し、その実装がライフサイクルのコールバックで実行される様に登録するのが仕事。

きっかけ

delayed_job のプラグインについて調べようと思ったきっかけは以下の gem。