@@ -308,6 +308,10 @@ response fields contained in the deferred fragment are not known to be complete.
308
308
Clients should expect the the GraphQL Service to incrementally deliver the
309
309
remainder of the fields contained in the deferred fragment.
310
310
311
+ If the associated ` @defer ` or ` @stream ` directive contains a ` label ` argument,
312
+ the Pending Result must contain an entry ` label ` with the value of this
313
+ argument.
314
+
311
315
If a Pending Result is not returned for a ` @defer ` or ` @stream ` directive,
312
316
clients must assume that the GraphQL service chose not to incrementally deliver
313
317
this data, and the data can be found either in the ` data ` entry in the initial
@@ -426,7 +430,199 @@ present, it informs clients that the delivery of the data associated with the
426
430
corresponding Pending Result has failed, due to an error bubbling to a path
427
431
higher than the Incremental Data Result's path. The ` errors ` entry must contain
428
432
these field errors. The value of this entry is described in the "Errors"
429
- section.e
433
+ section.
434
+
435
+ ### Examples
436
+
437
+ #### A query containing both defer and stream:
438
+
439
+ ``` graphql example
440
+ query {
441
+ person (id : " cGVvcGxlOjE=" ) {
442
+ ... HomeWorldFragment @defer (label : " homeWorldDefer" )
443
+ name
444
+ films @stream (initialCount : 1 , label : " filmsStream" ) {
445
+ title
446
+ }
447
+ }
448
+ }
449
+ fragment HomeWorldFragment on Person {
450
+ homeWorld {
451
+ name
452
+ }
453
+ }
454
+ ```
455
+
456
+ The response stream might look like:
457
+
458
+ Payload 1, the initial response does not contain any deferred or streamed
459
+ results in the ` data ` entry. The initial response contains a ` hasNext ` entry,
460
+ indicating that subsequent payloads will be delivered. There are two Pending
461
+ Responses indicating that results for both the ` @defer ` and ` @stream ` in the
462
+ query will be delivered in the subsequent payloads.
463
+
464
+ ``` json example
465
+ {
466
+ "data" : {
467
+ "person" : {
468
+ "name" : " Luke Skywalker" ,
469
+ "films" : [{ "title" : " A New Hope" }]
470
+ }
471
+ },
472
+ "pending" : [
473
+ { "id" : " 0" , "path" : [" person" ], "label" : " homeWorldDefer" },
474
+ { "id" : " 1" , "path" : [" person" , " films" ], "label" : " filmsStream" }
475
+ ],
476
+ "hasNext" : true
477
+ }
478
+ ```
479
+
480
+ Payload 2, contains the deferred data and the first streamed list item. There is
481
+ one Completed Result, indicating that the deferred data has been completely
482
+ delivered.
483
+
484
+ ``` json example
485
+ {
486
+ "incremental" : [
487
+ {
488
+ "id" : " 0" ,
489
+ "data" : { "homeWorld" : { "name" : " Tatooine" } }
490
+ },
491
+ {
492
+ "id" : " 1" ,
493
+ "items" : [{ "title" : " The Empire Strikes Back" }]
494
+ }
495
+ ],
496
+ "completed" : [
497
+ {"id" : " 0" }
498
+ ]
499
+ "hasNext" : true
500
+ }
501
+ ```
502
+
503
+ Payload 3, contains the final stream payload. In this example, the underlying
504
+ iterator does not close synchronously so {hasNext} is set to {true}. If this
505
+ iterator did close synchronously, {hasNext} would be set to {false} and this
506
+ would be the final response.
507
+
508
+ ``` json example
509
+ {
510
+ "incremental" : [
511
+ {
512
+ "id" : " 1" ,
513
+ "items" : [{ "title" : " Return of the Jedi" }]
514
+ }
515
+ ],
516
+ "hasNext" : true
517
+ }
518
+ ```
519
+
520
+ Payload 4, contains no incremental data. {hasNext} set to {false} indicates the
521
+ end of the response stream. This response is sent when the underlying iterator
522
+ of the ` films ` field closes.
523
+
524
+ ``` json example
525
+ {
526
+ "hasNext" : false
527
+ }
528
+ ```
529
+
530
+ ### Examples
531
+
532
+ #### A query containing overlapping defers:
533
+
534
+ ``` graphql example
535
+ query {
536
+ person (id : " cGVvcGxlOjE=" ) {
537
+ ... HomeWorldFragment @defer (label : " homeWorldDefer" )
538
+ ... NameAndHomeWorldFragment @defer (label : " nameAndWorld" )
539
+ firstName
540
+ }
541
+ }
542
+ fragment HomeWorldFragment on Person {
543
+ homeWorld {
544
+ name
545
+ terrain
546
+ }
547
+ }
548
+
549
+ fragment NameAndHomeWorldFragment on Person {
550
+ firstName
551
+ lastName
552
+ homeWorld {
553
+ name
554
+ }
555
+ }
556
+ ```
557
+
558
+ The response stream might look like:
559
+
560
+ Payload 1, the initial response contains the results of the ` firstName ` field.
561
+ Even though it is also present in the ` HomeWorldFragment ` , it must be returned
562
+ in the initial payload because it is also defined outside of any fragments with
563
+ the ` @defer ` directive. Additionally, There are two Pending Responses indicating
564
+ that results for both ` @defer ` s in the query will be delivered in the subsequent
565
+ payloads.
566
+
567
+ ``` json example
568
+ {
569
+ "data" : {
570
+ "person" : {
571
+ "firstName" : " Luke"
572
+ }
573
+ },
574
+ "pending" : [
575
+ { "id" : " 0" , "path" : [" person" ], "label" : " homeWorldDefer" },
576
+ { "id" : " 1" , "path" : [" person" ], "label" : " nameAndWorld" }
577
+ ],
578
+ "hasNext" : true
579
+ }
580
+ ```
581
+
582
+ Payload 2, contains the deferred data from ` HomeWorldFragment ` . There is one
583
+ Completed Result, indicating that ` HomeWorldFragment ` has been completely
584
+ delivered. Because the ` homeWorld ` field is present in two separate ` @defer ` s,
585
+ it is separated into its own Incremental Result.
586
+
587
+ The second Incremental Result contains the data for the ` terrain ` field. This
588
+ incremental result contains a ` subPath ` property to indicate to clients that the
589
+ path of this result can be determined by concatenating the path from the Pending
590
+ Result with id ` "0" ` and this ` subPath ` entry.
591
+
592
+ ``` json example
593
+ {
594
+ "incremental" : [
595
+ {
596
+ "id" : " 0" ,
597
+ "data" : { "homeWorld" : { "name" : " Tatooine" } }
598
+ },
599
+ {
600
+ "id" : " 0" ,
601
+ "subPath" : [" homeWorld" ],
602
+ "data" : { "terrain" : " desert" }
603
+ }
604
+ ],
605
+ "completed" : [{ "id" : " 0" }],
606
+ "hasNext" : true
607
+ }
608
+ ```
609
+
610
+ Payload 3, contains the remaining data from the ` NameAndHomeWorldFragment ` .
611
+ ` lastName ` is the only remaining field that has not been delivered in a previous
612
+ payload.
613
+
614
+ ``` json example
615
+ {
616
+ "incremental" : [
617
+ {
618
+ "id" : " 1" ,
619
+ "data" : { "lastName" : " Skywalker" }]
620
+ }
621
+ ],
622
+ "completed" : [{"id" : " 1" }],
623
+ "hasNext" : false
624
+ }
625
+ ```
430
626
431
627
## Serialization Format
432
628
@@ -504,3 +700,7 @@ encode the same value, they also have observably different property orderings.
504
700
505
701
Note: This does not violate the JSON spec, as clients may still interpret
506
702
objects in the response as unordered Maps and arrive at a valid value.
703
+
704
+ ```
705
+
706
+ ```
0 commit comments