Run a listen layer until Node.shutdown (or scope interrupt).
Prefer this over bare Layer.launch for nodes that should exit on shutdown.
Installs a latch keyed by node.key that status shutdown signals after
membership leave.
export const const launch: <E, R>(
node: AnyNode,
layer: Layer.Layer<never, E, R>
) => Effect.Effect<void, E, R>
Run a listen layer until
Node.shutdown
(or scope interrupt).
Prefer this over bare Layer.launch for nodes that should exit on shutdown.
Installs a latch keyed by node.key that status shutdown signals after
membership leave.
launch = <function (type parameter) E in <E, R>(node: AnyNode, layer: Layer.Layer<never, E, R>): Effect.Effect<void, E, R>E, function (type parameter) R in <E, R>(node: AnyNode, layer: Layer.Layer<never, E, R>): Effect.Effect<void, E, R>R>(
node: AnyNodenode: type AnyNode = NodeKey<unknown> & {
readonly url: string | undefined;
readonly path: string | undefined;
readonly kind: ProtocolKind | undefined;
readonly endpoints?: Endpoints;
readonly onConflict?: OnConflict;
readonly [portSym]?: number;
}
A
Tag
erased — its transport endpoints set, plus the primary address
(url and/or Unix path) and
ProtocolKind
kind (the first-declared endpoint, kept for
single-protocol readers), so a tag's distributed set is self-describing about where AND how to
reach each one.
AnyNode,
layer: Layer.Layer<never, E, R>(parameter) layer: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<never>, E, R>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
layer: import LayerLayer.interface Layer<in ROut, out E = never, out RIn = never>A Layer describes how to build one or more services for dependency injection.
When to use
Use to model construction of application services for dependency injection,
especially when services have dependencies, can fail during construction, or
need scoped setup and release.
Details
A Layer<ROut, E, RIn> represents ROut as the services this layer
provides, E as the possible errors during layer construction, and RIn as
the services this layer requires as dependencies.
Layer<never, function (type parameter) E in <E, R>(node: AnyNode, layer: Layer.Layer<never, E, R>): Effect.Effect<void, E, R>E, function (type parameter) R in <E, R>(node: AnyNode, layer: Layer.Layer<never, E, R>): Effect.Effect<void, E, R>R>,
): import EffectEffect.interface Effect<out A, out E = never, out R = never>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.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
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, function (type parameter) E in <E, R>(node: AnyNode, layer: Layer.Layer<never, E, R>): Effect.Effect<void, E, R>E, function (type parameter) R in <E, R>(node: AnyNode, layer: Layer.Layer<never, E, R>): Effect.Effect<void, E, R>R> =>
import EffectEffect.const gen: {
<Eff extends Effect<any, any, any>, AEff>(
f: () => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
<Self, Eff extends Effect<any, any, any>, AEff>(
options: { readonly self: Self },
f: (this: Self) => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
}
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Example (Sequencing effects with generators)
import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
gen(function* () {
const const gate: Deferred.Deferred<void, never>const gate: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
gate = yield* import DeferredDeferred.const make: <A, E = never>() => Effect<
Deferred<A, E>
>
Creates a new Deferred.
When to use
Use to allocate an empty Deferred inside an Effect workflow.
Example (Creating a Deferred)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() {
const deferred = yield* Deferred.make<number>()
yield* Deferred.succeed(deferred, 42)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})
make<void>();
yield* import listenExitlistenExit.const install: (
nodeKey: string,
gate: Deferred.Deferred<void, never>
) => Effect.Effect<void>
Install a latch for nodeKey before
Node.launch
builds the listen layer.
install(node: AnyNodenode.Key<unknown, NodeProtocol>.key: stringkey, const gate: Deferred.Deferred<void, never>const gate: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
gate);
yield* import EffectEffect.const addFinalizer: <R>(
finalizer: (
exit: Exit.Exit<unknown, unknown>
) => Effect<void, never, R>
) => Effect<void, never, R | Scope>
Adds a finalizer to the current scope.
When to use
Use to register low-level cleanup in the current scope.
Details
The finalizer runs when the surrounding scope is closed and receives the
Exit value used to close the scope.
Example (Registering scope finalizers)
import { Console, Effect, Exit } from "effect"
const program = Effect.scoped(
Effect.gen(function*() {
// Add a finalizer that runs when the scope closes
yield* Effect.addFinalizer((exit) =>
Console.log(
Exit.isSuccess(exit)
? "Cleanup: Operation completed successfully"
: "Cleanup: Operation failed, cleaning up resources"
)
)
yield* Console.log("Performing main operation...")
// This could succeed or fail
return "operation result"
})
)
Effect.runPromise(program).then(console.log)
// Output:
// Performing main operation...
// Cleanup: Operation completed successfully
// operation result
addFinalizer(() => import listenExitlistenExit.const uninstall: (
nodeKey: string
) => Effect.Effect<void>
Drop the latch (launch finalizer).
uninstall(node: AnyNodenode.Key<unknown, NodeProtocol>.key: stringkey));
yield* import EffectEffect.const raceFirst: {
<A2, E2, R2>(
that: Effect<A2, E2, R2>,
options?: {
readonly onWinner?: (options: {
readonly fiber: Fiber<any, any>
readonly index: number
readonly parentFiber: Fiber<any, any>
}) => void
}
): <A, E, R>(
self: Effect<A, E, R>
) => Effect<A | A2, E | E2, R | R2>
<A, E, R, A2, E2, R2>(
self: Effect<A, E, R>,
that: Effect<A2, E2, R2>,
options?: {
readonly onWinner?: (options: {
readonly fiber: Fiber<any, any>
readonly index: number
readonly parentFiber: Fiber<any, any>
}) => void
}
): Effect<A | A2, E | E2, R | R2>
}
Races two effects and returns the result of the first one to complete, whether
it succeeds or fails.
When to use
Use when any completion, including failure, should decide the race and
interrupt the losing effect.
Details
The losing effect is interrupted, and onWinner can observe the winning fiber.
Example (Observing the winning fiber)
import { Console, Duration, Effect } from "effect"
const fastFail = Effect.delay(Effect.fail("fast-fail"), Duration.millis(10))
const slowSuccess = Effect.delay(Effect.succeed("slow-success"), Duration.millis(50))
const program = Effect.gen(function*() {
const message = yield* Effect.match(Effect.raceFirst(fastFail, slowSuccess), {
onFailure: (error) => `failed: ${error}`,
onSuccess: (value) => `succeeded: ${value}`
})
yield* Console.log(message)
})
Effect.runPromise(program)
// Output: failed: fast-fail
raceFirst(
import LayerLayer.const launch: <RIn, E, ROut>(
self: Layer<ROut, E, RIn>
) => Effect<never, E, RIn>
Builds this layer and keeps it alive until the returned effect is interrupted.
When to use
Use when you model your entire application as a layer, such as an HTTP
server.
Details
When the returned effect is interrupted, the layer scope is closed and all
finalizers registered during layer acquisition are run.
Example (Launching an application layer)
import { Console, Context, Effect, Layer } from "effect"
class HttpServer extends Context.Service<HttpServer, {
readonly start: () => Effect.Effect<string>
readonly stop: () => Effect.Effect<string>
}>()("HttpServer") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
// Server layer that starts an HTTP server
const serverLayer = Layer.effect(HttpServer, Effect.gen(function*() {
yield* Console.log("Starting HTTP server...")
return {
start: Effect.fn("HttpServer.start")(function*() {
yield* Console.log("Server listening on port 3000")
return "Server started"
}),
stop: Effect.fn("HttpServer.stop")(function*() {
yield* Console.log("Server stopped gracefully")
return "Server stopped"
})
}
}))
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Console.log(`[LOG] ${msg}`))
})
// Application layer combining all services
const appLayer = Layer.mergeAll(serverLayer, loggerLayer)
// Launch the application - runs until interrupted
const application = appLayer.pipe(
Layer.launch,
Effect.tapError((error) => Console.log(`Application failed: ${error}`)),
Effect.tap(() => Console.log("Application completed"))
)
// This will run forever until externally interrupted
// Effect.runFork(application)
launch(layer: Layer.Layer<never, E, R>(parameter) layer: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<never>, E, R>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
layer),
import DeferredDeferred.await<A, E>(self: Deferred<A, E>): Effect<A, E>Retrieves the value of the Deferred, suspending the fiber running the
workflow until the result is available.
When to use
Use to wait for a Deferred to be completed and resume with its success,
failure, defect, or interruption.
Details
Awaiters observe the completion effect stored in the Deferred.
Example (Awaiting a Deferred value)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() {
const deferred = yield* Deferred.make<number>()
yield* Deferred.succeed(deferred, 42)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})
await(const gate: Deferred.Deferred<void, never>const gate: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
gate),
);
}).Pipeable.pipe<Effect.Effect<void, E, R | Scope>, Effect.Effect<void, E, Exclude<R, Scope>>, Effect.Effect<void, E, Exclude<R, Scope>>>(this: Effect.Effect<void, E, R | Scope>, ab: (_: Effect.Effect<void, E, R | Scope>) => Effect.Effect<void, E, Exclude<R, Scope>>, bc: (_: Effect.Effect<void, E, Exclude<R, Scope>>) => Effect.Effect<void, E, Exclude<R, Scope>>): Effect.Effect<...> (+21 overloads)pipe(import EffectEffect.const scoped: <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E, Exclude<R, Scope>>
Runs an effect with a scope that closes when the effect completes.
When to use
Use to acquire scoped resources for the duration of a single workflow.
Details
Finalizers for resources acquired inside the workflow run as soon as the
workflow completes, whether by success, failure, or interruption.
Example (Running a scoped acquisition)
import { Console, Effect } from "effect"
const resource = Effect.acquireRelease(
Console.log("Acquiring resource").pipe(Effect.as("resource")),
() => Console.log("Releasing resource")
)
const program = Effect.scoped(
Effect.gen(function*() {
const res = yield* resource
yield* Console.log(`Using ${res}`)
return res
})
)
Effect.runFork(program)
// Output: "Acquiring resource"
// Output: "Using resource"
// Output: "Releasing resource"
scoped, import EffectEffect.const asVoid: <A, E, R>(
self: Effect<A, E, R>
) => Effect<void, E, R>
Maps the success value of an Effect to void, preserving failures.
Example (Discarding success values)
import { Effect } from "effect"
const program = Effect.asVoid(Effect.succeed(42))
Effect.runPromise(program).then(console.log)
// undefined (void)
asVoid);