Skip to content

Commit 9951617

Browse files
committed
incremental delivery rewrite
1 parent a81e623 commit 9951617

File tree

8 files changed

+1471
-1233
lines changed

8 files changed

+1471
-1233
lines changed

src/execution/IncrementalPublisher.ts

+509-490
Large diffs are not rendered by default.

src/execution/__tests__/defer-test.ts

+17-33
Original file line numberDiff line numberDiff line change
@@ -367,20 +367,14 @@ describe('Execute: defer directive', () => {
367367
},
368368
id: '0',
369369
},
370-
],
371-
completed: [{ id: '0' }],
372-
hasNext: true,
373-
},
374-
{
375-
incremental: [
376370
{
377371
data: {
378372
friends: [{ name: 'Han' }, { name: 'Leia' }, { name: 'C-3PO' }],
379373
},
380374
id: '1',
381375
},
382376
],
383-
completed: [{ id: '1' }],
377+
completed: [{ id: '0' }, { id: '1' }],
384378
hasNext: false,
385379
},
386380
]);
@@ -674,8 +668,8 @@ describe('Execute: defer directive', () => {
674668
hero: {},
675669
},
676670
pending: [
677-
{ id: '0', path: [], label: 'DeferName' },
678-
{ id: '1', path: ['hero'], label: 'DeferID' },
671+
{ id: '0', path: ['hero'], label: 'DeferID' },
672+
{ id: '1', path: [], label: 'DeferName' },
679673
],
680674
hasNext: true,
681675
},
@@ -685,17 +679,17 @@ describe('Execute: defer directive', () => {
685679
data: {
686680
id: '1',
687681
},
688-
id: '1',
682+
id: '0',
689683
},
690684
{
691685
data: {
692686
name: 'Luke',
693687
},
694-
id: '0',
688+
id: '1',
695689
subPath: ['hero'],
696690
},
697691
],
698-
completed: [{ id: '1' }, { id: '0' }],
692+
completed: [{ id: '0' }, { id: '1' }],
699693
hasNext: false,
700694
},
701695
]);
@@ -983,37 +977,27 @@ describe('Execute: defer directive', () => {
983977
hasNext: true,
984978
},
985979
{
986-
pending: [{ id: '1', path: ['hero', 'nestedObject'] }],
980+
pending: [
981+
{ id: '1', path: ['hero', 'nestedObject'] },
982+
{ id: '2', path: ['hero', 'nestedObject', 'deeperObject'] },
983+
],
987984
incremental: [
988985
{
989986
data: { bar: 'bar' },
990987
id: '0',
991988
subPath: ['nestedObject', 'deeperObject'],
992989
},
993-
],
994-
completed: [{ id: '0' }],
995-
hasNext: true,
996-
},
997-
{
998-
pending: [{ id: '2', path: ['hero', 'nestedObject', 'deeperObject'] }],
999-
incremental: [
1000990
{
1001991
data: { baz: 'baz' },
1002992
id: '1',
1003993
subPath: ['deeperObject'],
1004994
},
1005-
],
1006-
hasNext: true,
1007-
completed: [{ id: '1' }],
1008-
},
1009-
{
1010-
incremental: [
1011995
{
1012996
data: { bak: 'bak' },
1013997
id: '2',
1014998
},
1015999
],
1016-
completed: [{ id: '2' }],
1000+
completed: [{ id: '0' }, { id: '1' }, { id: '2' }],
10171001
hasNext: false,
10181002
},
10191003
]);
@@ -1132,23 +1116,23 @@ describe('Execute: defer directive', () => {
11321116
},
11331117
},
11341118
pending: [
1135-
{ id: '0', path: [] },
1136-
{ id: '1', path: ['a', 'b'] },
1119+
{ id: '0', path: ['a', 'b'] },
1120+
{ id: '1', path: [] },
11371121
],
11381122
hasNext: true,
11391123
},
11401124
{
11411125
incremental: [
11421126
{
11431127
data: { e: { f: 'f' } },
1144-
id: '1',
1128+
id: '0',
11451129
},
11461130
{
11471131
data: { g: { h: 'h' } },
1148-
id: '0',
1132+
id: '1',
11491133
},
11501134
],
1151-
completed: [{ id: '1' }, { id: '0' }],
1135+
completed: [{ id: '0' }, { id: '1' }],
11521136
hasNext: false,
11531137
},
11541138
]);
@@ -1277,6 +1261,7 @@ describe('Execute: defer directive', () => {
12771261
},
12781262
],
12791263
completed: [
1264+
{ id: '0' },
12801265
{
12811266
id: '1',
12821267
errors: [
@@ -1288,7 +1273,6 @@ describe('Execute: defer directive', () => {
12881273
},
12891274
],
12901275
},
1291-
{ id: '0' },
12921276
],
12931277
hasNext: false,
12941278
},

src/execution/__tests__/executor-test.ts

+51
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,57 @@ describe('Execute: Handles basic execution tasks', () => {
635635
expect(isAsyncResolverFinished).to.equal(true);
636636
});
637637

638+
it('handles async bubbling errors combined with non-bubbling errors', async () => {
639+
const schema = new GraphQLSchema({
640+
query: new GraphQLObjectType({
641+
name: 'Query',
642+
fields: {
643+
asyncNonNullError: {
644+
type: new GraphQLNonNull(GraphQLString),
645+
async resolve() {
646+
await resolveOnNextTick();
647+
return null;
648+
},
649+
},
650+
asyncError: {
651+
type: GraphQLString,
652+
async resolve() {
653+
await resolveOnNextTick();
654+
throw new Error('Oops');
655+
},
656+
},
657+
},
658+
}),
659+
});
660+
661+
// Order is important here, as the nullable error should resolve first
662+
const document = parse(`
663+
{
664+
asyncError
665+
asyncNonNullError
666+
}
667+
`);
668+
669+
const result = execute({ schema, document });
670+
671+
expectJSON(await result).toDeepEqual({
672+
data: null,
673+
errors: [
674+
{
675+
message: 'Oops',
676+
locations: [{ line: 3, column: 9 }],
677+
path: ['asyncError'],
678+
},
679+
{
680+
message:
681+
'Cannot return null for non-nullable field Query.asyncNonNullError.',
682+
locations: [{ line: 4, column: 9 }],
683+
path: ['asyncNonNullError'],
684+
},
685+
],
686+
});
687+
});
688+
638689
it('Full response path is included for non-nullable fields', () => {
639690
const A: GraphQLObjectType = new GraphQLObjectType({
640691
name: 'A',

0 commit comments

Comments
 (0)