import * as Chunk from "@effect/data/Chunk" import { pipe } from "@effect/data/Function" import * as HashMap from "@effect/data/HashMap" import * as Option from "@effect/data/Option" import type * as DataSource from "@effect/query/DataSource" import type * as BlockedRequest from "@effect/query/internal_effect_untraced/blockedRequest" import * as Sequential from "@effect/query/internal_effect_untraced/sequential" /** @internal */ export const ParallelTypeId: unique symbol = Symbol.for("@effect/query/Parallel") /** @internal */ export type ParallelTypeId = typeof ParallelTypeId /** * A `Parallel` maintains a mapping from data sources to requests from those * data sources that can be executed in parallel. * * @internal */ export interface Parallel extends Parallel.Variance { readonly map: HashMap.HashMap< DataSource.DataSource, Chunk.Chunk> > } /** @internal */ export declare namespace Parallel { /** @internal */ export interface Variance { readonly [ParallelTypeId]: { readonly _R: (_: never) => R } } } /** @internal */ const parallelVariance = { _R: (_: never) => _ } /** @internal */ class ParallelImpl implements Parallel { readonly [ParallelTypeId] = parallelVariance constructor( readonly map: HashMap.HashMap< DataSource.DataSource, Chunk.Chunk> > ) {} } /** * The empty collection of requests. * * @internal */ export const empty = (): Parallel => new ParallelImpl(HashMap.empty()) /** * Constructs a new collection of requests containing a mapping from the * specified data source to the specified request. * * @internal */ export const make = ( dataSource: DataSource.DataSource, blockedRequest: BlockedRequest.BlockedRequest ): Parallel => new ParallelImpl(HashMap.make([dataSource, Chunk.of(blockedRequest)])) /** * Combines this collection of requests that can be executed in parallel with * that collection of requests that can be executed in parallel to return a * new collection of requests that can be executed in parallel. * * @internal */ export const combine = ( self: Parallel, that: Parallel ): Parallel => new ParallelImpl(HashMap.reduceWithIndex(self.map, that.map, (map, value, key) => HashMap.set( map, key, pipe( HashMap.get(map, key), Option.match(() => value, Chunk.concat(value)) ) ))) /** * Returns `true` if this collection of requests is empty, `false` otherwise. * * @internal */ export const isEmpty = (self: Parallel): boolean => HashMap.isEmpty(self.map) /** * Returns a collection of the data sources that the requests in this * collection are from. * * @internal */ export const keys = ( self: Parallel ): Chunk.Chunk> => Chunk.fromIterable(HashMap.keys(self.map)) as any /** * Converts this collection of requests that can be executed in parallel to a * batch of requests in a collection of requests that must be executed * sequentially. * * @internal */ export const toSequential = ( self: Parallel ): Sequential.Sequential => Sequential.make(HashMap.map(self.map, Chunk.of) as any) /** * Converts this collection of requests that can be executed in parallel to an * `Iterable` containing mappings from data sources to requests from those * data sources. * * @internal */ export const toChunk = ( self: Parallel ): Chunk.Chunk< readonly [ DataSource.DataSource, Chunk.Chunk> ] > => Chunk.fromIterable(self.map) as any