@@ -372,37 +372,21 @@ def execute_operation(
372372 collected_fields = collect_fields (
373373 schema , self .fragments , self .variable_values , root_type , operation
374374 )
375+
375376 grouped_field_set , new_defer_usages = collected_fields
376377
377- if new_defer_usages :
378- execution_plan = build_execution_plan (grouped_field_set )
379- grouped_field_set = execution_plan .grouped_field_set
380- new_grouped_field_sets = execution_plan .new_grouped_field_sets
381- new_defer_map = add_new_deferred_fragments (new_defer_usages , RefMap ())
382- graphql_wrapped_result = self .execute_root_grouped_field_set (
383- operation .operation ,
378+ graphql_wrapped_result = (
379+ self .execute_execution_plan (
384380 root_type ,
385381 root_value ,
386- grouped_field_set ,
387- new_defer_map ,
382+ new_defer_usages ,
383+ build_execution_plan ( grouped_field_set ) ,
388384 )
389- if new_grouped_field_sets :
390- new_pending_execution_groups = self .collect_execution_groups (
391- root_type ,
392- root_value ,
393- None ,
394- None ,
395- new_grouped_field_sets ,
396- new_defer_map ,
397- )
398- graphql_wrapped_result = self .with_new_execution_groups (
399- graphql_wrapped_result , new_pending_execution_groups
400- )
401-
402- else :
403- graphql_wrapped_result = self .execute_root_grouped_field_set (
385+ if new_defer_usages
386+ else self .execute_root_grouped_field_set (
404387 operation .operation , root_type , root_value , grouped_field_set , None
405388 )
389+ )
406390
407391 if self .is_awaitable (graphql_wrapped_result ):
408392
@@ -426,6 +410,45 @@ async def await_result() -> (
426410
427411 return self .build_data_response (resolved .result , resolved .increments )
428412
413+ def execute_execution_plan (
414+ self ,
415+ return_type : GraphQLObjectType ,
416+ source_value : Any ,
417+ new_defer_usages : list [DeferUsage ],
418+ execution_plan : ExecutionPlan ,
419+ path : Path | None = None ,
420+ incremental_context : IncrementalContext | None = None ,
421+ defer_map : RefMap [DeferUsage , DeferredFragmentRecord ] | None = None ,
422+ ) -> AwaitableOrValue [GraphQLWrappedResult [dict [str , Any ]]]:
423+ """Execute an execution plan."""
424+ new_defer_map = get_new_defer_map (new_defer_usages , defer_map , path )
425+
426+ grouped_field_set , new_grouped_field_sets = execution_plan
427+
428+ graphql_wrapped_result = self .execute_fields (
429+ return_type ,
430+ source_value ,
431+ path ,
432+ grouped_field_set ,
433+ incremental_context ,
434+ new_defer_map ,
435+ )
436+
437+ if new_grouped_field_sets :
438+ new_pending_execution_groups = self .collect_execution_groups (
439+ return_type ,
440+ source_value ,
441+ path ,
442+ incremental_context .defer_usage_set if incremental_context else None ,
443+ new_grouped_field_sets ,
444+ new_defer_map ,
445+ )
446+ return self .with_new_execution_groups (
447+ graphql_wrapped_result , new_pending_execution_groups
448+ )
449+
450+ return graphql_wrapped_result
451+
429452 def execute_root_grouped_field_set (
430453 self ,
431454 operation : OperationType ,
@@ -1479,46 +1502,27 @@ def collect_and_execute_subfields(
14791502 """Collect sub-fields to execute to complete this value."""
14801503 collected_subfields = self .collect_subfields (return_type , field_group )
14811504 grouped_field_set , new_defer_usages = collected_subfields
1482- if defer_map is None and not new_defer_usages :
1483- return self .execute_fields (
1505+
1506+ return (
1507+ self .execute_fields (
14841508 return_type , result , path , grouped_field_set , incremental_context , None
14851509 )
1486- sub_execution_plan = self .build_sub_execution_plan (
1487- grouped_field_set ,
1488- incremental_context .defer_usage_set if incremental_context else None ,
1489- )
1490-
1491- grouped_field_set , new_grouped_field_sets = sub_execution_plan
1492-
1493- new_defer_map = add_new_deferred_fragments (
1494- new_defer_usages ,
1495- RefMap (defer_map .items ()) if defer_map else RefMap (),
1496- path ,
1497- )
1498-
1499- sub_fields = self .execute_fields (
1500- return_type ,
1501- result ,
1502- path ,
1503- grouped_field_set ,
1504- incremental_context ,
1505- new_defer_map ,
1506- )
1507-
1508- if new_grouped_field_sets :
1509- new_deferred_grouped_field_set_records = self .collect_execution_groups (
1510+ if defer_map is None and not new_defer_usages
1511+ else self .execute_execution_plan (
15101512 return_type ,
15111513 result ,
1514+ new_defer_usages ,
1515+ self .build_sub_execution_plan (
1516+ grouped_field_set ,
1517+ incremental_context .defer_usage_set
1518+ if incremental_context
1519+ else None ,
1520+ ),
15121521 path ,
1513- incremental_context .defer_usage_set if incremental_context else None ,
1514- new_grouped_field_sets ,
1515- new_defer_map ,
1516- )
1517- return self .with_new_execution_groups (
1518- sub_fields , new_deferred_grouped_field_set_records
1522+ incremental_context ,
1523+ defer_map ,
15191524 )
1520-
1521- return sub_fields
1525+ )
15221526
15231527 def collect_subfields (
15241528 self , return_type : GraphQLObjectType , field_group : FieldGroup
@@ -2289,27 +2293,22 @@ def deferred_fragment_record_from_defer_usage(
22892293 return defer_map [defer_usage ]
22902294
22912295
2292- def add_new_deferred_fragments (
2296+ def get_new_defer_map (
22932297 new_defer_usages : Sequence [DeferUsage ],
2294- new_defer_map : RefMap [DeferUsage , DeferredFragmentRecord ],
2298+ defer_map : RefMap [DeferUsage , DeferredFragmentRecord ] | None ,
22952299 path : Path | None = None ,
22962300) -> RefMap [DeferUsage , DeferredFragmentRecord ]:
2297- """Add new deferred fragments to the defer map.
2301+ """Get the new defer map.
22982302
22992303 Instantiates new DeferredFragmentRecords for the given path within an
23002304 incremental data record, returning an updated map of DeferUsage
23012305 objects to DeferredFragmentRecords.
23022306
23032307 Note: As defer directives may be used with operations returning lists,
23042308 a DeferUsage object may correspond to many DeferredFragmentRecords.
2305-
2306- DeferredFragmentRecord creation includes the following steps:
2307- 1. The new DeferredFragmentRecord is instantiated at the given path.
2308- 2. The parent result record is calculated from the given incremental data record.
2309- 3. The IncrementalPublisher is notified that a new DeferredFragmentRecord
2310- with the calculated parent has been added; the record will be released only
2311- after the parent has completed.
23122309 """
2310+ new_defer_map = RefMap (None if defer_map is None else defer_map .items ())
2311+
23132312 # For each new DeferUsage object:
23142313 for new_defer_usage in new_defer_usages :
23152314 parent_defer_usage = new_defer_usage .parent_defer_usage
0 commit comments