Skip to content

Commit 656add9

Browse files
committed
refactor: subscribe: introduce new buildPerEventExecutionContext
= introduces `buildPerEventExecutionContext` that creates an `ExecutionContext` for each subscribe event from the original `ExecutionContext` used to create the event stream = `subscribe` now directly builds the `ExecutionContext` instead of relying on `createSourceEventStream` = introduces `createSourceEventStreamImpl` and `executeImpl` functions that operate on the built `ExecutionContext` rather the `ExecutionArgs` = `subscribe` calls the `createSourceEventStreamImpl` function on the original context and eventuallys calls `executeImpl` on the per event context created by `buildEventExecutionContext`. Motivation: 1. remove unnecessary `buildExecutionContext` call, reducing duplicate work 2. paves the way for easily enhancing the `buildPerEventExecutionContext` to add a new `perEventContextFactory` argument to augment the context argument passed to resolvers as need per event. depends on #3638
1 parent cfbc023 commit 656add9

File tree

1 file changed

+37
-8
lines changed

1 file changed

+37
-8
lines changed

src/execution/execute.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ export function execute(args: ExecutionArgs): PromiseOrValue<ExecutionResult> {
174174
return { errors: exeContext };
175175
}
176176

177+
return executeImpl(exeContext);
178+
}
179+
180+
function executeImpl(
181+
exeContext: ExecutionContext,
182+
): PromiseOrValue<ExecutionResult> {
177183
// Return a Promise that will eventually resolve to the data described by
178184
// The "Response" section of the GraphQL specification.
179185
//
@@ -320,6 +326,17 @@ export function buildExecutionContext(
320326
};
321327
}
322328

329+
function buildPerEventExecutionContext(
330+
exeContext: ExecutionContext,
331+
payload: unknown,
332+
): ExecutionContext {
333+
return {
334+
...exeContext,
335+
rootValue: payload,
336+
errors: [],
337+
};
338+
}
339+
323340
/**
324341
* Implements the "Executing operations" section of the spec.
325342
*/
@@ -1019,20 +1036,29 @@ export function subscribe(
10191036
): PromiseOrValue<
10201037
AsyncGenerator<ExecutionResult, void, void> | ExecutionResult
10211038
> {
1022-
const resultOrStream = createSourceEventStream(args);
1039+
// If a valid execution context cannot be created due to incorrect arguments,
1040+
// a "Response" with only errors is returned.
1041+
const exeContext = buildExecutionContext(args);
1042+
1043+
// Return early errors if execution context failed.
1044+
if (!('schema' in exeContext)) {
1045+
return { errors: exeContext };
1046+
}
1047+
1048+
const resultOrStream = createSourceEventStreamImpl(exeContext);
10231049

10241050
if (isPromise(resultOrStream)) {
10251051
return resultOrStream.then((resolvedResultOrStream) =>
1026-
mapSourceToResponse(resolvedResultOrStream, args),
1052+
mapSourceToResponse(exeContext, resolvedResultOrStream),
10271053
);
10281054
}
10291055

1030-
return mapSourceToResponse(resultOrStream, args);
1056+
return mapSourceToResponse(exeContext, resultOrStream);
10311057
}
10321058

10331059
function mapSourceToResponse(
1060+
exeContext: ExecutionContext,
10341061
resultOrStream: ExecutionResult | AsyncIterable<unknown>,
1035-
args: ExecutionArgs,
10361062
): PromiseOrValue<
10371063
AsyncGenerator<ExecutionResult, void, void> | ExecutionResult
10381064
> {
@@ -1047,10 +1073,7 @@ function mapSourceToResponse(
10471073
// "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the
10481074
// "ExecuteQuery" algorithm, for which `execute` is also used.
10491075
return mapAsyncIterator(resultOrStream, (payload: unknown) =>
1050-
execute({
1051-
...args,
1052-
rootValue: payload,
1053-
}),
1076+
executeImpl(buildPerEventExecutionContext(exeContext, payload)),
10541077
);
10551078
}
10561079

@@ -1094,6 +1117,12 @@ export function createSourceEventStream(
10941117
return { errors: exeContext };
10951118
}
10961119

1120+
return createSourceEventStreamImpl(exeContext);
1121+
}
1122+
1123+
function createSourceEventStreamImpl(
1124+
exeContext: ExecutionContext,
1125+
): PromiseOrValue<AsyncIterable<unknown> | ExecutionResult> {
10971126
try {
10981127
const eventStream = executeSubscription(exeContext);
10991128
if (isPromise(eventStream)) {

0 commit comments

Comments
 (0)