コンテンツにスキップ
UniKVS
Esc
↑↓移動↵開く⌘Jプレビュー
このページの内容

@unikvs/retry

一時的な失敗を指数バックオフで再試行するストレージラッパーです。

概要

Retry は委譲先ストレージの一時的な失敗を指数バックオフで再試行し、読み書きが成功しやすくします。

不安定な回線や一時的な過負荷で失敗する操作の再試行に使います。再試行の可否判定と待機時間は調整できます。

  • name は Retry です。
  • isOpen は委譲先の inner.isOpen を返します。
  • write・read・exists・delete・copy・move・clear・getWritable・getReadable を再試行し、open・close・onOtherWriteError は委譲のみ行います。
  • データとチャンクの変換は行わず、委譲先の型をそのまま保ちます。

インストールは次のコマンドで行います。

npm install @unikvs/retry
pnpm add @unikvs/retry
yarn add @unikvs/retry
bun add @unikvs/retry
nub add @unikvs/retry
aube add @unikvs/retry

使い方

Retry は IStorage を実装しています。UniKvs には persist() で渡します。

import { Retry } from "@unikvs/retry";

コンストラクターの引数は次のとおりです。

プロパティ型
innerIStorage

委譲先のストレージです。

型IStorage
maxRetries?number

初回試行の後の再試行回数です。0 では再試行しません。

型number
デフォルト3
initialDelayMs?number

初回の待機時間 (ミリ秒) です。

型number
デフォルト100
maxDelayMs?number

待機時間の上限 (ミリ秒) です。

型number
デフォルト5000
factor?number

待機時間の増加係数です。

型number
デフォルト2
jitter?boolean

待機時間にジッターを加えるかどうかです。

型boolean
デフォルトtrue
retryable?RetryablePredicate

エラーがリトライ可能かどうかを判定する述語です。既定では isRetryableError を使用します。

型RetryablePredicate
onRetry?(info: RetryAttemptInfo) => void

再試行の直前に呼び出される通知です。

型(info: RetryAttemptInfo) => void

以下は、委譲先の一時的な失敗を再試行する例です。

import { Memory } from "@unikvs/memory";
import { Retry } from "@unikvs/retry";
import * as unikvs from "unikvs";

const kvs = new unikvs.Builder<{ k1: unikvs.PlainValue<string> }>()
  .persist(new Retry(new Memory(), { maxRetries: 3 }))
  .build();

await kvs.open();
await kvs.set("k1", "hello");
console.log(await kvs.get("k1")); // "hello"
await kvs.close();

Retry

一時的な失敗を指数バックオフで再試行するストレージラッパーです。待機時間は initialDelayMs * factor^(attempt-1) で増加し、maxDelayMs が上限になります。

RetryOptions

Retry のコンストラクターが受け取るオプションです。再試行回数と待機時間、判定述語を指定します。

RetryOperation

リトライ対象の操作名です。"write"・"read"・"exists"・"delete"・"copy"・"move"・"clear"・"getWritable"・"getReadable" のいずれかです。

RetryablePredicate

エラーがリトライ可能かどうかを判定する述語です。

RetryAttemptInfo

リトライが発生したときに通知される試行情報です。

プロパティ型
operationRetryOperation

失敗した操作名です。

型RetryOperation
attemptnumber

失敗した試行回数 (1 始まり) です。

型number
errorunknown

発生したエラーです。

型unknown
nextDelayMsnumber

次の試行までの待機時間 (ミリ秒) です。

型number

isRetryableError

既定のリトライ可否判定です。この判定では、存在しないキーなどの恒久的な失敗と、中断による失敗はリトライしません。

データ型

操作 対応するデータ型
write・read・copy・move 委譲先のデータ型をそのまま保つ
getWritable・getReadable のチャンク 委譲先のチャンク型をそのまま保つ
  • すべての操作は委譲先の型をそのまま保ち、データとチャンクの変換を行いません。
  • 再試行対象は読み書きと存在確認、削除、コピー、移動、全削除、ストリーム取得です。
  • 内側ストレージが copy または move を持たない場合は、read・write・delete を組み合わせて同じ動作を再現します。
  • フォールバックは読み出し後と移動先への書き込み後に中断シグナルを確認します。書き込み後に中断された move は移動元を削除しないため、移動元と移動先の両方が残ります。
  • open と close の失敗は再試行せず、そのまま伝播します。
  • 待機時間は指数関数的に増加して上限で抑えられ、jitter が true の場合は上限の半分から上限までの範囲で変動します。

エラー

このパッケージが投げるエラーは次のとおりです。

RetryExhaustedError

プロパティ型
operationstring

失敗した操作名です。

型string
attemptsnumber

実行した試行回数です。

型number

意味

最大試行回数を超えても操作が成功しなかったときに投げます。最後に発生したエラーは cause に保持されます。

対処方法

cause から元の失敗原因を確認し、一時的な障害かどうかを切り分けてください。頻発する場合は maxRetries や待機時間、retryable の判定を見直してください。

例

以下は、RetryExhaustedError を捕捉する例です。

import { RetryExhaustedError } from "@unikvs/retry";

try {
  await kvs.set("k1", "hello");
} catch (ex) {
  if (ex instanceof RetryExhaustedError) {
    console.log(ex.meta); // { operation: "write", attempts: 4 }
    console.log(ex.cause); // 最後のエラー
  } else {
    throw ex;
  }
}

RetryInvalidOptionError

プロパティ型
namestring

不正だったオプション名です。

型string
actualunknown

指定された値です。

型unknown

意味

コンストラクターに不正なオプションが渡されたときに投げます。負の再試行回数や非整数、負の待機時間、1 未満の係数で投げます。

対処方法

meta.name のオプションを確認し、maxRetries は 0 以上の整数、initialDelayMs と maxDelayMs は 0 以上の有限数、factor は 1 以上の有限数を指定してください。

例

以下は、RetryInvalidOptionError を捕捉する例です。

import { RetryInvalidOptionError } from "@unikvs/retry";

try {
  const retry = new Retry(inner, { maxRetries: -1 });
} catch (ex) {
  if (ex instanceof RetryInvalidOptionError) {
    console.log(ex.meta); // { name: "maxRetries", actual: -1 }
  } else {
    throw ex;
  }
}

RetryUnsupportedOperationError

プロパティ型
operationstring

実装されていない操作名です。

型string
storagestring

委譲先のストレージ名です。

型string

意味

委譲先のストレージが getWritable や getReadable を実装していないときに投げます。

対処方法

委譲先がストリーム操作に対応しているか確認し、未対応の場合はプレーンな読み書きを使ってください。

例

以下は、RetryUnsupportedOperationError を捕捉する例です。

import { RetryUnsupportedOperationError } from "@unikvs/retry";

try {
  await kvs.stream("logs");
} catch (ex) {
  if (ex instanceof RetryUnsupportedOperationError) {
    console.log(ex.meta); // { operation: "getReadable", storage: "Bare" }
  } else {
    throw ex;
  }
}

KeyNotFoundError と中断による AbortError は既定では再試行せず、そのまま伝播します。

このページは役に立ちましたか?