UNPKG

graphql

Version:

A Query Language and Runtime which can target any service.

1 lines 15.5 kB
{"version":3,"file":"IncrementalPublisher.js","sourceRoot":"","sources":["../../../src/execution/incremental/IncrementalPublisher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ObjMap } from '../../jsutils/ObjMap.ts';\nimport { pathToArray } from '../../jsutils/Path.ts';\n\nimport { ensureGraphQLError } from '../../error/ensureGraphQLError.ts';\nimport type { GraphQLError } from '../../error/GraphQLError.ts';\n\nimport { mapAsyncIterable } from '../mapAsyncIterable.ts';\nimport { withConcurrentAbruptClose } from '../withConcurrentAbruptClose.ts';\n\nimport type {\n CompletedResult,\n DeliveryGroup,\n ExecutionGroupValue,\n ExperimentalIncrementalExecutionResults,\n IncrementalDeferResult,\n IncrementalResult,\n IncrementalWork,\n InitialIncrementalExecutionResult,\n ItemStream,\n PendingResult,\n StreamItemValue,\n SubsequentIncrementalExecutionResult,\n} from './IncrementalExecutor.ts';\nimport type { WorkQueueEvent } from './WorkQueue.ts';\nimport { createWorkQueue } from './WorkQueue.ts';\n\ninterface SubsequentIncrementalExecutionResultContext {\n pending: Array<PendingResult>;\n incremental: Array<IncrementalResult>;\n completed: Array<CompletedResult>;\n hasNext: boolean;\n}\n\n/** @internal */\nexport class IncrementalPublisher {\n private _ids: Map<DeliveryGroup | ItemStream, string>;\n private _nextId: number;\n\n constructor() {\n this._ids = new Map();\n this._nextId = 0;\n }\n\n buildResponse(\n data: ObjMap<unknown>,\n errors: ReadonlyArray<GraphQLError>,\n work: IncrementalWork,\n abortSignal: AbortSignal | undefined,\n onFinished: () => void,\n ): ExperimentalIncrementalExecutionResults {\n const { initialGroups, initialStreams, events } = createWorkQueue<\n ExecutionGroupValue,\n StreamItemValue,\n DeliveryGroup,\n ItemStream\n >(work);\n\n function abort(): void {\n subsequentResults.throw(abortSignal?.reason).catch(() => {\n // Ignore errors\n });\n }\n\n if (abortSignal) {\n abortSignal.addEventListener('abort', abort);\n }\n const onWorkQueueFinished = () => {\n onFinished();\n abortSignal?.removeEventListener('abort', abort);\n };\n\n const pending = this._toPendingResults(initialGroups, initialStreams);\n\n const initialResult: InitialIncrementalExecutionResult = errors.length\n ? { errors, data, pending, hasNext: true }\n : { data, pending, hasNext: true };\n\n const subsequentResults = withConcurrentAbruptClose(\n mapAsyncIterable(events, (batch) =>\n this._handleBatch(batch, onWorkQueueFinished),\n ),\n () => onWorkQueueFinished(),\n );\n\n return {\n initialResult,\n subsequentResults,\n };\n }\n\n private _ensureId(\n deferredFragmentOrStream: DeliveryGroup | ItemStream,\n ): string {\n let id = this._ids.get(deferredFragmentOrStream);\n if (id !== undefined) {\n return id;\n }\n id = String(this._nextId++);\n this._ids.set(deferredFragmentOrStream, id);\n return id;\n }\n\n private _toPendingResults(\n newGroups: ReadonlyArray<DeliveryGroup>,\n newStreams: ReadonlyArray<ItemStream>,\n ): Array<PendingResult> {\n const pendingResults: Array<PendingResult> = [];\n for (const collection of [newGroups, newStreams]) {\n for (const node of collection) {\n const id = this._ensureId(node);\n const pendingResult: PendingResult = {\n id,\n path: pathToArray(node.path),\n };\n if (node.label !== undefined) {\n pendingResult.label = node.label;\n }\n pendingResults.push(pendingResult);\n }\n }\n return pendingResults;\n }\n\n private _handleBatch(\n batch: ReadonlyArray<\n WorkQueueEvent<\n ExecutionGroupValue,\n StreamItemValue,\n DeliveryGroup,\n ItemStream\n >\n >,\n onWorkQueueFinished: (() => void) | undefined,\n ): SubsequentIncrementalExecutionResult {\n const context: SubsequentIncrementalExecutionResultContext = {\n pending: [],\n incremental: [],\n completed: [],\n hasNext: true,\n };\n\n for (const event of batch) {\n this._handleWorkQueueEvent(event, context, onWorkQueueFinished);\n }\n\n const { incremental, completed, pending, hasNext } = context;\n\n const result: SubsequentIncrementalExecutionResult = { hasNext };\n if (pending.length > 0) {\n result.pending = pending;\n }\n if (incremental.length > 0) {\n result.incremental = incremental;\n }\n if (completed.length > 0) {\n result.completed = completed;\n }\n\n return result;\n }\n\n private _handleWorkQueueEvent(\n event: WorkQueueEvent<\n ExecutionGroupValue,\n StreamItemValue,\n DeliveryGroup,\n ItemStream\n >,\n context: SubsequentIncrementalExecutionResultContext,\n onWorkQueueFinished: (() => void) | undefined,\n ): void {\n switch (event.kind) {\n case 'GROUP_VALUES': {\n const group = event.group;\n const id = this._ensureId(group);\n for (const value of event.values) {\n const { bestId, subPath } = this._getBestIdAndSubPath(\n id,\n group,\n value,\n );\n const incrementalEntry: IncrementalDeferResult = {\n id: bestId,\n data: value.data,\n };\n if (value.errors !== undefined) {\n incrementalEntry.errors = value.errors;\n }\n if (subPath !== undefined) {\n incrementalEntry.subPath = subPath;\n }\n context.incremental.push(incrementalEntry);\n }\n break;\n }\n case 'GROUP_SUCCESS': {\n const group = event.group;\n const id = this._ensureId(group);\n context.completed.push({ id });\n this._ids.delete(group);\n if (event.newGroups.length > 0 || event.newStreams.length > 0) {\n context.pending.push(\n ...this._toPendingResults(event.newGroups, event.newStreams),\n );\n }\n break;\n }\n case 'GROUP_FAILURE': {\n const { group, error } = event;\n const id = this._ensureId(group);\n context.completed.push({\n id,\n errors: [ensureGraphQLError(error)],\n });\n this._ids.delete(group);\n break;\n }\n case 'STREAM_VALUES': {\n const stream = event.stream;\n const id = this._ensureId(stream);\n const { values, newGroups, newStreams } = event;\n const items: Array<unknown> = [];\n const errors: Array<GraphQLError> = [];\n for (const value of values) {\n items.push(value.item);\n if (value.errors !== undefined) {\n errors.push(...value.errors);\n }\n }\n context.incremental.push(\n errors.length > 0 ? { id, items, errors } : { id, items },\n );\n if (newGroups.length > 0 || newStreams.length > 0) {\n context.pending.push(\n ...this._toPendingResults(newGroups, newStreams),\n );\n }\n break;\n }\n case 'STREAM_SUCCESS': {\n const stream = event.stream;\n context.completed.push({\n id: this._ensureId(stream),\n });\n this._ids.delete(stream);\n break;\n }\n case 'STREAM_FAILURE': {\n const stream = event.stream;\n context.completed.push({\n id: this._ensureId(stream),\n errors: [ensureGraphQLError(event.error)],\n });\n this._ids.delete(stream);\n break;\n }\n case 'WORK_QUEUE_TERMINATION': {\n onWorkQueueFinished?.();\n context.hasNext = false;\n break;\n }\n }\n }\n\n private _getBestIdAndSubPath(\n initialId: string,\n initialDeferredFragmentRecord: DeliveryGroup,\n executionGroupValue: ExecutionGroupValue,\n ): { bestId: string; subPath: ReadonlyArray<string | number> | undefined } {\n let maxLength = pathToArray(initialDeferredFragmentRecord.path).length;\n let bestId = initialId;\n\n for (const deliveryGroup of executionGroupValue.deliveryGroups) {\n if (deliveryGroup === initialDeferredFragmentRecord) {\n continue;\n }\n const id = this._ids.get(deliveryGroup);\n // TODO: Investigate why there is no coverage gap using node native test coverage.\n if (id === undefined) {\n continue;\n }\n const path = pathToArray(deliveryGroup.path);\n const length = path.length;\n if (length > maxLength) {\n maxLength = length;\n bestId = id;\n }\n }\n const subPath = executionGroupValue.path.slice(maxLength);\n return {\n bestId,\n subPath: subPath.length > 0 ? subPath : undefined,\n };\n }\n}\n"]}