(n: number): <A extends Request.Any>(
self: RequestResolver<A>
) => RequestResolver<A>
<A extends Request.Any>(
self: RequestResolver<A>,
n: number
): 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.
Example (Limiting parallel request batches)
import { Effect, Exit, Request, RequestResolver } from "effect"
interface GetDataRequest extends Request.Request<string> {
readonly _tag: "GetDataRequest"
readonly id: number
}
const GetDataRequest = Request.tagged<GetDataRequest>("GetDataRequest")
const resolver = RequestResolver.make<GetDataRequest>((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)
)export const const batchN: {
(n: number): <A extends Request.Any>(
self: RequestResolver<A>
) => RequestResolver<A>
<A extends Request.Any>(
self: RequestResolver<A>,
n: number
): 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.
Example (Limiting parallel request batches)
import { Effect, Exit, Request, RequestResolver } from "effect"
interface GetDataRequest extends Request.Request<string> {
readonly _tag: "GetDataRequest"
readonly id: number
}
const GetDataRequest = Request.tagged<GetDataRequest>("GetDataRequest")
const resolver = RequestResolver.make<GetDataRequest>((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)
)
batchN: {
(n: numbern: number): <function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>): RequestResolver<A>A extends import RequestRequest.type Any = Request.Request<any, any, any>Alias for any Request, regardless of its success, error, or service
requirements.
When to use
Use as a generic constraint for APIs that accept any request while preserving
each concrete request's success, error, and service types.
Any>(self: RequestResolver<A>(parameter) self: {
delay: Effect.Effect<void>;
batchKey: (entry: Request.Entry<A>) => unknown;
preCheck: ((entry: Request.Entry<A>) => boolean) | undefined;
collectWhile: (entries: ReadonlySet<Request.Entry<A>>) => boolean;
runAll: (entries: [Request.Entry<A>, ...Request.Entry<A>[]], key: unknown) => Effect.Effect<void, Request.Error<A>, 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; <…;
}
self: interface RequestResolver<in A extends Request.Any>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.
Example (Defining a request resolver)
import { Effect, Exit, RequestResolver } from "effect"
import type { Request } from "effect"
interface GetUserRequest extends Request.Request<string, Error> {
readonly _tag: "GetUserRequest"
readonly id: number
}
// In practice, you would typically use RequestResolver.make() instead
const resolver = RequestResolver.make<GetUserRequest>((entries) =>
Effect.sync(() => {
for (const entry of entries) {
entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`))
}
})
)
Namespace containing type-level helpers associated with RequestResolver.
RequestResolver<function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>): RequestResolver<A>A>) => interface RequestResolver<in A extends Request.Any>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.
Example (Defining a request resolver)
import { Effect, Exit, RequestResolver } from "effect"
import type { Request } from "effect"
interface GetUserRequest extends Request.Request<string, Error> {
readonly _tag: "GetUserRequest"
readonly id: number
}
// In practice, you would typically use RequestResolver.make() instead
const resolver = RequestResolver.make<GetUserRequest>((entries) =>
Effect.sync(() => {
for (const entry of entries) {
entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`))
}
})
)
Namespace containing type-level helpers associated with RequestResolver.
RequestResolver<function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>): RequestResolver<A>A>
<function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>, n: number): RequestResolver<A>A extends import RequestRequest.type Any = Request.Request<any, any, any>Alias for any Request, regardless of its success, error, or service
requirements.
When to use
Use as a generic constraint for APIs that accept any request while preserving
each concrete request's success, error, and service types.
Any>(self: RequestResolver<A>(parameter) self: {
delay: Effect.Effect<void>;
batchKey: (entry: Request.Entry<A>) => unknown;
preCheck: ((entry: Request.Entry<A>) => boolean) | undefined;
collectWhile: (entries: ReadonlySet<Request.Entry<A>>) => boolean;
runAll: (entries: [Request.Entry<A>, ...Request.Entry<A>[]], key: unknown) => Effect.Effect<void, Request.Error<A>, 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; <…;
}
self: interface RequestResolver<in A extends Request.Any>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.
Example (Defining a request resolver)
import { Effect, Exit, RequestResolver } from "effect"
import type { Request } from "effect"
interface GetUserRequest extends Request.Request<string, Error> {
readonly _tag: "GetUserRequest"
readonly id: number
}
// In practice, you would typically use RequestResolver.make() instead
const resolver = RequestResolver.make<GetUserRequest>((entries) =>
Effect.sync(() => {
for (const entry of entries) {
entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`))
}
})
)
Namespace containing type-level helpers associated with RequestResolver.
RequestResolver<function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>, n: number): RequestResolver<A>A>, n: numbern: number): interface RequestResolver<in A extends Request.Any>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.
Example (Defining a request resolver)
import { Effect, Exit, RequestResolver } from "effect"
import type { Request } from "effect"
interface GetUserRequest extends Request.Request<string, Error> {
readonly _tag: "GetUserRequest"
readonly id: number
}
// In practice, you would typically use RequestResolver.make() instead
const resolver = RequestResolver.make<GetUserRequest>((entries) =>
Effect.sync(() => {
for (const entry of entries) {
entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`))
}
})
)
Namespace containing type-level helpers associated with RequestResolver.
RequestResolver<function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>, n: number): RequestResolver<A>A>
} = dual<(...args: Array<any>) => any, <A extends Request.Any>(self: RequestResolver<A>, n: number) => RequestResolver<A>>(arity: 2, body: <A extends Request.Any>(self: RequestResolver<A>, n: number) => RequestResolver<A>): ((...args: Array<any>) => any) & (<A extends Request.Any>(self: RequestResolver<A>, n: number) => RequestResolver<A>) (+1 overload)Creates a function that can be called in data-first style or data-last
(pipe-friendly) style.
When to use
Use to expose one implementation through both direct and pipe-friendly
call styles.
Details
Pass either the arity of the uncurried function or a predicate that decides
whether the current call is data-first. Arity is the common case. Use a
predicate when optional arguments make arity ambiguous.
Example (Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(2, (self, that) => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: {
(that: number): (self: number) => number
(self: number, that: number): number
} = Function.dual(2, (self: number, that: number): number => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(
(args) => args.length === 2,
(self, that) => self + that
)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
dual(2, <function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>, n: number): RequestResolver<A>A extends import RequestRequest.type Any = Request.Request<any, any, any>Alias for any Request, regardless of its success, error, or service
requirements.
When to use
Use as a generic constraint for APIs that accept any request while preserving
each concrete request's success, error, and service types.
Any>(self: RequestResolver<A>(parameter) self: {
delay: Effect.Effect<void>;
batchKey: (entry: Request.Entry<A>) => unknown;
preCheck: ((entry: Request.Entry<A>) => boolean) | undefined;
collectWhile: (entries: ReadonlySet<Request.Entry<A>>) => boolean;
runAll: (entries: [Request.Entry<A>, ...Request.Entry<A>[]], key: unknown) => Effect.Effect<void, Request.Error<A>, 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; <…;
}
self: interface RequestResolver<in A extends Request.Any>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.
Example (Defining a request resolver)
import { Effect, Exit, RequestResolver } from "effect"
import type { Request } from "effect"
interface GetUserRequest extends Request.Request<string, Error> {
readonly _tag: "GetUserRequest"
readonly id: number
}
// In practice, you would typically use RequestResolver.make() instead
const resolver = RequestResolver.make<GetUserRequest>((entries) =>
Effect.sync(() => {
for (const entry of entries) {
entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`))
}
})
)
Namespace containing type-level helpers associated with RequestResolver.
RequestResolver<function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>, n: number): RequestResolver<A>A>, n: numbern: number): interface RequestResolver<in A extends Request.Any>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.
Example (Defining a request resolver)
import { Effect, Exit, RequestResolver } from "effect"
import type { Request } from "effect"
interface GetUserRequest extends Request.Request<string, Error> {
readonly _tag: "GetUserRequest"
readonly id: number
}
// In practice, you would typically use RequestResolver.make() instead
const resolver = RequestResolver.make<GetUserRequest>((entries) =>
Effect.sync(() => {
for (const entry of entries) {
entry.completeUnsafe(Exit.succeed(`User ${entry.request.id}`))
}
})
)
Namespace containing type-level helpers associated with RequestResolver.
RequestResolver<function (type parameter) A in <A extends Request.Any>(self: RequestResolver<A>, n: number): RequestResolver<A>A> =>
const makeWith: <
A extends Request.Any
>(options: {
readonly batchKey: (
request: Request.Entry<A>
) => unknown
readonly preCheck?:
| ((entry: Request.Entry<A>) => boolean)
| undefined
readonly delay: Effect.Effect<void>
readonly collectWhile: (
requests: ReadonlySet<Request.Entry<A>>
) => boolean
readonly runAll: (
entries: NonEmptyArray<Request.Entry<A>>,
key: unknown
) => Effect.Effect<void, Request.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.
makeWith({
...self: RequestResolver<A>(parameter) self: {
delay: Effect.Effect<void>;
batchKey: (entry: Request.Entry<A>) => unknown;
preCheck: ((entry: Request.Entry<A>) => boolean) | undefined;
collectWhile: (entries: ReadonlySet<Request.Entry<A>>) => boolean;
runAll: (entries: [Request.Entry<A>, ...Request.Entry<A>[]], key: unknown) => Effect.Effect<void, Request.Error<A>, 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; <…;
}
self,
collectWhile: (
requests: ReadonlySet<Request.Entry<A>>
) => boolean
collectWhile: (requests: ReadonlySet<Request.Entry<A>>requests) => requests: ReadonlySet<Request.Entry<A>>requests.ReadonlySet<T>.size: numbersize < n: numbern
}))