Fiber (Effect)
Effect-TSにおける軽量な仮想スレッド
Effectを実行したときに生成される実行単位
Effectを実行するたびにファイバーが生成される
特に並行してEffectを実行すると、それぞれに対応したファイバーが生成される
Effectの中断・待機・結果の取得などが可能
docs
#wip
Fiber型
code:ts
Fiber<Success, Error>
成功時にSuccess型の値を返す
失敗時にError型のエラーを返す
Effect.fork
Fiber.join
Fiber.await
Fiber.interrupt
Fiberの合成
Fiber.zip
Fiber.zipWith
Child Fiberのlifetime
https://effect.website/docs/concurrency/fibers/#lifetime-of-child-fibers
4種類のfork方法がある
どれでforkするかで、lifecycleが変わる
1. Effect.fork
2. Effect.forkDaemon
3. Effect.forkScoped
4. Effect.forkIn
Fiberはいつ実行されるのか
https://effect.website/docs/concurrency/fibers/#when-do-fibers-run
Fiberは fork された直後に即実行されるとは限らず、現在のFiberの実行が終わるかyieldされるまで開始されないことがある
例:遅延実行によって一部の値しか取得されない
code:ts
import { Effect, SubscriptionRef, Stream, Console } from "effect"
const program = Effect.gen(function* () {
const ref = yield* SubscriptionRef.make(0)
yield* ref.changes.pipe(
Stream.tap((n) => Console.log(SubscriptionRef changed to ${n})),
Stream.runDrain,
Effect.fork
)
yield* SubscriptionRef.set(ref, 1)
yield* SubscriptionRef.set(ref, 2)
})
Effect.runFork(program)
SubscriptionRefってなに?
解決策:Effect.sleep または Effect.yieldNowを使用してFiberの起動タイミングを調整
code:ts
const program = Effect.gen(function* () {
const ref = yield* SubscriptionRef.make(0)
yield* ref.changes.pipe(
Stream.tap((n) => Console.log(SubscriptionRef changed to ${n})),
Stream.runDrain,
Effect.fork
)
yield* Effect.sleep("100 millis") // Fiber起動を待つ
yield* SubscriptionRef.set(ref, 1)
yield* SubscriptionRef.set(ref, 2)
})
Effect.runFork(program)
/*
出力:
SubscriptionRef changed to 0
SubscriptionRef changed to 1
SubscriptionRef changed to 2
*/