注:最新の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