Skip to content

Commit

Permalink
incremental: disable early execution by default
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacovCR committed May 31, 2024
1 parent 5fc2723 commit 312138f
Show file tree
Hide file tree
Showing 5 changed files with 686 additions and 158 deletions.
13 changes: 11 additions & 2 deletions src/execution/IncrementalGraph.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Future } from '../jsutils/Future.js';
import { isPromise } from '../jsutils/isPromise.js';
import { promiseWithResolvers } from '../jsutils/promiseWithResolvers.js';

Expand Down Expand Up @@ -123,8 +124,13 @@ export class IncrementalGraph {
incrementalDataRecord.streamItemRecords,
);
} else {
const deferredGroupedFieldSetResult =
incrementalDataRecord.deferredGroupedFieldSetResult;
const result =
incrementalDataRecord.deferredGroupedFieldSetResult.value;
deferredGroupedFieldSetResult instanceof Future
? deferredGroupedFieldSetResult.value
: deferredGroupedFieldSetResult();

if (isPromise(result)) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
result.then((resolved) =>
Expand Down Expand Up @@ -315,7 +321,10 @@ export class IncrementalGraph {
let incrementalDataRecords: Array<IncrementalDataRecord> = [];
let streamItemRecord: StreamItemRecord | undefined;
while ((streamItemRecord = streamItemRecords.shift()) !== undefined) {
let result = streamItemRecord.value;
let result =
typeof streamItemRecord === 'function'
? streamItemRecord()
: streamItemRecord.value;
if (isPromise(result)) {
if (items.length > 0) {
this._enqueue({
Expand Down
171 changes: 150 additions & 21 deletions src/execution/__tests__/defer-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,16 @@ const query = new GraphQLObjectType({

const schema = new GraphQLSchema({ query });

async function complete(document: DocumentNode, rootValue: unknown = { hero }) {
async function complete(
document: DocumentNode,
rootValue: unknown = { hero },
enableEarlyExecution = false,
) {
const result = await experimentalExecuteIncrementally({
schema,
document,
rootValue,
enableEarlyExecution,
});

if ('initialResult' in result) {
Expand Down Expand Up @@ -247,6 +252,118 @@ describe('Execute: defer directive', () => {
},
]);
});
it('Does not execute deferred fragments early when not specified', async () => {
const document = parse(`
query HeroNameQuery {
hero {
id
...NameFragment @defer
}
}
fragment NameFragment on Hero {
name
}
`);
const order: Array<string> = [];
const result = await complete(document, {
hero: {
...hero,
id: async () => {
await resolveOnNextTick();
await resolveOnNextTick();
order.push('slow-id');
return hero.id;
},
name: () => {
order.push('fast-name');
return hero.name;
},
},
});

expectJSON(result).toDeepEqual([
{
data: {
hero: {
id: '1',
},
},
pending: [{ id: '0', path: ['hero'] }],
hasNext: true,
},
{
incremental: [
{
data: {
name: 'Luke',
},
id: '0',
},
],
completed: [{ id: '0' }],
hasNext: false,
},
]);
expect(order).to.deep.equal(['slow-id', 'fast-name']);
});
it('Does execute deferred fragments early when specified', async () => {
const document = parse(`
query HeroNameQuery {
hero {
id
...NameFragment @defer
}
}
fragment NameFragment on Hero {
name
}
`);
const order: Array<string> = [];
const result = await complete(
document,
{
hero: {
...hero,
id: async () => {
await resolveOnNextTick();
await resolveOnNextTick();
order.push('slow-id');
return hero.id;
},
name: () => {
order.push('fast-name');
return hero.name;
},
},
},
true,
);

expectJSON(result).toDeepEqual([
{
data: {
hero: {
id: '1',
},
},
pending: [{ id: '0', path: ['hero'] }],
hasNext: true,
},
{
incremental: [
{
data: {
name: 'Luke',
},
id: '0',
},
],
completed: [{ id: '0' }],
hasNext: false,
},
]);
expect(order).to.deep.equal(['fast-name', 'slow-id']);
});
it('Can defer fragments on the top level Query field', async () => {
const document = parse(`
query HeroNameQuery {
Expand Down Expand Up @@ -1492,20 +1609,24 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document, {
a: {
b: {
c: {
d: 'd',
nonNullErrorField: async () => {
await resolveOnNextTick();
return null;
const result = await complete(
document,
{
a: {
b: {
c: {
d: 'd',
nonNullErrorField: async () => {
await resolveOnNextTick();
return null;
},
},
},
someField: 'someField',
},
someField: 'someField',
},
});
true,
);
expectJSON(result).toDeepEqual([
{
data: {
Expand Down Expand Up @@ -1564,12 +1685,16 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document, {
hero: {
...hero,
nonNullName: () => null,
const result = await complete(
document,
{
hero: {
...hero,
nonNullName: () => null,
},
},
});
true,
);
expectJSON(result).toDeepEqual({
data: {
hero: null,
Expand All @@ -1596,12 +1721,16 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document, {
hero: {
...hero,
nonNullName: () => null,
const result = await complete(
document,
{
hero: {
...hero,
nonNullName: () => null,
},
},
});
true,
);
expectJSON(result).toDeepEqual([
{
data: {},
Expand Down
Loading

0 comments on commit 312138f

Please sign in to comment.