逃げる8回で会心の一撃

Web エンジニアのサトウリョウスケが開発とか色々書くブログです

ActiveJob の retry_on に jitter というオプションがあるの知ってますか?

僕は知らなかったです (・∀・)

jitter とは

Rails 6.1 から追加されたオプション で、 retry_on の待ち時間に対して任意の割合でバラけさせてくれるようになります(デフォルト 15% )。

ActiveJob::Exceptions::ClassMethods - retry_on

:jitter - A random delay of wait time used when calculating backoff. The default is 15% (0.15) which represents the upper bound of possible wait time (expressed as a percentage)

実装を確認してみた

このバラけさせ方が待ち時間に対して増えるのか減るのかが気になって実装を見てみました。増える方向でバラけるようです。 例えば wait: 60.secondsjitter: 0.5 の場合だと、最大 90 秒の待ち時間となります。

うっかり 100.0 とか指定すると最大 10000% 待ち時間が加算されちゃいそうです。 間違えて指定しないようにご注意下さい🙏

delay = seconds_or_duration_or_algorithm.to_i
delay_jitter = determine_jitter_for_delay(delay, jitter)
delay + delay_jitter

📝 jitter の計算処理は このあたり

どういう場面で使うの?

この機能が無かった従来だと、リトライ処理が一斉に起動してしまうという問題がありました。

例えば外部のサービスに API リクエストするような Job を作ったとします。API Rate Limit 超過の例外をハンドリングして、 retry_on で N 分後にリトライするように実装します。 この時、 1000 件の Job が同時に実行され 900 件が Rate Limit 超過となった場合、N 分後に 900 件の Job が一斉にリトライされてしまい、再び 800 件がエラーとなってしまう。 これが何度も繰り返される、という現象が起こってました。

Rails 6.1 以前だと回避できないの?

従来の ActiveJob でも一応回避策はあって、 waitProc を与えてランダムな待ち時間を返すような処理を書くことで似たような動作は可能です。

retry_on SomeError, wait: -> { rand(60..90).seconds }

iPad Air (第4世代) 買っちゃった

f:id:ryz310:20210302102542j:plain
iPad Air (第4世代)

近日中に iPad Pro の新型が出るとの噂があるが、軽い Air がほしかったので問題 🍆 (知らなかったけどね)

🔗 新型iPad Pro搭載A14X/A14Zチップの処理能力はM1チップに匹敵か - iPhone Mania