Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

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.

14 exports Since v2.0.0 Source

Combinators

Since v2.0.0

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 // => 1

Adds 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 // => 1

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 // => 0
Since v2.0.0

Interrupts 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]
Since v2.0.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")
Since v2.0.0

Forks an Effect and adds the fiber to the FiberSet. The fiber is removed when it completes. Set startImmediately: false to defer startup. By default, the effect starts immediately.

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"]
Since v2.0.0

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 // => 0

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"]
Since v2.0.0

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

Since v2.0.0

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 // => 2

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"]

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

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

FiberSet

interface
Since v2.0.0

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