例
API 呼び出しとタイムアウトの処理
サードパーティサービスへの API 呼び出しにおいて、いくつかの要件があります。
全体の関数が 4 秒以上かかる場合は中断するようにします。
さらに、API 呼び出しを最大 2 回再試行するように設定します。
解決策
import { NodeRuntime } from "@effect/platform-node";import { Console, Effect } from "effect";
const getJson = (url: string) => Effect.tryPromise(() => fetch(url).then((res) => { if (!res.ok) { console.log("エラー"); throw new Error(res.statusText); } console.log("成功"); return res.json() as unknown; }) );
const program = (url: string) => getJson(url).pipe( Effect.retry({ times: 2 }), Effect.timeout("4 seconds"), Effect.catchAll(Console.error) );
// ハッピーパスのテストNodeRuntime.runMain(program("https://dummyjson.com/products/1?delay=1000"));/*出力:成功*/
// タイムアウトのテスト// NodeRuntime.runMain(program("https://dummyjson.com/products/1?delay=5000"))/*出力:TimeoutException*/
// APIエラーのテスト// NodeRuntime.runMain(// program("https://dummyjson.com/auth/products/1?delay=500")// )/*出力:エラーエラーエラーUnknownException: Forbidden*/条件付き再試行の実装
特定の種類のエラーが発生したときのみ API 呼び出しを再試行するメカニズムを実装したいと思います。
解決策
import { NodeRuntime } from "@effect/platform-node";import { Console, Effect } from "effect";
class Err extends Error { constructor(message: string, readonly status: number) { super(message); }}
const getJson = (url: string) => Effect.tryPromise({ try: () => fetch(url).then((res) => { if (!res.ok) { console.log(res.status); throw new Err(res.statusText, res.status); } return res.json() as unknown; }), catch: (e) => e as Err, });
const program = (url: string) => getJson(url).pipe( // エラーが403の場合に再試行 Effect.retry({ while: (err) => err.status === 403 }), Effect.catchAll(Console.error) );
// 403のテストNodeRuntime.runMain( program("https://dummyjson.com/auth/products/1?delay=1000"));/*出力:403403403403...*/
// 404のテスト// NodeRuntime.runMain(program("https://dummyjson.com/-"))/*出力:404Err [Error]: Not Found*/完了までのスケジュールされた Effect の実行
スケジュールを使用して、別の長時間実行される Effect が完了するまで定期的に Effect を実行することができます。これは、ポーリングや定期的なログ記録のようなタスクに便利です。
解決策
import { Effect, Console, Schedule } from "effect";
const longRunningEffect = Console.log("完了").pipe(Effect.delay("5 seconds"));
const action = Console.log("アクション...");
const schedule = Schedule.fixed("1.5 seconds");
const program = Effect.race(Effect.repeat(action, schedule), longRunningEffect);
Effect.runPromise(program);/*出力:アクション...アクション...アクション...アクション...完了*/