LoginSignup
5
5

More than 5 years have passed since last update.

DelayedJobの殺し方

Last updated at Posted at 2014-03-14

注:最新のDelayedJobはうまくいってるらしいです。

経緯

Railsのバックグランドタスクのために、delayed_jobを利用することにした。
アプリケーションの更新などを行う場合、実行中のjobを停止する必要がある。
ところが、古いdelayed_jobはSIGTERMを受けても実行中のjobを停止させない。
より正確に言えば、delayed_jobはSIGTERMを受け取ると、現在のjobが終わるまで走り続け、その後死ぬ。
ので、kill サクッと殺すために以下の修正を行った。

殺すところから始めよう

job自体を殺すのは簡単で、SIGTERMをtrapしてExceptionを投げれば良い。

Signal.trap(:SIGTERM){ raise SignalException.new('SIGTERM') }

しかしこれだとdelayed_jobがtrapしているものを上書きしてしまうため、
実行中のjobは例外によって停止するが、その後workerは次のjobを実行してしまう。

最終的に

最終的に以下のコードに落ち着いた。

module TrapSignal
  def before
    @term_action = trap(:SIGTERM) {
      @term_action.call                   # delayed_jobのループを止める
      raise SignalException.new(:SIGTERM) # 実行中のjobを止める
    }
  end

  def after
    trap(:SIGTERM, @term_action) # trapを元に戻す
  end
end
class MyJob < ActiveRecord::Base
  include TrapSignal

  def perform
    # 実行したい処理
  end
end
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5