/** * @since 2.0.0 */ import type { NonEmptyArray } from "./Array.ts"; import * as Cache from "./Cache.ts"; import type * as Duration from "./Duration.ts"; import * as Effect from "./Effect.ts"; import { type Pipeable } from "./Pipeable.ts"; import type * as Request from "./Request.ts"; import type * as Schema from "./Schema.ts"; import type { Scope } from "./Scope.ts"; import * as Tracer from "./Tracer.ts"; import type * as Types from "./Types.ts"; import type * as Persistable from "./unstable/persistence/Persistable.ts"; import * as Persistence from "./unstable/persistence/Persistence.ts"; declare const TypeId = "~effect/RequestResolver"; /** * The `RequestResolver` interface requires an environment `R` and handles * the execution of requests of type `A`. * * Implementations must provide a `runAll` method, which processes a collection * of requests and produces an effect that fulfills these requests. Requests are * organized into a `Array>`, where the outer `Array` groups requests * into batches that are executed sequentially, and each inner `Array` contains * requests that can be executed in parallel. This structure allows * implementations to analyze all incoming requests collectively and optimize * query execution accordingly. * * Implementations are typically specialized for a subtype of `Request`. * However, they are not strictly limited to these subtypes as long as they can * map any given request type to `Request`. Implementations should inspect * the collection of requests to identify the needed information and execute the * corresponding queries. It is imperative that implementations resolve all the * requests they receive. Failing to do so will lead to a `QueryFailure` error * during query execution. * * @example * ```ts * import type { Request } from "effect" * import { Effect, Exit, RequestResolver } from "effect" * * interface GetUserRequest extends Request.Request { * readonly _tag: "GetUserRequest" * readonly id: number * } * * // In practice, you would typically use RequestResolver.make() instead * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`)) * } * }) * ) * ``` * * @since 2.0.0 * @category models */ export interface RequestResolver extends RequestResolver.Variance, Pipeable { readonly delay: Effect.Effect; /** * Get a batch key for the given request. */ batchKey(entry: Request.Entry): unknown; /** * An optional pre-check function that can be used to filter requests before * they are added to a batch. If the function returns `false`, the request * will not be processed. */ readonly preCheck: ((entry: Request.Entry) => boolean) | undefined; /** * Should the resolver continue collecting requests? Otherwise, it will * immediately execute the collected requests cutting the delay short. */ collectWhile(entries: ReadonlySet>): boolean; /** * Execute a collection of requests. */ runAll(entries: NonEmptyArray>, key: unknown): Effect.Effect>; } /** * @since 2.0.0 * @category models */ export declare namespace RequestResolver { /** * @since 2.0.0 * @category models */ interface Variance { readonly [TypeId]: { readonly _A: Types.Contravariant; }; } } /** * Returns `true` if the specified value is a `RequestResolver`, `false` otherwise. * * @since 2.0.0 * @category guards */ export declare const isRequestResolver: (u: unknown) => u is RequestResolver; /** * Low-level constructor for creating a request resolver with fine-grained * control over its behavior. * * @since 4.0.0 * @category constructors */ export declare const makeWith: (options: { readonly batchKey: (request: Request.Entry) => unknown; readonly preCheck?: ((entry: Request.Entry) => boolean) | undefined; readonly delay: Effect.Effect; readonly collectWhile: (requests: ReadonlySet>) => boolean; readonly runAll: (entries: NonEmptyArray>, key: unknown) => Effect.Effect>; }) => RequestResolver; /** * Constructs a request resolver with the specified method to run requests. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * // Define a request type * interface GetUserRequest extends Request.Request { * readonly _tag: "GetUserRequest" * readonly id: number * } * const GetUserRequest = Request.tagged("GetUserRequest") * * // Create a resolver that handles the requests * const UserResolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * // Complete each request with a result * entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`)) * } * }) * ) * * // Use the resolver to handle requests * const getUserEffect = Effect.request(GetUserRequest({ id: 123 }), UserResolver) * ``` * * @since 2.0.0 * @category constructors */ export declare const make: (runAll: (entries: NonEmptyArray>, key: unknown) => Effect.Effect>) => RequestResolver; /** * Constructs a request resolver with the requests grouped by a calculated key. * * The key can use the Equal trait to determine if two keys are equal. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetUserByRole extends Request.Request { * readonly _tag: "GetUserByRole" * readonly role: string * readonly id: number * } * const GetUserByRole = Request.tagged("GetUserByRole") * * // Group requests by role for efficient batch processing * const UserByRoleResolver = RequestResolver.makeGrouped({ * key: ({ request }) => request.role, * resolver: (entries, role) => * Effect.sync(() => { * console.log(`Processing ${entries.length} requests for role: ${role}`) * for (const entry of entries) { * entry.completeUnsafe( * Exit.succeed(`User ${entry.request.id} with role ${role}`) * ) * } * }) * }) * ``` * * @since 4.0.0 * @category constructors */ export declare const makeGrouped: (options: { readonly key: (entry: Request.Entry) => K; readonly resolver: (entries: NonEmptyArray>, key: K) => Effect.Effect>; }) => RequestResolver; /** * Constructs a request resolver from a pure function. * * @example * ```ts * import { Effect, Request, RequestResolver } from "effect" * * interface GetSquareRequest extends Request.Request { * readonly _tag: "GetSquareRequest" * readonly value: number * } * const GetSquareRequest = Request.tagged("GetSquareRequest") * * // Create a resolver from a pure function * const SquareResolver = RequestResolver.fromFunction( * (entry) => entry.request.value * entry.request.value * ) * * // Usage * const getSquareEffect = Effect.request( * GetSquareRequest({ value: 5 }), * SquareResolver * ) * // Will resolve to 25 * ``` * * @since 2.0.0 * @category constructors */ export declare const fromFunction: (f: (entry: Request.Entry) => Request.Success) => RequestResolver; /** * 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. * * @example * ```ts * import { Effect, Request, RequestResolver } from "effect" * * interface GetDoubleRequest extends Request.Request { * readonly _tag: "GetDoubleRequest" * readonly value: number * } * const GetDoubleRequest = Request.tagged("GetDoubleRequest") * * // Create a resolver that processes multiple requests in a batch * const DoubleResolver = RequestResolver.fromFunctionBatched( * (entries) => entries.map((entry) => entry.request.value * 2) * ) * * // Usage with multiple requests * const effects = [1, 2, 3].map((value) => * Effect.request(GetDoubleRequest({ value }), DoubleResolver) * ) * const batchedEffect = Effect.all(effects) // [2, 4, 6] * ``` * * @since 2.0.0 * @category constructors */ export declare const fromFunctionBatched: (f: (entries: NonEmptyArray>) => Iterable>) => RequestResolver; /** * Constructs a request resolver from an effectual function. * * @example * ```ts * import { Effect, Request, RequestResolver } from "effect" * * interface GetUserFromAPIRequest extends Request.Request { * readonly _tag: "GetUserFromAPIRequest" * readonly id: number * } * const GetUserFromAPIRequest = Request.tagged( * "GetUserFromAPIRequest" * ) * * // Create a resolver that uses effects (like HTTP calls) * const UserAPIResolver = RequestResolver.fromEffect( * (entry) => * Effect.gen(function*() { * // Simulate an API call * yield* Effect.sleep("100 millis") * // Just return the result without error handling for simplicity * return `User ${entry.request.id} from API` * }) * ) * * // Usage * const getUserEffect = Effect.request( * GetUserFromAPIRequest({ id: 123 }), * UserAPIResolver * ) * ``` * * @since 2.0.0 * @category constructors */ export declare const fromEffect: (f: (entry: Request.Entry) => Effect.Effect, Request.Error>) => RequestResolver; /** * 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. * * @example * ```ts * import type { Request } from "effect" * import { Effect, RequestResolver } from "effect" * * interface GetUser extends Request.Request { * readonly _tag: "GetUser" * readonly id: number * } * * interface GetPost extends Request.Request { * readonly _tag: "GetPost" * readonly id: number * } * * type MyRequest = GetUser | GetPost * * // Create a resolver that handles different request types * const MyResolver = RequestResolver.fromEffectTagged()({ * GetUser: (requests) => * Effect.succeed(requests.map((req) => `User ${req.request.id}`)), * GetPost: (requests) => * Effect.succeed(requests.map((req) => `Post ${req.request.id}`)) * }) * ``` * * @since 2.0.0 * @category constructors */ export declare const fromEffectTagged: () => ] extends [infer Req] ? Req extends Request.Request ? (requests: Array>) => Effect.Effect, ReqE> : never : never; }>(fns: Fns) => RequestResolver; /** * Sets the batch delay effect for this request resolver. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Set a custom delay effect (e.g., with logging) * const resolverWithCustomDelay = RequestResolver.setDelayEffect( * resolver, * Effect.gen(function*() { * yield* Effect.log("Waiting before processing batch...") * yield* Effect.sleep("50 millis") * }) * ) * ``` * * @since 4.0.0 * @category delay */ export declare const setDelayEffect: { /** * Sets the batch delay effect for this request resolver. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Set a custom delay effect (e.g., with logging) * const resolverWithCustomDelay = RequestResolver.setDelayEffect( * resolver, * Effect.gen(function*() { * yield* Effect.log("Waiting before processing batch...") * yield* Effect.sleep("50 millis") * }) * ) * ``` * * @since 4.0.0 * @category delay */ (delay: Effect.Effect): (self: RequestResolver) => RequestResolver; /** * Sets the batch delay effect for this request resolver. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Set a custom delay effect (e.g., with logging) * const resolverWithCustomDelay = RequestResolver.setDelayEffect( * resolver, * Effect.gen(function*() { * yield* Effect.log("Waiting before processing batch...") * yield* Effect.sleep("50 millis") * }) * ) * ``` * * @since 4.0.0 * @category delay */ (self: RequestResolver, delay: Effect.Effect): RequestResolver; }; /** * Sets the batch delay window for this request resolver to the specified duration. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Add a 100ms delay to batch requests together * const delayedResolver = RequestResolver.setDelay(resolver, "100 millis") * * // Can also use number for milliseconds * const delayedResolver2 = RequestResolver.setDelay(resolver, 100) * ``` * * @since 4.0.0 * @category delay */ export declare const setDelay: { /** * Sets the batch delay window for this request resolver to the specified duration. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Add a 100ms delay to batch requests together * const delayedResolver = RequestResolver.setDelay(resolver, "100 millis") * * // Can also use number for milliseconds * const delayedResolver2 = RequestResolver.setDelay(resolver, 100) * ``` * * @since 4.0.0 * @category delay */ (duration: Duration.Input): (self: RequestResolver) => RequestResolver; /** * Sets the batch delay window for this request resolver to the specified duration. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Add a 100ms delay to batch requests together * const delayedResolver = RequestResolver.setDelay(resolver, "100 millis") * * // Can also use number for milliseconds * const delayedResolver2 = RequestResolver.setDelay(resolver, 100) * ``` * * @since 4.0.0 * @category delay */ (self: RequestResolver, duration: Duration.Input): RequestResolver; }; /** * A request resolver aspect that executes requests between two effects, `before` * and `after`, where the result of `before` can be used by `after`. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Add setup and cleanup around request execution * const resolverWithAround = RequestResolver.around( * resolver, * (entries) => * Effect.gen(function*() { * yield* Effect.log(`Starting batch of ${entries.length} requests`) * return Date.now() * }), * (entries, startTime) => * Effect.gen(function*() { * const duration = Date.now() - startTime * yield* Effect.log(`Batch completed in ${duration}ms`) * }) * ) * ``` * * @since 2.0.0 * @category combinators */ export declare const around: { /** * A request resolver aspect that executes requests between two effects, `before` * and `after`, where the result of `before` can be used by `after`. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Add setup and cleanup around request execution * const resolverWithAround = RequestResolver.around( * resolver, * (entries) => * Effect.gen(function*() { * yield* Effect.log(`Starting batch of ${entries.length} requests`) * return Date.now() * }), * (entries, startTime) => * Effect.gen(function*() { * const duration = Date.now() - startTime * yield* Effect.log(`Batch completed in ${duration}ms`) * }) * ) * ``` * * @since 2.0.0 * @category combinators */ (before: (entries: NonEmptyArray>>) => Effect.Effect>, after: (entries: NonEmptyArray>>, a: A2) => Effect.Effect>): (self: RequestResolver) => RequestResolver; /** * A request resolver aspect that executes requests between two effects, `before` * and `after`, where the result of `before` can be used by `after`. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed("data")) * } * }) * ) * * // Add setup and cleanup around request execution * const resolverWithAround = RequestResolver.around( * resolver, * (entries) => * Effect.gen(function*() { * yield* Effect.log(`Starting batch of ${entries.length} requests`) * return Date.now() * }), * (entries, startTime) => * Effect.gen(function*() { * const duration = Date.now() - startTime * yield* Effect.log(`Batch completed in ${duration}ms`) * }) * ) * ``` * * @since 2.0.0 * @category combinators */ (self: RequestResolver, before: (entries: NonEmptyArray>>) => Effect.Effect>, after: (entries: NonEmptyArray>>, a: A2) => Effect.Effect>): RequestResolver; }; /** * A request resolver that never executes requests. * * @since 2.0.0 * @category constructors */ export declare const never: RequestResolver; /** * Returns a request resolver that executes at most `n` requests in parallel. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * console.log(`Processing batch of ${entries.length} requests`) * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`data-${entry.request.id}`)) * } * }) * ) * * // Limit batches to maximum 5 requests * const limitedResolver = RequestResolver.batchN(resolver, 5) * * // When more than 5 requests are made, they'll be split into multiple batches * const requests = Array.from( * { length: 12 }, * (_, i) => Effect.request(GetDataRequest({ id: i }), limitedResolver) * ) * ``` * * @since 2.0.0 * @category combinators */ export declare const batchN: { /** * Returns a request resolver that executes at most `n` requests in parallel. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * console.log(`Processing batch of ${entries.length} requests`) * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`data-${entry.request.id}`)) * } * }) * ) * * // Limit batches to maximum 5 requests * const limitedResolver = RequestResolver.batchN(resolver, 5) * * // When more than 5 requests are made, they'll be split into multiple batches * const requests = Array.from( * { length: 12 }, * (_, i) => Effect.request(GetDataRequest({ id: i }), limitedResolver) * ) * ``` * * @since 2.0.0 * @category combinators */ (n: number): (self: RequestResolver) => RequestResolver; /** * Returns a request resolver that executes at most `n` requests in parallel. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * console.log(`Processing batch of ${entries.length} requests`) * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`data-${entry.request.id}`)) * } * }) * ) * * // Limit batches to maximum 5 requests * const limitedResolver = RequestResolver.batchN(resolver, 5) * * // When more than 5 requests are made, they'll be split into multiple batches * const requests = Array.from( * { length: 12 }, * (_, i) => Effect.request(GetDataRequest({ id: i }), limitedResolver) * ) * ``` * * @since 2.0.0 * @category combinators */ (self: RequestResolver, n: number): RequestResolver; }; /** * Transform a request resolver by grouping requests using the specified key * function. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetUserRequest extends Request.Request { * readonly _tag: "GetUserRequest" * readonly userId: number * readonly department: string * } * const GetUserRequest = Request.tagged("GetUserRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * console.log(`Processing ${entries.length} users`) * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`User ${entry.request.userId}`)) * } * }) * ) * * // Group requests by department for more efficient processing * const groupedResolver = RequestResolver.grouped( * resolver, * ({ request }) => request.department * ) * * // Requests for the same department will be batched together * const requests = [ * Effect.request( * GetUserRequest({ userId: 1, department: "Engineering" }), * groupedResolver * ), * Effect.request( * GetUserRequest({ userId: 2, department: "Engineering" }), * groupedResolver * ), * Effect.request( * GetUserRequest({ userId: 3, department: "Marketing" }), * groupedResolver * ) * ] * ``` * * @since 4.0.0 * @category combinators */ export declare const grouped: { /** * Transform a request resolver by grouping requests using the specified key * function. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetUserRequest extends Request.Request { * readonly _tag: "GetUserRequest" * readonly userId: number * readonly department: string * } * const GetUserRequest = Request.tagged("GetUserRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * console.log(`Processing ${entries.length} users`) * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`User ${entry.request.userId}`)) * } * }) * ) * * // Group requests by department for more efficient processing * const groupedResolver = RequestResolver.grouped( * resolver, * ({ request }) => request.department * ) * * // Requests for the same department will be batched together * const requests = [ * Effect.request( * GetUserRequest({ userId: 1, department: "Engineering" }), * groupedResolver * ), * Effect.request( * GetUserRequest({ userId: 2, department: "Engineering" }), * groupedResolver * ), * Effect.request( * GetUserRequest({ userId: 3, department: "Marketing" }), * groupedResolver * ) * ] * ``` * * @since 4.0.0 * @category combinators */ (f: (entry: Request.Entry) => K): (self: RequestResolver) => RequestResolver; /** * Transform a request resolver by grouping requests using the specified key * function. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetUserRequest extends Request.Request { * readonly _tag: "GetUserRequest" * readonly userId: number * readonly department: string * } * const GetUserRequest = Request.tagged("GetUserRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * console.log(`Processing ${entries.length} users`) * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`User ${entry.request.userId}`)) * } * }) * ) * * // Group requests by department for more efficient processing * const groupedResolver = RequestResolver.grouped( * resolver, * ({ request }) => request.department * ) * * // Requests for the same department will be batched together * const requests = [ * Effect.request( * GetUserRequest({ userId: 1, department: "Engineering" }), * groupedResolver * ), * Effect.request( * GetUserRequest({ userId: 2, department: "Engineering" }), * groupedResolver * ), * Effect.request( * GetUserRequest({ userId: 3, department: "Marketing" }), * groupedResolver * ) * ] * ``` * * @since 4.0.0 * @category combinators */ (self: RequestResolver, f: (entry: Request.Entry) => K): RequestResolver; }; /** * Returns a new request resolver that executes requests by sending them to this * request resolver and that request resolver, returning the results from the first data * source to complete and safely interrupting the loser. * * The batch delay is determined by the first request resolver. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * // Fast resolver (simulating cache) * const fastResolver = RequestResolver.make((entries) => * Effect.gen(function*() { * yield* Effect.sleep("10 millis") * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`fast-${entry.request.id}`)) * } * }) * ) * * // Slow resolver (simulating database) * const slowResolver = RequestResolver.make((entries) => * Effect.gen(function*() { * yield* Effect.sleep("100 millis") * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`slow-${entry.request.id}`)) * } * }) * ) * * // Race resolvers - will use whichever completes first * const racingResolver = RequestResolver.race(fastResolver, slowResolver) * ``` * * @since 2.0.0 * @category combinators */ export declare const race: { /** * Returns a new request resolver that executes requests by sending them to this * request resolver and that request resolver, returning the results from the first data * source to complete and safely interrupting the loser. * * The batch delay is determined by the first request resolver. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * // Fast resolver (simulating cache) * const fastResolver = RequestResolver.make((entries) => * Effect.gen(function*() { * yield* Effect.sleep("10 millis") * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`fast-${entry.request.id}`)) * } * }) * ) * * // Slow resolver (simulating database) * const slowResolver = RequestResolver.make((entries) => * Effect.gen(function*() { * yield* Effect.sleep("100 millis") * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`slow-${entry.request.id}`)) * } * }) * ) * * // Race resolvers - will use whichever completes first * const racingResolver = RequestResolver.race(fastResolver, slowResolver) * ``` * * @since 2.0.0 * @category combinators */ (that: RequestResolver): (self: RequestResolver) => RequestResolver; /** * Returns a new request resolver that executes requests by sending them to this * request resolver and that request resolver, returning the results from the first data * source to complete and safely interrupting the loser. * * The batch delay is determined by the first request resolver. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * // Fast resolver (simulating cache) * const fastResolver = RequestResolver.make((entries) => * Effect.gen(function*() { * yield* Effect.sleep("10 millis") * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`fast-${entry.request.id}`)) * } * }) * ) * * // Slow resolver (simulating database) * const slowResolver = RequestResolver.make((entries) => * Effect.gen(function*() { * yield* Effect.sleep("100 millis") * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`slow-${entry.request.id}`)) * } * }) * ) * * // Race resolvers - will use whichever completes first * const racingResolver = RequestResolver.race(fastResolver, slowResolver) * ``` * * @since 2.0.0 * @category combinators */ (self: RequestResolver, that: RequestResolver): RequestResolver; }; /** * Add a tracing span to the request resolver, which will also add any span * links from the request's. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`data-${entry.request.id}`)) * } * }) * ) * * // Add tracing span with custom name and attributes * const tracedResolver = RequestResolver.withSpan( * resolver, * "user-data-resolver", * { * attributes: { * "resolver.type": "user-data", * "resolver.version": "1.0" * } * } * ) * * // Spans will automatically include batch size and request links * const effect = Effect.request(GetDataRequest({ id: 123 }), tracedResolver) * ``` * * @since 4.0.0 * @category combinators */ export declare const withSpan: { /** * Add a tracing span to the request resolver, which will also add any span * links from the request's. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`data-${entry.request.id}`)) * } * }) * ) * * // Add tracing span with custom name and attributes * const tracedResolver = RequestResolver.withSpan( * resolver, * "user-data-resolver", * { * attributes: { * "resolver.type": "user-data", * "resolver.version": "1.0" * } * } * ) * * // Spans will automatically include batch size and request links * const effect = Effect.request(GetDataRequest({ id: 123 }), tracedResolver) * ``` * * @since 4.0.0 * @category combinators */ (name: string, options?: Tracer.SpanOptions | ((entries: NonEmptyArray>) => Tracer.SpanOptions) | undefined): (self: RequestResolver) => RequestResolver; /** * Add a tracing span to the request resolver, which will also add any span * links from the request's. * * @example * ```ts * import { Effect, Exit, Request, RequestResolver } from "effect" * * interface GetDataRequest extends Request.Request { * readonly _tag: "GetDataRequest" * readonly id: number * } * const GetDataRequest = Request.tagged("GetDataRequest") * * const resolver = RequestResolver.make((entries) => * Effect.sync(() => { * for (const entry of entries) { * entry.completeUnsafe(Exit.succeed(`data-${entry.request.id}`)) * } * }) * ) * * // Add tracing span with custom name and attributes * const tracedResolver = RequestResolver.withSpan( * resolver, * "user-data-resolver", * { * attributes: { * "resolver.type": "user-data", * "resolver.version": "1.0" * } * } * ) * * // Spans will automatically include batch size and request links * const effect = Effect.request(GetDataRequest({ id: 123 }), tracedResolver) * ``` * * @since 4.0.0 * @category combinators */ (self: RequestResolver, name: string, options?: Tracer.SpanOptions | ((entries: NonEmptyArray>) => Tracer.SpanOptions) | undefined): RequestResolver; }; /** * Wraps a request resolver in a cache, allowing it to cache results up to a * specified capacity and optional time-to-live. * * @since 4.0.0 * @category Caching */ export declare const asCache: { /** * Wraps a request resolver in a cache, allowing it to cache results up to a * specified capacity and optional time-to-live. * * @since 4.0.0 * @category Caching */ (options: { readonly capacity: number; readonly timeToLive?: ((exit: Request.Result, request: A) => Duration.Input) | undefined; readonly requireServicesAt?: ServiceMode | undefined; }): (self: RequestResolver) => Effect.Effect, Request.Error, "construction" extends ServiceMode ? never : Request.Services>, never, "construction" extends ServiceMode ? Request.Services : never>; /** * Wraps a request resolver in a cache, allowing it to cache results up to a * specified capacity and optional time-to-live. * * @since 4.0.0 * @category Caching */ (self: RequestResolver, options: { readonly capacity: number; readonly timeToLive?: ((exit: Request.Result, request: A) => Duration.Input) | undefined; readonly requireServicesAt?: ServiceMode | undefined; }): Effect.Effect, Request.Error, "construction" extends ServiceMode ? never : Request.Services>, never, "construction" extends ServiceMode ? Request.Services : never>; }; /** * Adds caching capabilities to a request resolver, allowing it to cache * results up to a specified capacity. * * @since 4.0.0 * @category Caching */ export declare const withCache: { /** * Adds caching capabilities to a request resolver, allowing it to cache * results up to a specified capacity. * * @since 4.0.0 * @category Caching */ (options: { readonly capacity: number; readonly strategy?: "lru" | "fifo" | undefined; }): (self: RequestResolver) => Effect.Effect>; /** * Adds caching capabilities to a request resolver, allowing it to cache * results up to a specified capacity. * * @since 4.0.0 * @category Caching */ (self: RequestResolver, options: { readonly capacity: number; readonly strategy?: "lru" | "fifo" | undefined; }): Effect.Effect>; }; /** * @since 4.0.0 * @category Persistence */ export declare const persisted: { /** * @since 4.0.0 * @category Persistence */ & Persistable.Any>(options: { readonly storeId: string; readonly timeToLive?: ((exit: Request.Result, request: A) => Duration.Input) | undefined; readonly staleWhileRevalidate?: ((exit: Request.Result, request: A) => boolean) | undefined; }): (self: RequestResolver) => Effect.Effect, never, Persistence.Persistence | Scope>; /** * @since 4.0.0 * @category Persistence */ & Persistable.Any>(self: RequestResolver, options: { readonly storeId: string; readonly timeToLive?: ((exit: Request.Result, request: A) => Duration.Input) | undefined; readonly staleWhileRevalidate?: ((exit: Request.Result, request: A) => boolean) | undefined; }): Effect.Effect, never, Persistence.Persistence | Scope>; }; export {}; //# sourceMappingURL=RequestResolver.d.ts.map