effect-ts-concurrency について
並列処理、バックグラウンドの Fiber、レート制限付き処理を調整する開発者向けの Effect-TS 並行処理スキルです。並列数の制御や、セマフォと Deferred によるシグナル連携を扱います。
主な機能
- 01並列実行数の制限
- 02Fiber によるバックグラウンド処理
- 03セマフォによる並行数制御
- 04Deferred によるシグナル通知
活用シーン
- 01並列数を制限したコレクション処理
- 02API やデータベース要求のレート制限
- 03バックグラウンドタスクの調整
- 04並行処理間のシグナル通知
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mrevanzak/ effect-ts-skills --skill effect-ts-concurrencyインストール後、Claude Code で/effect-ts-concurrencyを入力して読み込まれたか確認します。
詳細
Effect-TS の並行処理
概要
Effect-TS は、高性能な並行処理のための軽量なファイバーを提供します。中心となる原則は明示的な制御です。リソースの枯渇を防ぐため、並列処理には常に上限を設けてください。
使用する場面
- 大きなエフェクトの配列を処理する場合(例:
Effect.all、Effect.forEach) - 外部 API 呼び出しやデータベース接続をレート制限する場合
- バックグラウンドプロセス(ファイバー)間で作業を調整する場合
- アプリの異なる部分間で完了や状態の変化を通知する場合
使用しない場面:
- 単純な逐次処理
- 標準の
Promise.allで十分な場合(ただし、一貫性を保つため、通常は Effect が推奨されます)
基本パターン:上限付き並列処理
上限のない並列処理は、「開いているファイルが多すぎます」や「接続タイムアウト」エラーの最も一般的な原因です。
| パターン | 実装 | 結果 |
|---|---|---|
| BAD | Effect.all(effects) | 上限なし — 入力が大きいとクラッシュします |
| GOOD | Effect.all(effects, { concurrency: 10 }) | 上限あり — 安全で予測可能です |
クイックリファレンス
| ツール | 用途 | 主なメソッド |
|---|---|---|
| Fiber | バックグラウンドでの実行 | Effect.fork / Fiber.join |
| Semaphore | 上限付き並行処理/レート制限 | semaphore.withPermits(n) |
| Deferred | 1 回限りの通知/プロミス | Deferred.await / Deferred.succeed |
| concurrency | all、forEach、mapEffect のオプション | `{ concurrency: number |
実装
1. 上限付き並列処理(必須)
コレクションを処理するときは、必ず並行処理数を指定してください。
import { Effect } from 'effect';
// Process 1000 items, max 10 concurrent
const results = yield* Effect.all(
items.map(processItem),
{ concurrency: 10 }
);
2. レート制限のための Semaphore
複数の独立した操作でグローバルな上限を共有する必要がある場合は、Semaphore を使用してください。
import { Effect } from 'effect';
const program = Effect.gen(function* () {
const semaphore = yield* Effect.makeSemaphore(5); // Max 5 concurrent
yield* Effect.all(
requests.map((req) =>
semaphore.withPermits(1)(handleRequest(req))
),
{ concurrency: 'unbounded' } // Semaphore controls actual concurrency
);
});
3. 通知のための Deferred
別のファイバーから特定のイベントや値が届くのを待つには、Deferred を使用してください。
import { Deferred, Effect, Fiber } from 'effect';
const program = Effect.gen(function* () {
const signal = yield* Deferred.make<void>();
const worker = yield* Effect.fork(
Effect.gen(function* () {
yield* Deferred.await(signal); // Wait for signal
yield* doWork();
})
);
yield* setup();
yield* Deferred.succeed(signal, undefined); // Trigger worker
yield* Fiber.join(worker);
});
よくある間違い
- 上限のない並列処理:
Effect.allで{ concurrency: n }を指定し忘れる。 - ファイバーのリーク: ファイバーを fork したまま join も中断もしない(安全のために
Effect.scopedを使用してください)。 - デッドロック: セマフォまたは deferred 間の循環依存。
危険信号 — STOP して最初からやり直す
{ concurrency: n }を指定せずに、大きな配列に対してEffect.allを使用している。- Effect-TS のコードベース内で
Promise.allを使用している。 - レート制限に
Effect.makeRateLimiterやSemaphoreではなく、手動のsetTimeoutを使用している。
正当化の一覧
| 言い訳 | 実際のところ |
|---|---|
| 「たった 100 項目です」 | 今日は 100 項目でも、明日は 10,000 項目かもしれません。今すぐ上限を設定してください。 |
| 「API は高速です」 | ネットワーク遅延やサーバー負荷は予測できません。 |
| 「並行処理は後で追加します」 | 上限のない並列処理は、いつ爆発してもおかしくない時限爆弾です。 |
必須の予備知識: 上限のない並列処理について詳しくは、effect-ts-anti-patterns を参照してください。
コメント
Markdown 対応