Born Too Late

Yuya's old tech blog.

PHP でも retry-handler を実装した

2012-03-20 02:02:29

便利そうだったので PHP でも実装しました.
Packagist に公開したので Composer でインストールできます.

何をするものかというと, 例えば HTTP リクエストなど, 失敗する可能性のある処理をリトライしよう, というときの処理を抽象化するためのものです.

インストール

Composer を使用するので, 適当なディレクトリに composer.json を用意します.

そして以下のコマンドを実行すると Composer 自体をインストールした後, Composer で RetryHandler が ./vendor ディレクトリにインストールされます.

使い方

無名関数をラップして, リトライしたい処理を Proc オブジェクトとして生成します.
retry() メソッドを呼び出すと引数に呼び出した数だけリトライ処理を行い, 全て失敗した場合は RetryOverException がスローされます.

リトライ対象の例外を指定する

デフォルトでは RuntimeException かそのサブクラスがスローされた場合のみリトライを行い, それ以外 (例えば LogicException など) の例外がスローされたら強制的に終了となります.

あるライブラリがスローする例外のみを想定してリトライし, それ以外はエラーとする, といった場合は accepted_exception オプションを使用することで実現できます.

待ち時間を入れる

リトライの前に待ち時間を入れたい, というときは wait オプションを使い, 待ち時間を秒単位で指定できます.
デフォルトでは 1 秒になっています.

まとめ

元の Ruby の実装だと Parallel や Thread を使ったとてもクールな実装になっていて, 素の PHP だとそこまではできなさそうな感じではありますが, リトライ処理自体は PHP でも割とやると思うので, 奇麗に書けるといいんじゃないかと思います.

RetryHandler はとりあえず動いた, 程度のレベルで, まだまだ使えない (例えば, Proc の中の値どうやって取るんだ, とか) と思うんですが, その辺りは今後気まぐれで改善していければという感じです.

ところで 2 年程まえにちょうど同じような需要があって作った Retrial というものがあるんですけど, 今見るととても酷いコードで, テストも何がやりたいのかわからない感じ.
まぁこの頃よりはまだマシなコードが書けるようになったんだなと自分を納得させています.