Skip to content

Supervisor

A Supervisor<A> is a tool that manages the creation and termination of fibers, producing some visible value of type A based on its supervision.

To create a supervisor, you can use the Supervisor.track function. It generates a new supervisor that keeps track of its child fibers in a set.

Whenever you need to supervise an effect, you can employ the Effect.supervised function. This function takes a supervisor and returns an effect that behaves the same as the original effect. However, all child fibers forked within this effect are reported to the specified supervisor.

By doing this, you associate the behavior of child fibers with the provided supervisor, giving you access to all the information about these child fibers through the supervisor.

In the following example, we will periodically monitor the number of fibers throughout our application’s lifecycle:

1
import {
import Effect
Effect
,
import Supervisor
Supervisor
,
import Schedule
Schedule
,
import Fiber
Fiber
,
import FiberStatus
FiberStatus
} from "effect"
2
3
const
const program: Effect.Effect<void, never, never>
program
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>, never, never>> | YieldWrap<Effect.Effect<Fiber.RuntimeFiber<number, never>, never, never>> | YieldWrap<...>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
4
const
const supervisor: Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>
supervisor
= yield*
import Supervisor
Supervisor
.
const track: Effect.Effect<Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>, never, never>

Creates a new supervisor that tracks children in a set.

track
5
const
const fibFiber: Fiber.RuntimeFiber<number, never>
fibFiber
= yield*
const fib: (n: number) => Effect.Effect<number>
fib
(20).
(method) Pipeable.pipe<Effect.Effect<number, never, never>, Effect.Effect<number, never, never>, Effect.Effect<Fiber.RuntimeFiber<number, never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
6
import Effect
Effect
.
const supervised: <Fiber.RuntimeFiber<any, any>[]>(supervisor: Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Returns an effect with the behavior of this one, but where all child fibers forked in the effect are reported to the specified supervisor.

supervised
(
const supervisor: Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>
supervisor
),
7
import Effect
Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect. You can use the `fork` method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as `raceWith`, `zipPar`, and so forth. The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See `Fiber` for more information. Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the `forkDaemon` or `forkIn` methods.

fork
8
)
9
const
const policy: Schedule.Schedule<number, unknown, never>
policy
=
import Schedule
Schedule
.
const spaced: (duration: DurationInput) => Schedule.Schedule<number>

Returns a schedule that recurs continuously, each repetition spaced the specified duration from the last run.

spaced
("500 millis").
(method) Pipeable.pipe<Schedule.Schedule<number, unknown, never>, Schedule.Schedule<number, unknown, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<number, unknown, never>) => Schedule.Schedule<number, unknown, never>): Schedule.Schedule<...> (+21 overloads)
pipe
(
10
import Schedule
Schedule
.
const whileInputEffect: <unknown, never>(f: (input: unknown) => Effect.Effect<boolean, never, never>) => <Out, R>(self: Schedule.Schedule<Out, unknown, R>) => Schedule.Schedule<Out, unknown, R> (+1 overload)

Returns a new schedule that continues for as long as the specified effectful predicate on the input evaluates to true.

whileInputEffect
((
(parameter) _: unknown
_
) =>
11
import Fiber
Fiber
.
const status: <number, never>(self: Fiber.RuntimeFiber<number, never>) => Effect.Effect<FiberStatus.FiberStatus>

Returns the `FiberStatus` of a `RuntimeFiber`.

status
(
const fibFiber: Fiber.RuntimeFiber<number, never>
fibFiber
).
(method) Pipeable.pipe<Effect.Effect<FiberStatus.FiberStatus, never, never>, Effect.Effect<boolean, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<FiberStatus.FiberStatus, never, never>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
12
import Effect
Effect
.
const andThen: <FiberStatus.FiberStatus, boolean>(f: (a: FiberStatus.FiberStatus) => boolean) => <E, R>(self: Effect.Effect<FiberStatus.FiberStatus, E, R>) => Effect.Effect<...> (+3 overloads)

Executes a sequence of two actions, typically two `Effect`s, where the second action can depend on the result of the first action. The `that` action can take various forms: - a value - a function returning a value - a promise - a function returning a promise - an effect - a function returning an effect

andThen
((
(parameter) status: FiberStatus.FiberStatus
status
) =>
(parameter) status: FiberStatus.FiberStatus
status
!==
import FiberStatus
FiberStatus
.
const done: FiberStatus.FiberStatus
done
)
13
)
14
)
15
)
16
const
const monitorFiber: Fiber.RuntimeFiber<number, never>
monitorFiber
= yield*
const monitorFibers: (supervisor: Supervisor.Supervisor<Array<Fiber.RuntimeFiber<any, any>>>) => Effect.Effect<void>
monitorFibers
(
const supervisor: Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>
supervisor
).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<number, never, never>, Effect.Effect<Fiber.RuntimeFiber<number, never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
17
import Effect
Effect
.
const repeat: <number, unknown, never>(schedule: Schedule.Schedule<number, unknown, never>) => <E, R>(self: Effect.Effect<unknown, E, R>) => Effect.Effect<number, E, R> (+3 overloads)

The `repeat` function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so `Effect.repeat(action, Schedule.once)` executes `action` once initially, and if it succeeds, repeats it an additional time.

repeat
(
const policy: Schedule.Schedule<number, unknown, never>
policy
),
18
import Effect
Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect. You can use the `fork` method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as `raceWith`, `zipPar`, and so forth. The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See `Fiber` for more information. Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the `forkDaemon` or `forkIn` methods.

fork
19
)
20
yield*
import Fiber
Fiber
.
const join: <number, never>(self: Fiber.Fiber<number, never>) => Effect.Effect<number, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

join
(
const monitorFiber: Fiber.RuntimeFiber<number, never>
monitorFiber
)
21
const
const result: number
result
= yield*
import Fiber
Fiber
.
const join: <number, never>(self: Fiber.Fiber<number, never>) => Effect.Effect<number, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

join
(
const fibFiber: Fiber.RuntimeFiber<number, never>
fibFiber
)
22
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(`fibonacci result: ${
const result: number
result
}`)
23
})
24
25
const
const monitorFibers: (supervisor: Supervisor.Supervisor<Array<Fiber.RuntimeFiber<any, any>>>) => Effect.Effect<void>
monitorFibers
= (
26
(parameter) supervisor: Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>
supervisor
:
import Supervisor
Supervisor
.
interface Supervisor<out T> namespace Supervisor
Supervisor
<
interface Array<T>
Array
<
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

RuntimeFiber
<any, any>>>
27
):
import Effect
Effect
.
interface Effect<out A, out E = never, out R = never> namespace Effect

The `Effect` interface defines a value that lazily describes a workflow or job. The workflow requires some context `R`, and may fail with an error of type `E`, or succeed with a value of type `A`. `Effect` values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability. To run an `Effect` value, you need a `Runtime`, which is a type that is capable of executing `Effect` values.

Effect
<void> =>
28
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<Fiber.RuntimeFiber<any, any>[], never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Fiber.RuntimeFiber<any, any>[], never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
29
const
const fibers: Fiber.RuntimeFiber<any, any>[]
fibers
= yield*
(parameter) supervisor: Supervisor.Supervisor<Fiber.RuntimeFiber<any, any>[]>
supervisor
.
(property) Supervisor<RuntimeFiber<any, any>[]>.value: Effect.Effect<Fiber.RuntimeFiber<any, any>[], never, never>

Returns an `Effect` that succeeds with the value produced by this supervisor. This value may change over time, reflecting what the supervisor produces as it supervises fibers.

value
30
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(`number of fibers: ${
const fibers: Fiber.RuntimeFiber<any, any>[]
fibers
.
(property) Array<RuntimeFiber<any, any>>.length: number

Gets or sets the length of the array. This is a number one higher than the highest index in the array.

length
}`)
31
})
32
33
const
const fib: (n: number) => Effect.Effect<number>
fib
= (
(parameter) n: number
n
: number):
import Effect
Effect
.
interface Effect<out A, out E = never, out R = never> namespace Effect

The `Effect` interface defines a value that lazily describes a workflow or job. The workflow requires some context `R`, and may fail with an error of type `E`, or succeed with a value of type `A`. `Effect` values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability. To run an `Effect` value, you need a `Runtime`, which is a type that is capable of executing `Effect` values.

Effect
<number> =>
34
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, number, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
35
if (
(parameter) n: number
n
<= 1) {
36
return 1
37
}
38
yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("500 millis")
39
const
const fiber1: Fiber.RuntimeFiber<number, never>
fiber1
= yield*
import Effect
Effect
.
const fork: <number, never, never>(self: Effect.Effect<number, never, never>) => Effect.Effect<Fiber.RuntimeFiber<number, never>, never, never>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect. You can use the `fork` method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as `raceWith`, `zipPar`, and so forth. The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See `Fiber` for more information. Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the `forkDaemon` or `forkIn` methods.

fork
(
const fib: (n: number) => Effect.Effect<number>
fib
(
(parameter) n: number
n
- 2))
40
const
const fiber2: Fiber.RuntimeFiber<number, never>
fiber2
= yield*
import Effect
Effect
.
const fork: <number, never, never>(self: Effect.Effect<number, never, never>) => Effect.Effect<Fiber.RuntimeFiber<number, never>, never, never>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect. You can use the `fork` method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as `raceWith`, `zipPar`, and so forth. The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See `Fiber` for more information. Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the `forkDaemon` or `forkIn` methods.

fork
(
const fib: (n: number) => Effect.Effect<number>
fib
(
(parameter) n: number
n
- 1))
41
const
const v1: number
v1
= yield*
import Fiber
Fiber
.
const join: <number, never>(self: Fiber.Fiber<number, never>) => Effect.Effect<number, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

join
(
const fiber1: Fiber.RuntimeFiber<number, never>
fiber1
)
42
const
const v2: number
v2
= yield*
import Fiber
Fiber
.
const join: <number, never>(self: Fiber.Fiber<number, never>) => Effect.Effect<number, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

join
(
const fiber2: Fiber.RuntimeFiber<number, never>
fiber2
)
43
return
const v1: number
v1
+
const v2: number
v2
44
})
45
46
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
47
/*
48
Output:
49
number of fibers: 0
50
number of fibers: 2
51
number of fibers: 6
52
number of fibers: 14
53
number of fibers: 30
54
number of fibers: 62
55
number of fibers: 126
56
number of fibers: 254
57
number of fibers: 510
58
number of fibers: 1022
59
number of fibers: 2034
60
number of fibers: 3795
61
number of fibers: 5810
62
number of fibers: 6474
63
number of fibers: 4942
64
number of fibers: 2515
65
number of fibers: 832
66
number of fibers: 170
67
number of fibers: 18
68
number of fibers: 0
69
fibonacci result: 10946
70
*/