RequestResolver
Resolves data requests made with Effect.request.
A Request describes what a fiber needs, while a RequestResolver describes how to collect request entries, group them into batches, run backend work, and complete each waiting entry. This module includes constructors for common resolver shapes and tools for controlling batching, grouping, delays, tracing, caching, racing, hooks around resolver execution, and persistence.
Caching
Signature
declare const asCache: {
<A extends Any, ServiceMode extends "lookup" | "construction" = never>(options: {
readonly capacity: number;
readonly requireServicesAt?: ServiceMode;
readonly timeToLive?: (exit: Request.Result<A>, request: A) => Duration.Input;
}): (
self: RequestResolver<A>,
) => Effect<
Cache<A, Success<A>, Error<A>, "construction" extends ServiceMode ? never : Services<A>>,
never,
"construction" extends ServiceMode ? Services<A> : never
>;
<A extends Any, ServiceMode extends "lookup" | "construction" = never>(
self: RequestResolver<A>,
options: {
readonly capacity: number;
readonly requireServicesAt?: ServiceMode;
readonly timeToLive?: (exit: Request.Result<A>, request: A) => Duration.Input;
},
): Effect<
Cache<A, Success<A>, Error<A>, "construction" extends ServiceMode ? never : Services<A>>,
never,
"construction" extends ServiceMode ? Services<A> : never
>;
};Wraps a request resolver with persistent storage for persistable requests.
When to use
Use to keep a RequestResolver interface while reusing completed Persistable request results through a Persistence store.
Details
Cached results are loaded from the configured persistence store before running the underlying resolver. Missing entries are resolved normally and written back to the store. Entries marked stale by staleWhileRevalidate receive the stored result and are also resolved again so the refreshed result can be written back to the store. Creating the persisted resolver requires Persistence.Persistence and Scope.
See
Signature
declare const persisted: {
<A extends Request<any, SchemaError | PersistenceError, any> & Any>(options: {
readonly staleWhileRevalidate?: (exit: Request.Result<A>, request: A) => boolean;
readonly storeId: string;
readonly timeToLive?: (exit: Request.Result<A>, request: A) => Duration.Input;
}): (self: RequestResolver<A>) => Effect<RequestResolver<A>, never, Scope | Persistence>;
<A extends Request<any, SchemaError | PersistenceError, any> & Any>(
self: RequestResolver<A>,
options: {
readonly staleWhileRevalidate?: (exit: Request.Result<A>, request: A) => boolean;
readonly storeId: string;
readonly timeToLive?: (exit: Request.Result<A>, request: A) => Duration.Input;
},
): Effect<RequestResolver<A>, never, Scope | Persistence>;
};Adds a bounded in-memory cache to a request resolver.
When to use
Use to reuse completed results for repeated equal request values while still passing a RequestResolver to Effect.request.
Details
Running the returned effect creates the cache and returns a wrapped resolver. The cache stores completed success or failure results by request equality up to capacity. The strategy option controls eviction order and defaults to "lru"; "fifo" keeps insertion order.
Gotchas
Entries do not expire by time, and completed failures are cached the same as successes. Request equality controls cache hits.
See
Signature
declare const withCache: {
<A extends Any>(options: {
readonly capacity: number;
readonly strategy?: "lru" | "fifo";
}): (self: RequestResolver<A>) => Effect<RequestResolver<A>>;
<A extends Any>(
self: RequestResolver<A>,
options: {
readonly capacity: number;
readonly strategy?: "lru" | "fifo";
},
): Effect<RequestResolver<A>>;
};Combinators
Wraps request resolver execution between before and after effects.
Signature
declare const around: {
<A extends Any, A2, X>(
before: (entries: [Entry<NoInfer<A>>, ...Array<Entry<NoInfer<A>>>]) => Effect<A2, Error<A>>,
after: (
entries: [Entry<NoInfer<A>>, ...Array<Entry<NoInfer<A>>>],
a: A2,
) => Effect<X, Error<A>>,
): (self: RequestResolver<A>) => RequestResolver<A>;
<A extends Any, A2, X>(
self: RequestResolver<A>,
before: (entries: [Entry<NoInfer<A>>, ...Array<Entry<NoInfer<A>>>]) => Effect<A2, Error<A>>,
after: (
entries: [Entry<NoInfer<A>>, ...Array<Entry<NoInfer<A>>>],
a: A2,
) => Effect<X, Error<A>>,
): RequestResolver<A>;
};Returns a request resolver that collects at most n requests into each batch.
Details
When more than n requests are waiting for the same resolver and batch key, the current batch is run and additional requests are collected into later batches.
Signature
declare const batchN: {
(n: number): <A extends Any>(self: RequestResolver<A>) => RequestResolver<A>;
<A extends Any>(self: RequestResolver<A>, n: number): RequestResolver<A>;
};Transforms a request resolver by grouping requests using the specified key function.
Signature
declare const grouped: {
<A extends Any, K>(f: (entry: Entry<A>) => K): (self: RequestResolver<A>) => RequestResolver<A>;
<A extends Any, K>(self: RequestResolver<A>, f: (entry: Entry<A>) => K): RequestResolver<A>;
};Returns a request resolver that sends each batch to both resolvers and completes with the first resolver to finish.
Details
The losing resolver run is interrupted after the winning resolver completes the batch.
Signature
declare const race: {
<A2 extends Any>(
that: RequestResolver<A2>,
): <A extends Any>(self: RequestResolver<A>) => RequestResolver<A2 & A>;
<A extends Any, A2 extends Any>(
self: RequestResolver<A>,
that: RequestResolver<A2>,
): RequestResolver<A & A2>;
};Adds a tracing span to the request resolver, which will also add any span links from the request's.
Signature
declare const withSpan: {
<A extends Any>(name: string, options?: SpanOptions | (entries: [Entry<A>, ...Array<Entry<A>>]) => SpanOptions): (self: RequestResolver<A>) => RequestResolver<A>;
<A extends Any>(self: RequestResolver<A>, name: string, options?: SpanOptions | (entries: [Entry<A>, ...Array<Entry<A>>]) => SpanOptions): RequestResolver<A>;
}Constructors
fromEffect
Constructs a request resolver from an effectual function.
Signature
declare function fromEffect<A extends Any>(
f: (entry: Entry<A>) => Effect<Success<A>, Error<A>>,
): RequestResolver<A>;fromEffectTagged
Constructs a request resolver from a list of tags paired to functions, that takes a list of requests and returns a list of results of the same size. Each item in the result list must correspond to the item at the same index in the request list.
Signature
declare function fromEffectTagged<
A extends Any & {
readonly _tag: string;
},
>(): <
Fns extends {
[Tag in string]: [
Extract<
A,
{
readonly _tag: Tag;
}
>,
] extends [Req]
? Req extends Request<ReqA, ReqE, _ReqR>
? (requests: Array<Entry<Req>>) => Effect<Iterable<ReqA, any, any>, ReqE>
: never
: never;
},
>(
fns: Fns,
) => RequestResolver<A>;fromFunction
Constructs a request resolver from a pure function.
Signature
declare function fromFunction<A extends Any>(
f: (entry: Entry<A>) => Success<A>,
): RequestResolver<A>;fromFunctionBatched
Constructs a request resolver from a pure function that takes a list of requests and returns a list of results of the same size. Each item in the result list must correspond to the item at the same index in the request list.
Signature
declare function fromFunctionBatched<A extends Any>(
f: (entries: [Entry<A>, ...Array<Entry<A>>]) => Iterable<Success<A>>,
): RequestResolver<A>;Constructs a request resolver with the specified method to run requests.
Signature
declare function make<A extends Any>(
runAll: (entries: [Entry<A>, ...Array<Entry<A>>], key: unknown) => Effect<void, Error<A>>,
): RequestResolver<A>;makeGrouped
Constructs a request resolver with the requests grouped by a calculated key.
Details
The key can use the Equal trait to determine if two keys are equal.
Signature
declare function makeGrouped<A extends Any, K>(options: {
readonly key: (entry: Entry<A>) => K;
readonly resolver: (entries: [Entry<A>, ...Array<Entry<A>>], key: K) => Effect<void, Error<A>>;
}): RequestResolver<A>;Creates a request resolver with fine-grained control over its behavior.
When to use
Use when you need to supply the resolver batching primitives directly, including the batch key, optional pre-check, delay effect, collection cutoff, and batch runner.
Details
batchKey groups request entries, delay schedules batch execution, collectWhile can end collection early, and runAll receives a non-empty batch for one key.
Gotchas
Accepted entries must be completed. If runAll succeeds with incomplete entries, waiting requests fail. If preCheck returns false, the entry is not batched, so it must be completed or linked to another completion path.
See
makefor constructing a resolver from a batch runnermakeGroupedfor constructing a resolver that groups requests by key
Signature
declare function makeWith<A extends Any>(options: {
readonly batchKey: (request: Entry<A>) => unknown;
readonly collectWhile: (requests: ReadonlySet<Entry<A>>) => boolean;
readonly delay: Effect<void>;
readonly preCheck?: (entry: Entry<A>) => boolean;
readonly runAll: (
entries: [Entry<A>, ...Array<Entry<A>>],
key: unknown,
) => Effect<void, Error<A>>;
}): RequestResolver<A>;Creates a request resolver that never executes requests.
When to use
Use as a resolver value for request types that are statically impossible and should never be issued.
Gotchas
If this resolver is used for an actual request, the request waits forever unless the fiber is interrupted.
See
makefor constructing a resolver that executes batches and completes request entries
Signature
declare const never: RequestResolver<never>;Delays & Timeouts
Sets the batch delay window for this request resolver to the specified duration.
Signature
declare const setDelay: {
(duration: Input): <A extends Any>(self: RequestResolver<A>) => RequestResolver<A>;
<A extends Any>(self: RequestResolver<A>, duration: Input): RequestResolver<A>;
};setDelayEffect
Sets the batch delay effect for this request resolver.
Signature
declare const setDelayEffect: {
(delay: Effect<void>): <A extends Any>(self: RequestResolver<A>) => RequestResolver<A>;
<A extends Any>(self: RequestResolver<A>, delay: Effect<void>): RequestResolver<A>;
};Guards
isRequestResolver
Returns true if the specified value is a RequestResolver, false otherwise.
When to use
Use to narrow unknown values before passing them to APIs that require a RequestResolver.
See
RequestResolverfor the type narrowed by this guard
Signature
declare function isRequestResolver(u: unknown): u is RequestResolver<any>;Models
RequestResolver interface
A resolver that executes and completes batched Request entries.
Details
A resolver controls how requests are grouped, delayed, optionally pre-checked, and finally run. Its runAll method receives a non-empty batch of Request.Entry values for a single batch key and must complete every received entry, usually by calling completeUnsafe or one of the Request completion helpers.
Gotchas
If a resolver finishes without completing an entry, the waiting request fails because the resolver did not supply a result.
Signature
interface RequestResolver<in A extends Request.Any> extends Variance<A>, Pipeable {
readonly delay: Effect<void>;
readonly preCheck: (entry: Entry<A>) => boolean | undefined;
batchKey(entry: Entry<A>): unknown;
collectWhile(entries: ReadonlySet<Entry<A>>): boolean;
runAll(entries: [Entry<A>, ...Array<Entry<A>>], key: unknown): Effect<void, Error<A>>;
}Other
RequestResolver
Namespace containing type-level helpers associated with RequestResolver.
Wraps a request resolver in a cache, allowing it to cache results up to a specified capacity and optional time-to-live.
When to use
Use to turn a request resolver into a first-class
Cachewhen callers need cache lookup, refresh, invalidation, or inspection around request results.Details
The request value is the cache key. Cache misses run the resolver via
Effect.request,timeToLivereceives the requestExitand the request, andrequireServicesAtcontrols whether services are required at lookup time or construction time.Gotchas
Cache hits depend on the request value's equality semantics.
See
withCachefor keeping caching behind a resolver used withEffect.requestpersistedfor storing persistable request results outside process memoryCache.Cache for operations available on the returned cache