@@ -7,154 +7,38 @@ import graphql.nadel.engine.util.emptyOrSingle
77import graphql.nadel.engine.util.makeFieldCoordinates
88import graphql.nadel.engine.util.mapFrom
99import graphql.nadel.engine.util.strictAssociateBy
10- import graphql.nadel.hints.NadelValidationBlueprintHint
1110import graphql.normalized.ExecutableNormalizedField
1211import graphql.schema.FieldCoordinates
1312import graphql.schema.GraphQLSchema
1413
1514/* *
1615 * Execution blueprint where keys are in terms of the overall schema.
1716 */
18- interface NadelOverallExecutionBlueprint {
19- val engineSchema: GraphQLSchema
20-
21- val fieldInstructions: Map <FieldCoordinates , List <NadelFieldInstruction >>
22-
23- fun getUnderlyingTypeNamesForService (service : Service ): Set <String >
24-
25- fun getOverAllTypeNamesForService (service : Service ): Set <String >
26-
27- fun getUnderlyingTypeName (
28- service : Service ,
29- overallTypeName : String ,
30- ): String
31-
32- fun getUnderlyingTypeName (overallTypeName : String ): String
33-
34- fun getRename (overallTypeName : String ): NadelTypeRenameInstruction ?
35-
36- fun getOverallTypeName (
37- service : Service ,
38- underlyingTypeName : String ,
39- ): String
40-
41- fun getServiceOwning (fieldCoordinates : FieldCoordinates ): Service ?
42- }
43-
44- /* *
45- * Can't put inline function inside interface, so made it an extension function.
46- *
47- * This is temporary until we delete [NadelOverallExecutionBlueprintMigrator].
48- */
49- inline fun <reified T : NadelFieldInstruction > NadelOverallExecutionBlueprint.getInstructionInsideVirtualType (
50- hydrationDetails : ServiceExecutionHydrationDetails ? ,
51- backingField : ExecutableNormalizedField ,
52- ): Map <GraphQLObjectTypeName , List <T >> {
53- hydrationDetails ? : return emptyMap() // Need hydration to provide virtual hydration context
54-
55- val backingFieldParentTypeName = backingField.objectTypeNames.singleOrNull()
56- ? : return emptyMap() // Don't support abstract types for now
57-
58- val nadelHydrationContext = fieldInstructions[hydrationDetails.hydrationVirtualField]!!
59- .asSequence()
60- .filterIsInstance<NadelGenericHydrationInstruction >()
61- .first() as ? NadelHydrationFieldInstruction
62- ? : return emptyMap() // Virtual types only come about from standard hydrations, not batched
63-
64- val virtualTypeContext = nadelHydrationContext.virtualTypeContext
65- ? : return emptyMap() // Not all hydrations create virtual types
66-
67- val virtualType = virtualTypeContext.backingTypeToVirtualType[backingFieldParentTypeName]
68- ? : return emptyMap() // Not a virtual type
69-
70- val fieldCoordinatesInVirtualType = makeFieldCoordinates(virtualType, backingField.name)
71-
72- val instructions = fieldInstructions[fieldCoordinatesInVirtualType]
73- ?.filterIsInstance<T >()
74- ?.takeIf {
75- it.isNotEmpty()
76- }
77- ? : return emptyMap()
78-
79- return mapOf (
80- backingField.objectTypeNames.single() to instructions,
81- )
82- }
83-
84- internal class NadelOverallExecutionBlueprintMigrator (
85- private val hint : NadelValidationBlueprintHint ,
86- val old : NadelOverallExecutionBlueprint ,
87- val new : Lazy <NadelOverallExecutionBlueprint ?>,
88- ) : NadelOverallExecutionBlueprint {
89- private val impl: NadelOverallExecutionBlueprint
90- get() {
91- return if (hint.isNewBlueprintEnabled()) {
92- new.value ? : old
93- } else {
94- old
95- }
96- }
97-
98- override val engineSchema: GraphQLSchema
99- get() = impl.engineSchema
100-
101- override val fieldInstructions: Map <FieldCoordinates , List <NadelFieldInstruction >>
102- get() = impl.fieldInstructions
103-
104- override fun getUnderlyingTypeNamesForService (service : Service ): Set <String > {
105- return impl.getUnderlyingTypeNamesForService(service)
106- }
107-
108- override fun getOverAllTypeNamesForService (service : Service ): Set <String > {
109- return impl.getOverAllTypeNamesForService(service)
110- }
111-
112- override fun getUnderlyingTypeName (service : Service , overallTypeName : String ): String {
113- return impl.getUnderlyingTypeName(service, overallTypeName)
114- }
115-
116- override fun getUnderlyingTypeName (overallTypeName : String ): String {
117- return impl.getUnderlyingTypeName(overallTypeName)
118- }
119-
120- override fun getRename (overallTypeName : String ): NadelTypeRenameInstruction ? {
121- return impl.getRename(overallTypeName)
122- }
123-
124- override fun getOverallTypeName (service : Service , underlyingTypeName : String ): String {
125- return impl.getOverallTypeName(service, underlyingTypeName)
126- }
127-
128- override fun getServiceOwning (fieldCoordinates : FieldCoordinates ): Service ? {
129- return impl.getServiceOwning(fieldCoordinates)
130- }
131- }
132-
133- internal data class NadelOverallExecutionBlueprintImpl (
134- override val engineSchema : GraphQLSchema ,
135- override val fieldInstructions : Map <FieldCoordinates , List <NadelFieldInstruction >>,
17+ data class NadelOverallExecutionBlueprint (
18+ val engineSchema : GraphQLSchema ,
19+ val fieldInstructions : Map <FieldCoordinates , List <NadelFieldInstruction >>,
13620 private val underlyingTypeNamesByService : Map <Service , Set <String >>,
13721 private val overallTypeNamesByService : Map <Service , Set <String >>,
13822 private val underlyingBlueprints : Map <String , NadelUnderlyingExecutionBlueprint >,
13923 private val coordinatesToService : Map <FieldCoordinates , Service >,
14024 private val typeRenamesByOverallTypeName : Map <String , NadelTypeRenameInstruction >,
141- ) : NadelOverallExecutionBlueprint {
25+ ) {
14226 private fun setOfServiceTypes (
14327 map : Map <Service , Set <String >>,
14428 service : Service ,
14529 ): Set <String > {
14630 return (map[service] ? : error(" Could not find service: ${service.name} " ))
14731 }
14832
149- override fun getUnderlyingTypeNamesForService (service : Service ): Set <String > {
33+ fun getUnderlyingTypeNamesForService (service : Service ): Set <String > {
15034 return setOfServiceTypes(underlyingTypeNamesByService, service)
15135 }
15236
153- override fun getOverAllTypeNamesForService (service : Service ): Set <String > {
37+ fun getOverAllTypeNamesForService (service : Service ): Set <String > {
15438 return setOfServiceTypes(overallTypeNamesByService, service)
15539 }
15640
157- override fun getUnderlyingTypeName (
41+ fun getUnderlyingTypeName (
15842 service : Service ,
15943 overallTypeName : String ,
16044 ): String {
@@ -165,15 +49,15 @@ internal data class NadelOverallExecutionBlueprintImpl(
16549 return getUnderlyingBlueprint(service).typeInstructions.getUnderlyingName(overallTypeName)
16650 }
16751
168- override fun getUnderlyingTypeName (overallTypeName : String ): String {
52+ fun getUnderlyingTypeName (overallTypeName : String ): String {
16953 return typeRenamesByOverallTypeName[overallTypeName]?.underlyingName ? : overallTypeName
17054 }
17155
172- override fun getRename (overallTypeName : String ): NadelTypeRenameInstruction ? {
56+ fun getRename (overallTypeName : String ): NadelTypeRenameInstruction ? {
17357 return typeRenamesByOverallTypeName[overallTypeName]
17458 }
17559
176- override fun getOverallTypeName (
60+ fun getOverallTypeName (
17761 service : Service ,
17862 underlyingTypeName : String ,
17963 ): String {
@@ -184,10 +68,45 @@ internal data class NadelOverallExecutionBlueprintImpl(
18468 return getUnderlyingBlueprint(service).typeInstructions.getOverallName(underlyingTypeName)
18569 }
18670
187- override fun getServiceOwning (fieldCoordinates : FieldCoordinates ): Service ? {
71+ fun getServiceOwning (fieldCoordinates : FieldCoordinates ): Service ? {
18872 return coordinatesToService[fieldCoordinates]
18973 }
19074
75+ inline fun <reified T : NadelFieldInstruction > getInstructionInsideVirtualType (
76+ hydrationDetails : ServiceExecutionHydrationDetails ? ,
77+ backingField : ExecutableNormalizedField ,
78+ ): Map <GraphQLObjectTypeName , List <T >> {
79+ hydrationDetails ? : return emptyMap() // Need hydration to provide virtual hydration context
80+
81+ val backingFieldParentTypeName = backingField.objectTypeNames.singleOrNull()
82+ ? : return emptyMap() // Don't support abstract types for now
83+
84+ val nadelHydrationContext = fieldInstructions[hydrationDetails.hydrationVirtualField]!!
85+ .asSequence()
86+ .filterIsInstance<NadelGenericHydrationInstruction >()
87+ .first() as ? NadelHydrationFieldInstruction
88+ ? : return emptyMap() // Virtual types only come about from standard hydrations, not batched
89+
90+ val virtualTypeContext = nadelHydrationContext.virtualTypeContext
91+ ? : return emptyMap() // Not all hydrations create virtual types
92+
93+ val virtualType = virtualTypeContext.backingTypeToVirtualType[backingFieldParentTypeName]
94+ ? : return emptyMap() // Not a virtual type
95+
96+ val fieldCoordinatesInVirtualType = makeFieldCoordinates(virtualType, backingField.name)
97+
98+ val instructions = fieldInstructions[fieldCoordinatesInVirtualType]
99+ ?.filterIsInstance<T >()
100+ ?.takeIf {
101+ it.isNotEmpty()
102+ }
103+ ? : return emptyMap()
104+
105+ return mapOf (
106+ backingField.objectTypeNames.single() to instructions,
107+ )
108+ }
109+
191110 private fun getUnderlyingBlueprint (service : Service ): NadelUnderlyingExecutionBlueprint {
192111 val name = service.name
193112 return underlyingBlueprints[name] ? : error(" Could not find service: $name " )
0 commit comments