ScopedCache
Caches values that need scoped resource management.
Each cached entry owns its own Scope, so resources opened while creating a value stay alive while that entry is cached and are released when the entry is removed. A ScopedCache also belongs to an outer scope, which closes all remaining entries when the cache is closed. Lookups for the same missing key share one in-progress effect, and entries can expire, be refreshed, be invalidated, or be evicted by capacity limits.
Combinators
Signature
declare function entries<Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect<Array<[Key, A]>>;Gets the value for a key, running the cache lookup when no unexpired entry is present.
When to use
Use to retrieve a scoped cached value by key when a missing or expired entry should run the cache lookup and share the in-flight lookup with concurrent callers.
Details
Concurrent get calls for the same key share the same in-flight lookup. Successful and failed lookup exits are cached according to the configured TTL. If the cache is closed, the effect is interrupted.
See
getOptionfor reading only when an unexpired entry is already cachedgetSuccessfor inspecting an already-completed successful entryrefreshfor forcing a new lookup
Signature
declare const get: {
<Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect<A, E, R>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect<A, E, R>;
};Reads an existing unexpired cache entry without running the lookup function.
When to use
Use to read a scoped value only when it is already cached, without starting the lookup for missing or expired keys.
Details
Returns Option.none when the key is absent or expired. If an entry exists, the effect waits for its cached result and returns Option.some(value) on success, or fails with the cached lookup error.
See
getfor running the lookup on missing or expired keysgetSuccessfor inspecting only already-completed successful entries
Signature
declare const getOption: {
<Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect<Option<A>, E>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect<Option<A>, E>;
};getSuccess
Retrieves the value associated with the specified key from the cache, only if it contains a resolved successful value.
When to use
Use to inspect an already-completed successful scoped cache entry without running or awaiting the lookup effect.
Details
Returns Option.some for a resolved successful entry. Returns Option.none for missing, expired, failed, or still-pending entries.
See
Signature
declare const getSuccess: {
<Key, A, R>(key: Key): <E>(self: ScopedCache<Key, A, E, R>) => Effect<Option<A>>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect<Option<A>>;
};Checks whether the cache contains an entry for the specified key.
When to use
Use to test whether an unexpired entry exists for a key without running the cache lookup.
Details
This does not start lookups and does not refresh access order. Expired entries are treated as absent and their scopes are closed while checking. If the cache is closed, the effect is interrupted.
See
Signature
declare const has: {
<Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect<boolean>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect<boolean>;
};invalidate
Removes the entry associated with a key and closes its entry scope.
When to use
Use to remove a single key from a scoped cache and release any resources owned by that entry before a later lookup computes it again.
Details
If the key is absent, this is a no-op.
Gotchas
If the cache is closed, the effect is interrupted.
See
refreshfor replacing a key by running a new lookup immediatelyinvalidateWhenfor invalidating only when a cached value matches a predicateinvalidateAllfor removing every cached entry
Signature
declare const invalidate: {
<Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect<void>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect<void>;
};invalidateAll
Removes every entry from the cache and closes each entry scope.
When to use
Use to clear a scoped cache and release resources owned by all cached entries.
Details
If the cache is closed, the effect is interrupted.
See
invalidatefor removing one cached entry
Signature
declare function invalidateAll<Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect<void>;invalidateWhen
Invalidates the entry associated with the specified key in the cache when the predicate returns true for the cached value.
When to use
Use to remove an already-cached scoped value only when the successful cached value satisfies a predicate.
Details
Returns true only when a successful cached value matches and is removed. It returns false for absent, expired, failed, or non-matching entries.
Gotchas
A matching invalidation closes the entry scope and releases its resources.
See
invalidatefor unconditional removal by key
Signature
declare const invalidateWhen: {
<Key, A>(key: Key, f: Predicate<A>): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect<boolean>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key, f: Predicate<A>): Effect<boolean>;
};Retrieves all active keys from the cache, automatically filtering out expired entries.
When to use
Use to inspect currently cached unexpired keys without running cache lookups.
Gotchas
Expired entries are removed and their scopes are closed while filtering.
See
Signature
declare function keys<Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect<Array<Key>>;Forces a refresh of the value associated with the specified key in the cache.
When to use
Use to recompute a scoped cache entry immediately, even when an unexpired value is already cached.
Details
It will always invoke the lookup function to construct a new value, overwriting any existing value for that key.
See
getfor reusing an unexpired entry before running the lookupinvalidatefor removing an entry without recomputing it
Signature
declare const refresh: {
<Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect<A, E, R>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect<A, E, R>;
};Sets a successful value for a key without running the lookup function.
When to use
Use to seed or overwrite a scoped cache entry with an already available successful value.
Details
This replaces and closes any existing entry scope for the key, applies the cache's TTL using a successful exit for the value, and may evict older entries if the cache capacity is exceeded.
See
Signature
declare const set: {
<Key, A>(key: Key, value: A): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect<void>;
<Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key, value: A): Effect<void>;
};Retrieves the approximate number of entries in the cache.
When to use
Use to inspect how many entries are currently stored in the scoped cache.
Gotchas
Note that expired entries are counted until they are accessed and removed. The size reflects the current number of entries stored, not the number of valid entries.
Signature
declare function size<Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect<number>;Retrieves all successfully cached values from the cache, excluding failed lookups and expired entries.
When to use
Use to inspect currently successful cached values without running cache lookups.
Gotchas
Expired entries are removed and their scopes are closed while filtering.
See
Signature
declare function values<Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect<Array<A>>;Constructors
Creates a ScopedCache with a fixed time-to-live for every lookup result.
When to use
Use to create a scoped cache when every cached lookup result should share the same lifetime.
Details
This is the constant-TTL variant of makeWith: values are acquired by the lookup effect in per-entry scopes, capacity can evict older entries, and entry scopes are closed when entries expire, are invalidated, are evicted, or when the cache's owning scope closes.
See
makeWithfor computing time-to-live from each lookup result and key
Signature
declare function make<
Key,
A,
E = never,
R = never,
ServiceMode extends "lookup" | "construction" = never,
>(options: {
readonly capacity: number;
readonly lookup: (key: Key) => Effect<A, E, Scope | R>;
readonly requireServicesAt?: ServiceMode;
readonly timeToLive?: Input;
}): Effect<
ScopedCache<Key, A, E, "lookup" extends ServiceMode ? Exclude<R, Scope> : never>,
never,
Scope | "lookup" extends ServiceMode ? never : R
>;Creates a ScopedCache from a lookup function, maximum capacity, and a time-to-live function computed from each lookup exit and key.
When to use
Use when you need a scoped cache whose entry lifetime depends on each lookup result or key.
Details
The cache must be constructed in a Scope. Each lookup runs in its own entry scope, and that scope is closed when the entry expires, is invalidated, is evicted by capacity, or when the cache's owning scope closes. requireServicesAt controls whether lookup services are captured at construction time or required when lookup operations run.
See
makefor creating a scoped cache with one fixed time-to-live
Signature
declare function makeWith<
Key,
A,
E = never,
R = never,
ServiceMode extends "lookup" | "construction" = never,
>(options: {
readonly capacity: number;
readonly lookup: (key: Key) => Effect<A, E, Scope | R>;
readonly requireServicesAt?: ServiceMode;
readonly timeToLive?: (exit: Exit<A, E>, key: Key) => Input;
}): Effect<
ScopedCache<Key, A, E, "lookup" extends ServiceMode ? Exclude<R, Scope> : never>,
never,
Scope | "lookup" extends ServiceMode ? never : R
>;Models
A single scoped cache entry.
When to use
Use when inspecting the open state of a ScopedCache and you need the stored deferred result, entry scope, or expiration timestamp for a key.
Details
The entry contains the deferred lookup result shared by readers, the scope that owns resources acquired while computing the value, and an optional expiration time in milliseconds. Removing the entry closes its scope.
See
Statefor the open/closed cache state that stores entries by key
Signature
interface Entry<A, E> {
readonly deferred: Deferred<A, E>;
expiresAt: number | undefined;
readonly scope: Closeable;
}ScopedCache interface
A scoped cache whose values are acquired by a lookup effect and stored in per-entry scopes.
When to use
Use to cache values that acquire scoped resources and must release those resources when entries expire, are evicted, or are invalidated.
Details
Concurrent requests for the same key share the same in-flight lookup. Entries can expire based on the lookup exit, are evicted when capacity is exceeded, and release their entry scopes when invalidated, evicted, expired, or when the cache's owning scope closes.
See
Signature
interface ScopedCache<in out Key, in out A, in out E = never, out R = never> extends Pipeable {
readonly "~effect/ScopedCache": "~effect/ScopedCache";
readonly capacity: number;
readonly lookup: (key: Key) => Effect<A, E, Scope | R>;
state: State<Key, A, E>;
readonly timeToLive: (exit: Exit<A, E>, key: Key) => Duration;
}Represents whether a ScopedCache is open or closed.
When to use
Use when inspecting the low-level lifecycle state of a scoped cache.
Details
Open stores cached entries in access order for reuse and eviction. Closed means the owning scope has closed and the cache can no longer perform lookup operations.
Signature
type State<K, A, E> =
| {
readonly _tag: "Open";
readonly map: MutableHashMap.MutableHashMap<K, Entry<A, E>>;
}
| {
readonly _tag: "Closed";
};
Retrieves all key-value pairs from the cache as an array. This function only returns entries with successfully resolved values, filtering out any failed lookups or expired entries.
When to use
Use to inspect the currently successful cached key-value pairs without running cache lookups.
Gotchas
Expired entries are removed and their scopes are closed while filtering.
See
keysfor retrieving only cached keysvaluesfor retrieving only cached values