Hyperlinkv0.8.0-beta.28

RequestResolver

RequestResolver.fromEffectTaggedconsteffect/RequestResolver.ts:487
<A extends Request.Any & { readonly _tag: string }>(): <
  Fns extends {
    readonly [Tag in A["_tag"]]: [
      Extract<A, { readonly _tag: Tag }>
    ] extends [infer Req]
      ? Req extends Request.Request<infer ReqA, infer ReqE, infer _ReqR>
        ? (
            requests: Array<Request.Entry<Req>>
          ) => Effect.Effect<Iterable<ReqA>, ReqE>
        : never
      : never
  }
>(
  fns: Fns
) => RequestResolver<A>

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 (Handling tagged request batches)

import { Effect, RequestResolver } from "effect"
import type { Request } from "effect"

interface GetUser extends Request.Request<string, Error> {
  readonly _tag: "GetUser"
  readonly id: number
}

interface GetPost extends Request.Request<string, Error> {
  readonly _tag: "GetPost"
  readonly id: number
}

type MyRequest = GetUser | GetPost

// Create a resolver that handles different request types
const MyResolver = RequestResolver.fromEffectTagged<MyRequest>()({
  GetUser: (requests) =>
    Effect.succeed(requests.map((req) => `User ${req.request.id}`)),
  GetPost: (requests) =>
    Effect.succeed(requests.map((req) => `Post ${req.request.id}`))
})
constructors
export const fromEffectTagged = <A extends Request.Any & { readonly _tag: string }>() =>
<
  Fns extends {
    readonly [Tag in A["_tag"]]: [Extract<A, { readonly _tag: Tag }>] extends [infer Req]
      ? Req extends Request.Request<infer ReqA, infer ReqE, infer _ReqR> ?
        (requests: Array<Request.Entry<Req>>) => Effect.Effect<Iterable<ReqA>, ReqE>
      : never
      : never
  }
>(
  fns: Fns
): RequestResolver<A> =>
  make<A>(
    (entries): Effect.Effect<void> => {
      const grouped = new Map<A["_tag"], Array<Request.Entry<A>>>()
      for (let i = 0, len = entries.length; i < len; i++) {
        const group = grouped.get(entries[i].request._tag)
        if (group) {
          group.push(entries[i])
        } else {
          grouped.set(entries[i].request._tag, [entries[i]])
        }
      }
      return Effect.forEach(
        grouped,
        ([tag, requests]) =>
          Effect.matchCause((fns[tag] as any)(requests) as Effect.Effect<Array<any>, unknown, unknown>, {
            onFailure: (cause) => {
              for (let i = 0; i < requests.length; i++) {
                const entry = requests[i]
                entry.completeUnsafe(exitFail(cause) as any)
              }
            },
            onSuccess: (res) => {
              for (let i = 0; i < res.length; i++) {
                const entry = requests[i]
                entry.completeUnsafe(exitSucceed(res[i]) as any)
              }
            }
          }),
        { concurrency: "unbounded", discard: true }
      ) as Effect.Effect<void>
    }
  ) as any