FiberSet
Manages many fibers together inside one scope.
A FiberSet<A, E> tracks running fibers, removes each fiber when it
completes, and interrupts all still-running fibers when the owning scope
closes. This module includes scoped runtime constructors plus helpers for
adding, clearing, running, counting, joining, and waiting for managed fibers.
Combinators
Adds a fiber to the FiberSet. When the fiber completes, it will be removed.
Signature
declare const add: { <A, E, XE, XA>(fiber: Fiber<XA, XE>, options?: { readonly propagateInterruption?: boolean; }): (self: FiberSet<A, E>) => Effect<void>; <A, E, XE, XA>(self: FiberSet<A, E>, fiber: Fiber<XA, XE>, options?: { readonly propagateInterruption?: boolean; }): Effect<void>;}Example
(Adding a fiber)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make() const fiber = yield* Effect.forkChild(Effect.never)
// Add the fiber to the set yield* FiberSet.add(set, fiber)
// The fiber is now managed by the set return yield* FiberSet.size(set)})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => 1Adds an existing fiber to the FiberSet using a synchronous, unsafe
mutation.
When to use
Use when an already forked fiber must be registered immediately and synchronous interruption on a closed set is acceptable.
Details
When the fiber completes, it is removed from the set. If the set is already
closed, the supplied fiber is interrupted immediately. Non-interruption
failures are recorded for FiberSet.join.
Signature
declare const addUnsafe: { <A, E, XE, XA>(fiber: Fiber<XA, XE>, options?: { readonly propagateInterruption?: boolean; }): (self: FiberSet<A, E>) => void; <A, E, XE, XA>(self: FiberSet<A, E>, fiber: Fiber<XA, XE>, options?: { readonly propagateInterruption?: boolean; }): void;}Example
(Adding a fiber unsafely)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make() const fiber = yield* Effect.forkChild(Effect.never)
// Unsafe add - doesn't return an Effect FiberSet.addUnsafe(set, fiber)
// The fiber is now managed by the set return yield* FiberSet.size(set)})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => 1awaitEmpty
Waits until the fiber set is empty.
Signature
declare function awaitEmpty<A, E>(self: FiberSet<A, E>): Effect<void>Example
(Waiting for an empty set)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make()
yield* FiberSet.run(set, Effect.yieldNow) yield* FiberSet.run(set, Effect.yieldNow)
// Wait for all fibers to complete yield* FiberSet.awaitEmpty(set)
return yield* FiberSet.size(set)})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => 0Interrupts all fibers in the FiberSet and clears the set.
Signature
declare function clear<A, E>(self: FiberSet<A, E>): Effect<void>Example
(Clearing all fibers)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make()
// Add some fibers yield* FiberSet.run(set, Effect.never) yield* FiberSet.run(set, Effect.never)
const sizeBefore = yield* FiberSet.size(set)
// Clear all fibers yield* FiberSet.clear(set)
return [sizeBefore, yield* FiberSet.size(set)]})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => [2, 0]Joins all fibers in the FiberSet. If any fiber in the set terminates with a failure, the returned Effect will terminate with the first failure that occurred.
Signature
declare function join<A, E>(self: FiberSet<A, E>): Effect<void, E>Example
(Joining failing fibers)
import { Effect, Exit, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make() yield* FiberSet.add(set, Effect.runFork(Effect.fail("error")))
// parent fiber will fail with "error" yield* FiberSet.join(set)})
const actual = await Effect.runPromise(Effect.exit(Effect.scoped(program)))actual // => Exit.fail("error")Forks an Effect and add the forked fiber to the FiberSet. When the fiber completes, it will be removed from the FiberSet.
Signature
declare const run: { <A, E>(self: FiberSet<A, E>, options?: { readonly propagateInterruption?: boolean; readonly startImmediately?: boolean; }): <R, XE, XA>(effect: Effect<XA, XE, R>) => Effect<Fiber<XA, XE>, never, R>; <A, E, R, XE, XA>(self: FiberSet<A, E>, effect: Effect<XA, XE, R>, options?: { readonly propagateInterruption?: boolean; readonly startImmediately?: boolean; }): Effect<Fiber<XA, XE>, never, R>;}Example
(Forking effects into a set)
import { Effect, Fiber, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make()
// Fork and add to set const fiber1 = yield* FiberSet.run(set, Effect.succeed("hello")) const fiber2 = yield* FiberSet.run(set, Effect.succeed("world"))
// Get results return [yield* Fiber.join(fiber1), yield* Fiber.join(fiber2)]})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => ["hello", "world"]Captures a Runtime and uses it to fork effects into the FiberSet.
Signature
declare const runtime: <A, E>(self: FiberSet<A, E>) => <R = never>() => Effect.Effect<<XE extends E, XA extends A>(effect: Effect.Effect<XA, XE, R>, options?: Effect.RunOptions & { readonly propagateInterruption?: boolean;}) => Fiber.Fiber<XA, XE>, never, R>Example
(Capturing a runtime)
import { Context, Effect, Fiber, FiberSet } from "effect"
class Users extends Context.Service<Users, { readonly getAll: Effect.Effect<Array<unknown>>}>()("Users") {}
const program = Effect.gen(function*() { const set = yield* FiberSet.make() const run = yield* FiberSet.runtime(set)<Users>()
// run some effects and add the fibers to the set const fiber = run(Effect.andThen(Users, (_) => _.getAll)) return (yield* Fiber.join(fiber)).length}).pipe( Effect.scoped // The fibers will be interrupted when the scope is closed)
const actual = await Effect.runPromise(Effect.provideService(program, Users, { getAll: Effect.succeed([])}))actual // => 0runtimePromise
Captures a Runtime and returns a Promise-based runner that forks effects
into the FiberSet.
When to use
Use when you need to bridge effects to Promise values while still tracking
their fibers in a FiberSet.
Details
The returned run function returns a Promise for each effect result.
See
- runtime for a runner that returns the forked
Fiber
Signature
declare function runtimePromise<A, E>(self: FiberSet<A, E>): <R = never>() => Effect<<XE, XA>(effect: Effect<XA, XE, R>, options?: RunOptions & { readonly propagateInterruption?: boolean;}) => Promise<XA>, never, R>Example
(Running effects as promises)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make() const runPromise = yield* FiberSet.runtimePromise(set)()
// Run effects as promises const promise1 = runPromise(Effect.succeed("hello")) const promise2 = runPromise(Effect.succeed("world"))
return [yield* Effect.promise(() => promise1), yield* Effect.promise(() => promise2)]})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => ["hello", "world"]Gets the number of fibers currently in the FiberSet.
Signature
declare function size<A, E>(self: FiberSet<A, E>): Effect<number>Example
(Checking the set size)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make()
const sizeBefore = yield* FiberSet.size(set)
// Add some fibers yield* FiberSet.run(set, Effect.never) yield* FiberSet.run(set, Effect.never)
return [sizeBefore, yield* FiberSet.size(set)]})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => [0, 2]Constructors
Creates a scoped FiberSet for storing fibers.
Details
When the associated Scope is closed, all fibers in the set will be
interrupted. You can add fibers to the set using FiberSet.add or
FiberSet.run, and the fibers will be automatically removed from the
FiberSet when they complete.
Signature
declare function make<A = unknown, E = unknown>(): Effect<FiberSet<A, E>, never, Scope>Example
(Creating a scoped FiberSet)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make()
// run some effects and add the fibers to the set yield* FiberSet.run(set, Effect.never) yield* FiberSet.run(set, Effect.never)
yield* Effect.yieldNow return yield* FiberSet.size(set)}).pipe( Effect.scoped // The fibers will be interrupted when the scope is closed)
const actual = await Effect.runPromise(program)actual // => 2makeRuntime
Creates a scoped run function that forks effects into a new FiberSet.
Details
Each call returns the forked fiber and adds it to the set. Managed fibers are removed when they complete and are interrupted when the set's scope closes.
Signature
declare function makeRuntime<R = never, A = unknown, E = unknown>(): Effect<<XE, XA>(effect: Effect<XA, XE, R>, options?: RunOptions & { readonly propagateInterruption?: boolean;}) => Fiber<XA, XE>, never, Scope | R>Example
(Creating a scoped runtime)
import { Effect, Fiber, FiberSet } from "effect"
const program = Effect.gen(function*() { const runFork = yield* FiberSet.makeRuntime()
// Fork effects using the runtime const fiber1 = runFork(Effect.succeed("hello")) const fiber2 = runFork(Effect.succeed("world"))
return [yield* Fiber.join(fiber1), yield* Fiber.join(fiber2)]})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => ["hello", "world"]makeRuntimePromise
Creates a scoped run function that forks effects into a new FiberSet and
returns a Promise for each effect result.
When to use
Use when many scoped fibers should be tracked as a set while exposing each result through Promise-based APIs.
Details
Managed fibers are removed when they complete and are interrupted when the set's scope closes. Each Promise resolves with the effect's success value or rejects with the squashed failure cause.
Signature
declare function makeRuntimePromise<R = never, A = unknown, E = unknown>(): Effect<<XE, XA>(effect: Effect<XA, XE, R>, options?: RunOptions & { readonly propagateInterruption?: boolean;}) => Promise<XA>, never, Scope | R>Example
(Creating a promise runtime)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const runPromise = yield* FiberSet.makeRuntimePromise()
// Run effects as promises const promise1 = runPromise(Effect.succeed("hello")) const promise2 = runPromise(Effect.succeed("world"))
return [yield* Effect.promise(() => promise1), yield* Effect.promise(() => promise2)]})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => ["hello", "world"]Guards
isFiberSet
Checks whether a value is a FiberSet.
Signature
declare function isFiberSet(u: unknown): u is FiberSet<unknown, unknown>Example
(Checking if a value is a FiberSet)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make()
return [FiberSet.isFiberSet(set), FiberSet.isFiberSet({})]})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => [true, false]Models
A FiberSet is a collection of fibers that can be managed together. When the associated Scope is closed, all fibers in the set will be interrupted.
Signature
interface FiberSet<out A = unknown, out E = unknown> extends Pipeable, Inspectable, "/home/runner/work/website/website/.effect-source-v4/packages/effect/src/Iterable"<Fiber.Fiber<A, E>> { readonly "~effect/FiberSet": "~effect/FiberSet"; readonly deferred: Deferred<void, unknown>; state: { readonly _tag: "Open"; readonly backing: Set<Fiber<A, E>>; } | { readonly _tag: "Closed"; };}Example
(Managing fibers in a set)
import { Effect, FiberSet } from "effect"
const program = Effect.gen(function*() { const set = yield* FiberSet.make<string, string>()
// Add fibers to the set yield* FiberSet.run(set, Effect.succeed("hello")) yield* FiberSet.run(set, Effect.succeed("world"))
// Wait for all fibers to complete yield* FiberSet.awaitEmpty(set) return yield* FiberSet.size(set)})
const actual = await Effect.runPromise(Effect.scoped(program))actual // => 0