リトライ処理の作成メモです。
アルゴリズムはAWSでお馴染みのExponentialBackoffを使用しています。
Function
export function sleep (milliSec: number) {
return new Promise(resolve => setTimeout(resolve, milliSec))
}
export async function backOff <T> (
handler: () => T | Promise<T>,
checkHandler: (val: T) => boolean,
maxCount: number = 5,
interval: number = 100
): Promise<T | undefined> {
for (let retryNum = 0; retryNum < maxCount; retryNum++) {
const handlerResult = handler()
const result = await (handlerResult instanceof Promise
? handlerResult : Promise.resolve(handlerResult))
if (checkHandler(result)) {
return result
}
await sleep(2 ** retryNum * interval)
}
return undefined
}
Params
リトライ内で評価したい処理を定義します。
Promiseが返却されることも想定しておきます。
handler: () => T | Promise<T>
リトライ処理を抜ける条件の評価式です。
checkHandler: (val: T) => boolean
使い方
0 ~ 200のランダムな整数の生成を、100以上の整数が取得されるまで最大5回トライします。
// expected output: 0 ~ 200
const getRandomInt = () => Math.floor(Math.random() * 200)
const isOver100 = (num) => num >= 100
const num = await backOff <number | undefined> (getRandomInt, isOver100)
console.log(num)
補足
今回は異常系は考慮していません。
例えば、apiリクエストをエラーレスポンスのコードでリトライか異常終了するか判断する場合は、
Error判定用のhandlerをbackOffの引数に追加してtry-catch内でcallすれば良さそう。