Skip to content

rename executeImpl to executeOperation #4045

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 98 additions & 86 deletions src/execution/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,38 +234,103 @@ export function experimentalExecuteIncrementally(
return { errors: exeContext };
}

return executeImpl(exeContext);
return executeOperation(exeContext);
}

function executeImpl(
/**
* Implements the "Executing operations" section of the spec.
*
* Returns a Promise that will eventually resolve to the data described by
* The "Response" section of the GraphQL specification.
*
* If errors are encountered while executing a GraphQL field, only that
* field and its descendants will be omitted, and sibling fields will still
* be executed. An execution which encounters errors will still result in a
* resolved Promise.
*
* Errors from sub-fields of a NonNull type may propagate to the top level,
* at which point we still log the error and null the parent field, which
* in this case is the entire response.
*/
function executeOperation(
exeContext: ExecutionContext,
): PromiseOrValue<ExecutionResult | ExperimentalIncrementalExecutionResults> {
// Return a Promise that will eventually resolve to the data described by
// The "Response" section of the GraphQL specification.
//
// If errors are encountered while executing a GraphQL field, only that
// field and its descendants will be omitted, and sibling fields will still
// be executed. An execution which encounters errors will still result in a
// resolved Promise.
//
// Errors from sub-fields of a NonNull type may propagate to the top level,
// at which point we still log the error and null the parent field, which
// in this case is the entire response.
const incrementalPublisher = exeContext.incrementalPublisher;
const initialResultRecord = new InitialResultRecord();
try {
const data = executeOperation(exeContext, initialResultRecord);
if (isPromise(data)) {
return data.then(
const {
operation,
schema,
fragments,
variableValues,
rootValue,
incrementalPublisher,
} = exeContext;
const rootType = schema.getRootType(operation.operation);
if (rootType == null) {
throw new GraphQLError(
`Schema is not configured to execute ${operation.operation} operation.`,
{ nodes: operation },
);
}

const { fields, newDeferUsages } = collectFields(
schema,
fragments,
variableValues,
rootType,
operation,
);
const { groupedFieldSet, newGroupedFieldSetDetailsMap } =
buildFieldPlan(fields);

const newDeferMap = addNewDeferredFragments(
incrementalPublisher,
newDeferUsages,
initialResultRecord,
);

const path = undefined;

const newDeferredGroupedFieldSetRecords = addNewDeferredGroupedFieldSets(
incrementalPublisher,
newGroupedFieldSetDetailsMap,
newDeferMap,
path,
);

const result = executeRootGroupedFieldSet(
exeContext,
operation.operation,
rootType,
rootValue,
groupedFieldSet,
initialResultRecord,
newDeferMap,
);

executeDeferredGroupedFieldSets(
exeContext,
rootType,
rootValue,
path,
newDeferredGroupedFieldSetRecords,
newDeferMap,
);

if (isPromise(result)) {
return result.then(
(resolved) =>
incrementalPublisher.buildDataResponse(initialResultRecord, resolved),
(error) =>
incrementalPublisher.buildErrorResponse(initialResultRecord, error),
);
}
return incrementalPublisher.buildDataResponse(initialResultRecord, data);
return incrementalPublisher.buildDataResponse(initialResultRecord, result);
} catch (error) {
return incrementalPublisher.buildErrorResponse(initialResultRecord, error);
return exeContext.incrementalPublisher.buildErrorResponse(
initialResultRecord,
error,
);
}
}

Expand Down Expand Up @@ -384,102 +449,49 @@ function buildPerEventExecutionContext(
};
}

/**
* Implements the "Executing operations" section of the spec.
*/
function executeOperation(
function executeRootGroupedFieldSet(
exeContext: ExecutionContext,
operation: OperationTypeNode,
rootType: GraphQLObjectType,
rootValue: unknown,
groupedFieldSet: GroupedFieldSet,
initialResultRecord: InitialResultRecord,
newDeferMap: ReadonlyMap<DeferUsage, DeferredFragmentRecord>,
): PromiseOrValue<ObjMap<unknown>> {
const {
operation,
schema,
fragments,
variableValues,
rootValue,
incrementalPublisher,
} = exeContext;
const rootType = schema.getRootType(operation.operation);
if (rootType == null) {
throw new GraphQLError(
`Schema is not configured to execute ${operation.operation} operation.`,
{ nodes: operation },
);
}

const { fields, newDeferUsages } = collectFields(
schema,
fragments,
variableValues,
rootType,
operation,
);
const { groupedFieldSet, newGroupedFieldSetDetailsMap } =
buildFieldPlan(fields);

const newDeferMap = addNewDeferredFragments(
incrementalPublisher,
newDeferUsages,
initialResultRecord,
);

const path = undefined;

const newDeferredGroupedFieldSetRecords = addNewDeferredGroupedFieldSets(
incrementalPublisher,
newGroupedFieldSetDetailsMap,
newDeferMap,
path,
);

let result;
switch (operation.operation) {
switch (operation) {
case OperationTypeNode.QUERY:
result = executeFields(
return executeFields(
exeContext,
rootType,
rootValue,
path,
undefined,
groupedFieldSet,
initialResultRecord,
newDeferMap,
);
break;
case OperationTypeNode.MUTATION:
result = executeFieldsSerially(
return executeFieldsSerially(
exeContext,
rootType,
rootValue,
path,
undefined,
groupedFieldSet,
initialResultRecord,
newDeferMap,
);
break;
case OperationTypeNode.SUBSCRIPTION:
// TODO: deprecate `subscribe` and move all logic here
// Temporary solution until we finish merging execute and subscribe together
result = executeFields(
return executeFields(
exeContext,
rootType,
rootValue,
path,
undefined,
groupedFieldSet,
initialResultRecord,
newDeferMap,
);
}

executeDeferredGroupedFieldSets(
exeContext,
rootType,
rootValue,
path,
newDeferredGroupedFieldSetRecords,
newDeferMap,
);

return result;
}

/**
Expand Down Expand Up @@ -1725,7 +1737,7 @@ function mapSourceToResponse(
return mapAsyncIterable(
resultOrStream,
(payload: unknown) =>
executeImpl(
executeOperation(
buildPerEventExecutionContext(exeContext, payload),
// typecast to ExecutionResult, not possible to return
// ExperimentalIncrementalExecutionResults when
Expand Down