<
I,
E,
R,
X,
const Preload extends boolean = never,
SE = never,
SR = never
>(
layer: Layer.Layer<I, E, R>,
options?:
| {
readonly idleTimeToLive?: Duration.Input | undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
): Effect.Effect<
LayerRef<I, E>,
[Preload] extends [true] ? E : never,
Scope.Scope | R | SR
>Creates a LayerRef from a Layer.
When to use
Use when you have one layer-built resource that should be shared, optionally kept alive while idle, and refreshed on demand.
Details
The layer is built lazily on first use unless preload is true.
idleTimeToLive keeps the context cached after it stops being used, and
invalidationSchedule can periodically invalidate it. When preload is
true, scheduled invalidation also reacquires the context.
Gotchas
Invalidation does not revoke contexts already borrowed by active scopes; those contexts remain usable until their scopes close.
Example (Sharing one layer-built service)
import { Context, Effect, Layer, LayerRef } from "effect"
class Database extends Context.Service<Database, {
readonly query: Effect.Effect<string>
}>()("Database") {}
const databaseLayer = Layer.succeed(Database, {
query: Effect.succeed("result")
})
const query = Effect.gen(function*() {
const database = yield* Database
return yield* database.query
})
const program = Effect.scoped(
Effect.gen(function*() {
const ref = yield* LayerRef.make(databaseLayer, {
idleTimeToLive: "5 seconds"
})
const result = yield* Effect.provide(query, ref.get)
yield* ref.invalidate
return result
})
)export const const make: <
I,
E,
R,
X,
Preload extends boolean = never,
SE = never,
SR = never
>(
layer: Layer.Layer<I, E, R>,
options?:
| {
readonly idleTimeToLive?:
| Duration.Input
| undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
) => Effect.Effect<
LayerRef<I, E>,
[Preload] extends [true] ? E : never,
Scope.Scope | R | SR
>
Creates a LayerRef from a Layer.
When to use
Use when you have one layer-built resource that should be shared, optionally
kept alive while idle, and refreshed on demand.
Details
The layer is built lazily on first use unless preload is true.
idleTimeToLive keeps the context cached after it stops being used, and
invalidationSchedule can periodically invalidate it. When preload is
true, scheduled invalidation also reacquires the context.
Gotchas
Invalidation does not revoke contexts already borrowed by active scopes; those
contexts remain usable until their scopes close.
Example (Sharing one layer-built service)
import { Context, Effect, Layer, LayerRef } from "effect"
class Database extends Context.Service<Database, {
readonly query: Effect.Effect<string>
}>()("Database") {}
const databaseLayer = Layer.succeed(Database, {
query: Effect.succeed("result")
})
const query = Effect.gen(function*() {
const database = yield* Database
return yield* database.query
})
const program = Effect.scoped(
Effect.gen(function*() {
const ref = yield* LayerRef.make(databaseLayer, {
idleTimeToLive: "5 seconds"
})
const result = yield* Effect.provide(query, ref.get)
yield* ref.invalidate
return result
})
)
make = import EffectEffect.fnUntraced(
function*<function (type parameter) I in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
I, function (type parameter) E in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
E, function (type parameter) R in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
R, function (type parameter) X in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
X, const function (type parameter) Preload in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
Preload extends boolean = never, function (type parameter) SE in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
SE = never, function (type parameter) SR in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
SR = never>(
layer: Layer.Layer<I, E, R>(parameter) layer: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<I>, 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.type Layer.Layer = /*unresolved*/ anyLayer<function (type parameter) I in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
I, function (type parameter) E in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
E, function (type parameter) R in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
R>,
options: | {
readonly idleTimeToLive?:
| Duration.Input
| undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
options?: {
/**
* Duration to keep the resource alive after it is no longer used.
*/
readonly idleTimeToLive?: Duration.Input | undefinedDuration to keep the resource alive after it is no longer used.
idleTimeToLive?: import DurationDuration.type Duration.Input = /*unresolved*/ anyInput | undefined
/**
* Whether to acquire the resource during creation.
*/
readonly preload?: Preload | undefinedWhether to acquire the resource during creation.
preload?: function (type parameter) Preload in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
Preload | undefined
/**
* Schedule used to invalidate the cached resource. When `preload` is
* `true`, each scheduled invalidation also reacquires the resource.
*/
readonly invalidationSchedule?: | Schedule.Schedule<X, unknown, SE, SR>
| undefined
Schedule used to invalidate the cached resource. When preload is
true, each scheduled invalidation also reacquires the resource.
invalidationSchedule?: import ScheduleSchedule.interface Schedule<out Output, in Input = unknown, out Error = never, out Env = never>A Schedule defines a strategy for repeating or retrying effects based on some policy.
Example (Defining retry and repeat schedules)
import { Console, Data, Effect, Schedule } from "effect"
class NetworkError extends Data.TaggedError("NetworkError")<{
readonly attempt: number
}> {}
// Basic retry schedule - retry up to 3 times with exponential backoff
const retrySchedule = Schedule.max([
Schedule.exponential("100 millis"),
Schedule.recurs(3)
])
// Basic repeat schedule - repeat every 30 seconds forever
const repeatSchedule: Schedule.Schedule<number, unknown, never> = Schedule
.spaced("30 seconds")
const program = Effect.gen(function*() {
let attempts = 0
const result1 = yield* Effect.retry(
Effect.gen(function*() {
attempts++
if (attempts < 3) {
return yield* Effect.fail(new NetworkError({ attempt: attempts }))
}
return "Success"
}),
retrySchedule
)
console.log(result1) // "Success"
yield* Console.log("heartbeat").pipe(
Effect.repeat(repeatSchedule.pipe(Schedule.upTo({ times: 5 })))
)
})
The Schedule namespace contains types and utilities for working with schedules.
Schedule<function (type parameter) X in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
X, unknown, function (type parameter) SE in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
SE, function (type parameter) SR in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
SR> | undefined
} | undefined
): import EffectEffect.declarefn.type Effect.fn.Return = /*unresolved*/ anyReturn<
interface LayerRef<in out I, in out E = never>A refreshable reference to a single layer-built service context.
When to use
Use when you want to share one scoped layer resource across many users while
retaining the ability to invalidate it and rebuild it later.
Details
A LayerRef is the unkeyed counterpart to a layer cache: it lazily builds the
layer on first use, reuses the resulting context while it is borrowed or kept
idle, and can invalidate the cached context so the next use rebuilds it.
LayerRef<function (type parameter) I in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
I, function (type parameter) E in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
E>,
[function (type parameter) Preload in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
Preload] extends [true] ? function (type parameter) E in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
E : never,
import ScopeScope.Scope | function (type parameter) R in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
R | function (type parameter) SR in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
SR
> {
const const context: Context.Context<never>const context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
context = yield* import EffectEffect.context<never>()
const const memoMap: Layer.MemoMapconst memoMap: {
get: <RIn, E, ROut>(layer: Layer<ROut, E, RIn>, scope: Scope.Scope) => Effect<Context.Context<ROut>, E, RIn> | undefined;
getOrElseMemoize: <RIn, E, ROut>(layer: Layer<ROut, E, RIn>, scope: Scope.Scope, build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<ROut>, E, RIn>) => Effect<Context.Context<ROut>, E, RIn>;
}
memoMap = import LayerLayer.CurrentMemoMap.forkOrCreate(const context: Context.Context<never>const context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
context)
const const rcRef: RcRef.RcRef<
Context.Context<I>,
E
>
const rcRef: {
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; <…;
}
rcRef = yield* import RcRefRcRef.const make: <A, E, R>(options: {
readonly acquire: Effect.Effect<A, E, R>
readonly idleTimeToLive?:
| Duration.Input
| undefined
}) => Effect.Effect<RcRef<A, E>, never, R | Scope>
Creates an RcRef from an acquire effect.
When to use
Use to create a lazily acquired, reference-counted resource from an acquire
effect.
Details
The resource is acquired lazily on the first get and shared by subsequent
gets while it remains cached. Each get adds a reference to the current
Scope. When the last reference is released, the resource is closed
immediately by default, or after idleTimeToLive when that option is
provided.
Example (Creating a reference-counted resource)
import { Effect, RcRef } from "effect"
Effect.gen(function*() {
const ref = yield* RcRef.make({
acquire: Effect.acquireRelease(
Effect.succeed("foo"),
() => Effect.log("release foo")
)
})
// will only acquire the resource once, and release it
// when the scope is closed
yield* RcRef.get(ref).pipe(
Effect.andThen(RcRef.get(ref)),
Effect.scoped
)
})
make({
acquire: Effect.Effect<
Context.Context<I>,
E,
Scope.Scope | R
>
(property) acquire: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
acquire: import EffectEffect.contextWith((_: Context.Context<Scope.Scope>(parameter) _: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
_: import ContextContext.type Context.Context = /*unresolved*/ anyContext<import ScopeScope.Scope>) =>
import LayerLayer.buildWithMemoMap(layer: Layer.Layer<I, E, R>(parameter) layer: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<I>, 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, const memoMap: Layer.MemoMapconst memoMap: {
get: <RIn, E, ROut>(layer: Layer<ROut, E, RIn>, scope: Scope.Scope) => Effect<Context.Context<ROut>, E, RIn> | undefined;
getOrElseMemoize: <RIn, E, ROut>(layer: Layer<ROut, E, RIn>, scope: Scope.Scope, build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<ROut>, E, RIn>) => Effect<Context.Context<ROut>, E, RIn>;
}
memoMap, import ContextContext.get(_: Context.Context<Scope.Scope>(parameter) _: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
_, import ScopeScope.const Scope: Context.Service<Scope, Scope>const Scope: {
key: string;
Service: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
};
of: (this: void, self: Scope.Scope) => Scope.Scope;
context: (self: Scope.Scope) => Context.Context<Scope.Scope>;
use: (f: (service: Scope.Scope) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, Scope.Scope | R>;
useSync: (f: (service: Scope.Scope) => A) => Effect.Effect<A, never, Scope.Scope>;
Identifier: Identifier;
stack: string | 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; <…;
toString: () => string;
toJSON: () => unknown;
}
A Scope represents a context where resources can be acquired and
automatically cleaned up when the scope is closed. Scopes can use
either sequential or parallel finalization strategies.
Example (Managing scoped resources)
import { Effect, Exit, Scope } from "effect"
const program = Effect.gen(function*() {
const scope = yield* Scope.make("sequential")
// Scope has a strategy and state
console.log(scope.strategy) // "sequential"
console.log(scope.state._tag) // "Open"
// Close the scope
yield* Scope.close(scope, Exit.void)
console.log(scope.state._tag) // "Closed"
})
Service tag for the active resource lifetime.
When to use
Use to access the active lifetime when registering finalizers or sharing
resources with the surrounding scope.
Example (Accessing the scope service)
import { Effect, Scope } from "effect"
const program = Effect.gen(function*() {
// Access the scope from the context
const scope = yield* Scope.Scope
// Use the scope for resource management
yield* Scope.addFinalizer(scope, Effect.log("Cleanup"))
})
// Provide a scope to the program
const scoped = Effect.scoped(program)
Scope))
),
idleTimeToLive?: anyWhen the reference count reaches zero, the resource will be released
after this duration.
idleTimeToLive: options: | {
readonly idleTimeToLive?:
| Duration.Input
| undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
options?.idleTimeToLive?: Duration.Input | undefinedDuration to keep the resource alive after it is no longer used.
idleTimeToLive
})
const const refresh: Effect.Effect<
void,
E,
never
>
const refresh: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
refresh = import RcRefRcRef.const invalidate: <A, E>(
self: RcRef<A, E>
) => Effect.Effect<void>
Invalidates the currently cached resource, if one has been acquired.
When to use
Use to force future RcRef.get calls to acquire a fresh resource when the
currently cached resource should no longer be reused.
Details
After invalidation, the next get acquires a fresh resource.
Gotchas
Invalidation does not revoke resources already borrowed by active scopes;
those remain usable until their scopes close.
invalidate(const rcRef: RcRef.RcRef<
Context.Context<I>,
E
>
const rcRef: {
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; <…;
}
rcRef).pipe(
import EffectEffect.andThen(import EffectEffect.scoped(import RcRefRcRef.const get: <A, E>(
self: RcRef<A, E>
) => Effect.Effect<A, E, Scope>
Gets the value from an RcRef, acquiring it first if needed.
When to use
Use to borrow the current resource within a Scope, acquiring it first if
necessary.
Details
The reference count is incremented for the current Scope, and a release
finalizer is added to that scope. When the current scope closes, the
reference is released; the resource is closed when the final reference is
released, subject to any configured idle time-to-live.
Example (Sharing one acquired value)
import { Effect, RcRef } from "effect"
const program = Effect.gen(function*() {
// Create an RcRef with a resource
const ref = yield* RcRef.make({
acquire: Effect.acquireRelease(
Effect.succeed("shared resource"),
(resource) => Effect.log(`Releasing ${resource}`)
)
})
// Get the value from the RcRef
const value1 = yield* RcRef.get(ref)
const value2 = yield* RcRef.get(ref)
// Both values are the same instance
console.log(value1 === value2) // true
return value1
})
get(const rcRef: RcRef.RcRef<
Context.Context<I>,
E
>
const rcRef: {
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; <…;
}
rcRef))),
import EffectEffect.asVoid
)
if (options: | {
readonly idleTimeToLive?:
| Duration.Input
| undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
options?.preload?: Preload | undefinedWhether to acquire the resource during creation.
preload) {
yield* const refresh: Effect.Effect<
void,
E,
never
>
const refresh: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
refresh as import EffectEffect.type Effect.Effect = /*unresolved*/ anyEffect<void>
}
if (options: | {
readonly idleTimeToLive?:
| Duration.Input
| undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
options?.invalidationSchedule?: | Schedule.Schedule<X, unknown, SE, SR>
| undefined
Schedule used to invalidate the cached resource. When preload is
true, each scheduled invalidation also reacquires the resource.
invalidationSchedule) {
const const onRefresh: Effect.Effect<
void,
E,
never
>
const onRefresh: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
onRefresh = options: | {
readonly idleTimeToLive?:
| Duration.Input
| undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
options.preload?: Preload | undefinedWhether to acquire the resource during creation.
preload ? const refresh: Effect.Effect<
void,
E,
never
>
const refresh: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
refresh : import RcRefRcRef.const invalidate: <A, E>(
self: RcRef<A, E>
) => Effect.Effect<void>
Invalidates the currently cached resource, if one has been acquired.
When to use
Use to force future RcRef.get calls to acquire a fresh resource when the
currently cached resource should no longer be reused.
Details
After invalidation, the next get acquires a fresh resource.
Gotchas
Invalidation does not revoke resources already borrowed by active scopes;
those remain usable until their scopes close.
invalidate(const rcRef: RcRef.RcRef<
Context.Context<I>,
E
>
const rcRef: {
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; <…;
}
rcRef)
yield* const onRefresh: Effect.Effect<
void,
E,
never
>
const onRefresh: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
onRefresh.pipe(
import EffectEffect.ignoreCause,
import EffectEffect.schedule(options: | {
readonly idleTimeToLive?:
| Duration.Input
| undefined
readonly preload?: Preload | undefined
readonly invalidationSchedule?:
| Schedule.Schedule<X, unknown, SE, SR>
| undefined
}
| undefined
options.invalidationSchedule?: | Schedule.Schedule<X, unknown, SE, SR>
| undefined
(property) invalidationSchedule?: {
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; <…;
}
Schedule used to invalidate the cached resource. When preload is
true, each scheduled invalidation also reacquires the resource.
invalidationSchedule),
import EffectEffect.forkScoped
)
}
return import identityidentity<interface LayerRef<in out I, in out E = never>A refreshable reference to a single layer-built service context.
When to use
Use when you want to share one scoped layer resource across many users while
retaining the ability to invalidate it and rebuild it later.
Details
A LayerRef is the unkeyed counterpart to a layer cache: it lazily builds the
layer on first use, reuses the resulting context while it is borrowed or kept
idle, and can invalidate the cached context so the next use rebuilds it.
LayerRef<function (type parameter) I in <I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(layer: Layer.Layer<I, E, R>, options?: {
readonly idleTimeToLive?: Duration.Input | undefined;
readonly preload?: Preload | undefined;
readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined;
} | undefined): Effect.fn.Return<LayerRef<I, E>, [Preload] extends [true] ? E : never, Scope.Scope | R | SR>
I, any>>({
[const TypeId: "~effect/LayerRef"TypeId]: const TypeId: "~effect/LayerRef"TypeId,
rcRef: RcRef.RcRef<Context.Context<I>, E>(property) rcRef: {
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; <…;
}
rcRef,
get: Layer.Layer<I, E, never>(property) get: {
build: (memoMap: MemoMap, scope: Scope.Scope) => Effect<Context.Context<I>, E, never>;
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; <…;
}
get: import LayerLayer.effectContext(import RcRefRcRef.const get: <A, E>(
self: RcRef<A, E>
) => Effect.Effect<A, E, Scope>
Gets the value from an RcRef, acquiring it first if needed.
When to use
Use to borrow the current resource within a Scope, acquiring it first if
necessary.
Details
The reference count is incremented for the current Scope, and a release
finalizer is added to that scope. When the current scope closes, the
reference is released; the resource is closed when the final reference is
released, subject to any configured idle time-to-live.
Example (Sharing one acquired value)
import { Effect, RcRef } from "effect"
const program = Effect.gen(function*() {
// Create an RcRef with a resource
const ref = yield* RcRef.make({
acquire: Effect.acquireRelease(
Effect.succeed("shared resource"),
(resource) => Effect.log(`Releasing ${resource}`)
)
})
// Get the value from the RcRef
const value1 = yield* RcRef.get(ref)
const value2 = yield* RcRef.get(ref)
// Both values are the same instance
console.log(value1 === value2) // true
return value1
})
get(const rcRef: RcRef.RcRef<
Context.Context<I>,
E
>
const rcRef: {
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; <…;
}
rcRef)),
contextEffect: Effect.Effect<
Context.Context<I>,
E,
Scope.Scope
>
(property) contextEffect: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
contextEffect: import RcRefRcRef.const get: <A, E>(
self: RcRef<A, E>
) => Effect.Effect<A, E, Scope>
Gets the value from an RcRef, acquiring it first if needed.
When to use
Use to borrow the current resource within a Scope, acquiring it first if
necessary.
Details
The reference count is incremented for the current Scope, and a release
finalizer is added to that scope. When the current scope closes, the
reference is released; the resource is closed when the final reference is
released, subject to any configured idle time-to-live.
Example (Sharing one acquired value)
import { Effect, RcRef } from "effect"
const program = Effect.gen(function*() {
// Create an RcRef with a resource
const ref = yield* RcRef.make({
acquire: Effect.acquireRelease(
Effect.succeed("shared resource"),
(resource) => Effect.log(`Releasing ${resource}`)
)
})
// Get the value from the RcRef
const value1 = yield* RcRef.get(ref)
const value2 = yield* RcRef.get(ref)
// Both values are the same instance
console.log(value1 === value2) // true
return value1
})
get(const rcRef: RcRef.RcRef<
Context.Context<I>,
E
>
const rcRef: {
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; <…;
}
rcRef),
invalidate: Effect.Effect<void, never, never>(property) invalidate: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
invalidate: import RcRefRcRef.const invalidate: <A, E>(
self: RcRef<A, E>
) => Effect.Effect<void>
Invalidates the currently cached resource, if one has been acquired.
When to use
Use to force future RcRef.get calls to acquire a fresh resource when the
currently cached resource should no longer be reused.
Details
After invalidation, the next get acquires a fresh resource.
Gotchas
Invalidation does not revoke resources already borrowed by active scopes;
those remain usable until their scopes close.
invalidate(const rcRef: RcRef.RcRef<
Context.Context<I>,
E
>
const rcRef: {
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; <…;
}
rcRef),
refresh: Effect.Effect<void, E, never>(property) refresh: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
refresh
})
}
)