例外を位置引数で渡すことで Continuable の例外記録が正しくなる
ActiveJob の Continuable ジョブは、途中で回復可能なエラーが発生した場合に continue から再開されますが、エラー情報の記録方法が分岐ごとに不一致でした。本 PR は resume_job を位置引数で呼び出すよう統一し、例外メッセージをキーとした正しい統計が蓄積されるようにします。
背景
続行可能ジョブが StandardError を捕捉した際、従来は resume_job(exception: e) とキーワード形式で呼び出していました。resume_job は位置引数のみを受け取るシグネチャであるため、ハッシュ { exception: e } がそのまま exception パラメータに渡り、executions_for がハッシュ文字列をキーとして記録していました。その結果、例外メッセージではなく "{exception: #<StandardError: …>}" が exception_executions に保存され、Interrupt 分岐とキーが食い違う状態が発生していました。
この不整合はテストでも露呈しており、エラーレジューム後の統計が正しく集計できないという実用的な問題につながっていました。
技術的な変更
continue メソッドの例外処理統一
activejob/lib/active_job/continuable.rb の continue メソッド内で、StandardError 捕捉時に 位置引数 で resume_job を呼び出すよう変更しました。
変更前:
rescue StandardError => e
if resume_errors_after_advancing? && continuation.advanced?
resume_job(exception: e) # キーワード引数形式
else
raise
end
変更後:
rescue StandardError => e
if resume_errors_after_advancing? && continuation.advanced?
resume_job(e) # 位置引数形式
else
raise
end
この一行の差し替えにより、resume_job が期待通りの exception オブジェクトを受け取り、executions_for が例外メッセージ文字列をキーとして正しく記録できるようになります。
テストの追加で挙動を検証
activejob/test/cases/continuation_test.rb に新たにテストケースを追加し、エラー後に exception_executions が { "Cursor error" => 1 } という形で蓄積されることを確認しました。
test "records the exception message as the exception_executions key when resuming after an error" do
IteratingRecord.records = [ 123, 432, 6565, 3243, 234, 13, 22 ].map { |i| IteratingRecord.new(i, "item_#{i}") }
IteratingJob.perform_later(raise_when_cursor: 433)
assert_enqueued_jobs 1, only: IteratingJob do
perform_enqueued_jobs
end
job = queue_adapter.enqueued_jobs.first
assert_equal({ "Cursor error" => 1 }, job["exception_executions"])
end
テストはジョブがキューに入った後に実行され、exception_executions のキーが例外メッセージそのものになることを明示的に検証しています。
設計判断
resume_job のシグネチャは 位置引数 exception のみで定義されており、キーワード引数は意図されていませんでした。そのため、既存の Interrupt 分岐と同様に位置引数で呼び出す方針が採られました。PR の議論では新しいキーワードパラメータ exception: を導入する案も検討されましたが、シグネチャの変更は下位互換性への影響が大きく、既存の呼び出し側に不要なリファクタリングを強いる可能性があったため、最小限の変更で挙動統一 を選択しました。
この判断により、コードベース全体で resume_job の呼び出し方が一貫し、例外記録ロジックがシンプルかつ予測可能になります。
まとめ
resume_job を位置引数で呼び出す統一により、Continuable ジョブのエラー再開時に例外メッセージが正しく exception_executions に記録されるようになりました。追加テストで挙動を裏付け、既存のインターフェースを保ちながらバグを根本的に解消した点が本変更の意義です。