ActiveJobの `retry_on` が Float の `:wait` を受け付けるようになった
ActiveJob の retry_on が :wait オプションに Float 値を渡すことを正式にサポートし、整数への変換ではなくそのままの小数点以下を利用できるようになりました。これにより、1.5.seconds のようなサブ秒レベルの待ち時間指定が例外なく動作し、テストでも期待通りのリトライ間隔が確認できます。
背景
retry_on の :wait は従来「秒数(デフォルト 3 秒)」と記載され、整数のみが正しく処理されていました。Float を渡すと determine_delay がマッチせず Couldn't determine a delay based on 2.5 という例外が発生し、リトライ自体が行われない問題がありました(例: retry_on SomeError, wait: 2.5)。この挙動は ActiveJob.set(wait: 2.5) が Float を受け入れるのとは不整合で、開発者に混乱を招いていました。PR #57817 ではこの不整合を解消し、Float を正式に受け入れる変更が行われました。
技術的な変更
activejob/lib/active_job/exceptions.rb の determine_delay メソッドに Float をマッチ対象に加え、遅延計算に to_f を使用するよう変更されました。
変更前:
when ActiveSupport::Duration, Integer, Float
delay = seconds_or_duration_or_algorithm.to_i
変更後:
when ActiveSupport::Duration, Integer, Float
delay = seconds_or_duration_or_algorithm.to_f
この差分により、2.5 や 4.5 といった Float がそのまま秒数として扱われ、内部で整数へ丸める処理が除かれました。さらに、activejob/test/jobs/retry_job.rb では FloatWaitError の待機時間を wait: 4.5 に変更し、テストコードでも期待遅延 4.5.seconds が正しく計算されることを検証しています。テストケース float wait job も同様に期待値を 4.5.seconds に合わせて更新され、 CI がパスすることが確認されています。
設計判断
Float の受け入れは Numeric 系の拡張として最小限の変更で実装され、既存の整数・Duration との互換性を保持しています。to_f を用いることで、将来的にサブ秒精度をサポートできる余地を残しつつ、現行のキューアダプタが整数秒のみを期待するケースでも安全に動作します。新たな設定キーを導入せず、既存の retry_on オプションをそのまま拡張した点が、バックワード・コンパチビリティを重視した設計判断と言えるでしょう。
まとめ
retry_on の :wait に Float を渡すことが正式に可能になり、ActiveJob.set と同様の挙動が提供されました。determine_delay のマッチ対象拡張と to_f への変更だけで実装でき、既存コードへの影響はほぼありません。この改修により、サブ秒レベルのリトライ遅延指定が安全に利用できるようになりました。