Skip to content

Commit c588416

Browse files
committed
add nadel transform service context
1 parent 964b82e commit c588416

33 files changed

Lines changed: 188 additions & 53 deletions

lib/src/main/java/graphql/nadel/engine/plan/NadelExecutionPlan.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
package graphql.nadel.engine.plan
22

33
import graphql.nadel.Service
4-
import graphql.nadel.engine.transform.NadelTransform
4+
import graphql.nadel.engine.transform.NadelTransformServiceExecutionContext
5+
import graphql.nadel.engine.transform.NadelTransformWithContext
56
import graphql.nadel.instrumentation.parameters.NadelInstrumentationTimingParameters
67
import graphql.normalized.ExecutableNormalizedField
78

8-
internal typealias AnyNadelExecutionPlanStep = NadelExecutionPlan.Step<Any>
9+
internal typealias AnyNadelExecutionPlanStep = NadelExecutionPlan.Step<Any, NadelTransformServiceExecutionContext>
910

1011
data class NadelExecutionPlan(
1112
// this is a map for overall Fields
1213
val transformationSteps: Map<ExecutableNormalizedField, List<AnyNadelExecutionPlanStep>>,
1314
) {
14-
data class Step<T : Any>(
15+
data class Step<T : Any, U : NadelTransformServiceExecutionContext>(
1516
val service: Service,
1617
val field: ExecutableNormalizedField,
17-
val transform: NadelTransform<T>,
18+
val transform: NadelTransformWithContext<T, U>,
1819
val queryTransformTimingStep: NadelInstrumentationTimingParameters.Step,
1920
val resultTransformTimingStep: NadelInstrumentationTimingParameters.Step,
2021
val state: T,
22+
val context: U?,
2123
)
2224

2325
/**

lib/src/main/java/graphql/nadel/engine/plan/NadelExecutionPlanFactory.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import graphql.nadel.engine.transform.NadelRenameArgumentInputTypesTransform
1111
import graphql.nadel.engine.transform.NadelRenameTransform
1212
import graphql.nadel.engine.transform.NadelServiceTypeFilterTransform
1313
import graphql.nadel.engine.transform.NadelTransform
14+
import graphql.nadel.engine.transform.NadelTransformServiceExecutionContext
1415
import graphql.nadel.engine.transform.NadelTypeRenameResultTransform
1516
import graphql.nadel.engine.transform.hydration.NadelHydrationTransform
1617
import graphql.nadel.engine.transform.hydration.batch.NadelBatchHydrationTransform
@@ -62,13 +63,15 @@ internal class NadelExecutionPlanFactory(
6263
rootField: ExecutableNormalizedField,
6364
serviceHydrationDetails: ServiceExecutionHydrationDetails?,
6465
): NadelExecutionPlan {
65-
val executionSteps: MutableMap<ExecutableNormalizedField, List<NadelExecutionPlan.Step<Any>>> =
66+
val executionSteps: MutableMap<ExecutableNormalizedField, List<NadelExecutionPlan.Step<Any, NadelTransformServiceExecutionContext>>> =
67+
mutableMapOf()
68+
val transformContexts: MutableMap<NadelTransform<Any>, NadelTransformServiceExecutionContext?> =
6669
mutableMapOf()
67-
6870
executionContext.timer.batch { timer ->
6971
traverseQuery(rootField) { field ->
7072
val steps = transformsWithTimingStepInfo.mapNotNull { transformWithTimingInfo ->
7173
val transform = transformWithTimingInfo.transform
74+
val executionTransformContext = transformContexts.getOrPut(transform) { transform.buildContext() }
7275
// This is a patch to prevent errors
7376
// Ideally this should not happen but the proper fix requires more refactoring
7477
// See NadelSkipIncludeTransform.isApplicable for more details
@@ -83,6 +86,7 @@ internal class NadelExecutionPlanFactory(
8386
services,
8487
service,
8588
field,
89+
executionTransformContext,
8690
serviceHydrationDetails,
8791
)
8892
}
@@ -97,6 +101,7 @@ internal class NadelExecutionPlanFactory(
97101
queryTransformTimingStep = transformWithTimingInfo.queryTransformTimingStep,
98102
resultTransformTimingStep = transformWithTimingInfo.resultTransformTimingStep,
99103
state = state,
104+
executionTransformContext
100105
)
101106
}
102107
}

lib/src/main/java/graphql/nadel/engine/transform/NadelDeepRenameTransform.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ internal class NadelDeepRenameTransform : NadelTransform<NadelDeepRenameTransfor
8888
services: Map<String, Service>,
8989
service: Service,
9090
overallField: ExecutableNormalizedField,
91+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
9192
hydrationDetails: ServiceExecutionHydrationDetails?,
9293
): State? {
9394
val deepRenameInstructions = executionBlueprint
@@ -161,6 +162,7 @@ internal class NadelDeepRenameTransform : NadelTransform<NadelDeepRenameTransfor
161162
service: Service,
162163
field: ExecutableNormalizedField,
163164
state: State,
165+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
164166
): NadelTransformFieldResult {
165167
val objectTypesNoRenames = field.objectTypeNames.filterNot { it in state.instructionsByObjectTypeNames }
166168

@@ -299,6 +301,7 @@ internal class NadelDeepRenameTransform : NadelTransform<NadelDeepRenameTransfor
299301
result: ServiceExecutionResult,
300302
state: State,
301303
nodes: JsonNodes,
304+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
302305
): List<NadelResultInstruction> {
303306
val parentNodes = nodes.getNodesAt(
304307
queryPath = underlyingParentField?.queryPath ?: NadelQueryPath.root,

lib/src/main/java/graphql/nadel/engine/transform/NadelRenameArgumentInputTypesTransform.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ internal class NadelRenameArgumentInputTypesTransform : NadelTransform<State> {
3535
services: Map<String, Service>,
3636
service: Service,
3737
overallField: ExecutableNormalizedField,
38+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
3839
hydrationDetails: ServiceExecutionHydrationDetails?,
3940
): State? {
4041
// Transform if there's any arguments at all
@@ -55,6 +56,7 @@ internal class NadelRenameArgumentInputTypesTransform : NadelTransform<State> {
5556
service: Service,
5657
field: ExecutableNormalizedField,
5758
state: State,
59+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
5860
): NadelTransformFieldResult {
5961
return NadelTransformFieldResult(
6062
newField = field
@@ -74,6 +76,7 @@ internal class NadelRenameArgumentInputTypesTransform : NadelTransform<State> {
7476
result: ServiceExecutionResult,
7577
state: State,
7678
nodes: JsonNodes,
79+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
7780
): List<NadelResultInstruction> {
7881
return emptyList()
7982
}

lib/src/main/java/graphql/nadel/engine/transform/NadelRenameTransform.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ internal class NadelRenameTransform : NadelTransform<State> {
4343
services: Map<String, Service>,
4444
service: Service,
4545
overallField: ExecutableNormalizedField,
46+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
4647
hydrationDetails: ServiceExecutionHydrationDetails?,
4748
): State? {
4849
val renameInstructions = executionBlueprint
@@ -73,6 +74,7 @@ internal class NadelRenameTransform : NadelTransform<State> {
7374
service: Service,
7475
field: ExecutableNormalizedField,
7576
state: State,
77+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
7678
): NadelTransformFieldResult {
7779
return NadelTransformFieldResult(
7880
newField = if (state.objectTypesWithoutRename.isNotEmpty()) {
@@ -185,6 +187,7 @@ internal class NadelRenameTransform : NadelTransform<State> {
185187
result: ServiceExecutionResult,
186188
state: State,
187189
nodes: JsonNodes,
190+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
188191
): List<NadelResultInstruction> {
189192
val parentNodes = nodes.getNodesAt(
190193
queryPath = underlyingParentField?.queryPath ?: NadelQueryPath.root,

lib/src/main/java/graphql/nadel/engine/transform/NadelServiceTypeFilterTransform.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class NadelServiceTypeFilterTransform : NadelTransform<State> {
7777
services: Map<String, Service>,
7878
service: Service,
7979
overallField: ExecutableNormalizedField,
80+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
8081
hydrationDetails: ServiceExecutionHydrationDetails?,
8182
): State? {
8283
when {
@@ -100,7 +101,9 @@ class NadelServiceTypeFilterTransform : NadelTransform<State> {
100101
.all { objectTypeName ->
101102
objectTypeName in typeNamesOwnedByService
102103
|| objectTypeName in underlyingTypeNamesOwnedByService
103-
|| (executionContext.hints.sharedTypeRenames(service) && executionBlueprint.getUnderlyingTypeName(objectTypeName) in underlyingTypeNamesOwnedByService)
104+
|| (executionContext.hints.sharedTypeRenames(service) && executionBlueprint.getUnderlyingTypeName(
105+
objectTypeName
106+
) in underlyingTypeNamesOwnedByService)
104107
}
105108

106109
if (noForeignTypes) {
@@ -110,7 +113,9 @@ class NadelServiceTypeFilterTransform : NadelTransform<State> {
110113
val fieldObjectTypeNamesOwnedByService = overallField.objectTypeNames.filter { objectTypeName ->
111114
objectTypeName in typeNamesOwnedByService
112115
|| objectTypeName in underlyingTypeNamesOwnedByService
113-
|| (executionContext.hints.sharedTypeRenames(service) && executionBlueprint.getUnderlyingTypeName(objectTypeName) in underlyingTypeNamesOwnedByService)
116+
|| (executionContext.hints.sharedTypeRenames(service) && executionBlueprint.getUnderlyingTypeName(
117+
objectTypeName
118+
) in underlyingTypeNamesOwnedByService)
114119
}
115120

116121
return State(
@@ -132,6 +137,7 @@ class NadelServiceTypeFilterTransform : NadelTransform<State> {
132137
service: Service,
133138
field: ExecutableNormalizedField,
134139
state: State,
140+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
135141
): NadelTransformFieldResult {
136142
// Nothing to query if there are no fields, we need to add selection
137143
if (state.fieldObjectTypeNamesOwnedByService.isEmpty()) {
@@ -190,6 +196,7 @@ class NadelServiceTypeFilterTransform : NadelTransform<State> {
190196
result: ServiceExecutionResult,
191197
state: State,
192198
nodes: JsonNodes,
199+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
193200
): List<NadelResultInstruction> {
194201
return emptyList()
195202
}

lib/src/main/java/graphql/nadel/engine/transform/NadelTransform.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,29 @@ import graphql.nadel.engine.transform.result.NadelResultInstruction
1212
import graphql.nadel.engine.transform.result.json.JsonNodes
1313
import graphql.normalized.ExecutableNormalizedField
1414

15-
interface NadelTransform<State : Any> {
15+
//todo pull out into its own file and add some fields to this thing???
16+
abstract class NadelTransformServiceExecutionContext
17+
18+
typealias NadelTransform<State> = NadelTransformWithContext<State, NadelTransformServiceExecutionContext>
19+
20+
interface NadelTransformWithContext<State : Any, TransformServiceExecutionContext : NadelTransformServiceExecutionContext?> {
1621
/**
1722
* The name of the transform. Used for metrics purposes. Should be short and contain no special characters.
1823
*/
1924
val name: String
2025
get() = javaClass.simpleName.ifBlank { "UnknownTransform" }
2126

27+
/**
28+
* This method is called once before execution of the transform starts.
29+
* Override it to create a common object that is shared between all invocations of all other methods
30+
* of the transform on all the fields.
31+
*/
32+
suspend fun buildContext(
33+
//todo need to pass some useful params here
34+
): TransformServiceExecutionContext? {
35+
return null
36+
}
37+
2238
/**
2339
* Determines whether the [NadelTransform] should run. If it should run return a [State].
2440
*
@@ -48,6 +64,7 @@ interface NadelTransform<State : Any> {
4864
services: Map<String, Service>,
4965
service: Service,
5066
overallField: ExecutableNormalizedField,
67+
serviceExecutionTransformContext: TransformServiceExecutionContext?,
5168
hydrationDetails: ServiceExecutionHydrationDetails? = null,
5269
): State?
5370

@@ -66,6 +83,7 @@ interface NadelTransform<State : Any> {
6683
service: Service,
6784
field: ExecutableNormalizedField,
6885
state: State,
86+
serviceExecutionTransformContext: TransformServiceExecutionContext?,
6987
): NadelTransformFieldResult
7088

7189
/**
@@ -84,23 +102,22 @@ interface NadelTransform<State : Any> {
84102
result: ServiceExecutionResult,
85103
state: State,
86104
nodes: JsonNodes,
105+
serviceExecutionTransformContext: TransformServiceExecutionContext?,
87106
): List<NadelResultInstruction>
88107

89108
/**
90109
* Called once after all other functions of a transform ran on all fields in the query.
91110
* Override this function to perform cleanup or finalization tasks.
92111
* This method is optional for implementing classes.
93-
*
94-
* @param states - list with all [State] objects created during the transform execution
95112
*/
96-
suspend fun finalizeTransform(
113+
suspend fun onComplete(
97114
executionContext: NadelExecutionContext,
98115
serviceExecutionContext: NadelServiceExecutionContext,
99116
executionBlueprint: NadelOverallExecutionBlueprint,
100117
service: Service,
101118
result: ServiceExecutionResult,
102-
states: List<State>,
103119
nodes: JsonNodes,
120+
serviceExecutionTransformContext: TransformServiceExecutionContext? = null,
104121
) {
105122
}
106123
}

lib/src/main/java/graphql/nadel/engine/transform/NadelTransformJavaCompat.kt

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import java.util.concurrent.CompletableFuture
1818
/**
1919
* See [NadelTransform]
2020
*/
21-
interface NadelTransformJavaCompat<State : Any> {
21+
interface NadelTransformJavaCompat<State : Any, ServiceExecutionTransformContext : NadelTransformServiceExecutionContext> {
2222
val name: String
2323
get() = javaClass.simpleName.ifBlank { "UnknownTransform" }
2424

@@ -66,23 +66,25 @@ interface NadelTransformJavaCompat<State : Any> {
6666
): CompletableFuture<List<NadelResultInstruction>>
6767

6868
/**
69-
* See [NadelTransform.finalizeTransform]
69+
* See [NadelTransform.onComplete]
7070
*/
71-
fun finalizeTransform(
71+
fun onComplete(
7272
executionContext: NadelExecutionContext,
7373
serviceExecutionContext: NadelServiceExecutionContext,
7474
executionBlueprint: NadelOverallExecutionBlueprint,
7575
service: Service,
7676
result: ServiceExecutionResult,
77-
states: List<State>,
7877
nodes: JsonNodes,
78+
context: ServiceExecutionTransformContext? = null,
7979
): CompletableFuture<Void> {
8080
return CompletableFuture.completedFuture(null)
8181
}
8282

8383
companion object {
8484
@JvmStatic
85-
fun <State : Any> create(compat: NadelTransformJavaCompat<State>): NadelTransform<State> {
85+
fun <State : Any, ServiceExecutionTransformContext : NadelTransformServiceExecutionContext> create(
86+
compat: NadelTransformJavaCompat<State, ServiceExecutionTransformContext>,
87+
): NadelTransform<State> {
8688
return object : NadelTransform<State> {
8789
override val name: String
8890
get() = compat.name
@@ -94,6 +96,7 @@ interface NadelTransformJavaCompat<State : Any> {
9496
services: Map<String, Service>,
9597
service: Service,
9698
overallField: ExecutableNormalizedField,
99+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
97100
hydrationDetails: ServiceExecutionHydrationDetails?,
98101
): State? {
99102
return compat.isApplicable(
@@ -115,6 +118,7 @@ interface NadelTransformJavaCompat<State : Any> {
115118
service: Service,
116119
field: ExecutableNormalizedField,
117120
state: State,
121+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
118122
): NadelTransformFieldResult {
119123
return coroutineScope {
120124
val scope = this@coroutineScope
@@ -141,6 +145,7 @@ interface NadelTransformJavaCompat<State : Any> {
141145
result: ServiceExecutionResult,
142146
state: State,
143147
nodes: JsonNodes,
148+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
144149
): List<NadelResultInstruction> {
145150
return compat.getResultInstructions(
146151
executionContext = executionContext,
@@ -155,23 +160,22 @@ interface NadelTransformJavaCompat<State : Any> {
155160
).asDeferred().await()
156161
}
157162

158-
override suspend fun finalizeTransform(
163+
override suspend fun onComplete(
159164
executionContext: NadelExecutionContext,
160165
serviceExecutionContext: NadelServiceExecutionContext,
161166
executionBlueprint: NadelOverallExecutionBlueprint,
162167
service: Service,
163168
result: ServiceExecutionResult,
164-
states: List<State>,
165169
nodes: JsonNodes,
170+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
166171
) {
167-
compat.finalizeTransform(
172+
compat.onComplete(
168173
executionContext = executionContext,
169174
serviceExecutionContext = serviceExecutionContext,
170175
executionBlueprint = executionBlueprint,
171176
service = service,
172177
result = result,
173-
states = states,
174-
nodes = nodes,
178+
nodes = nodes
175179
).asDeferred().await()
176180
}
177181
}

lib/src/main/java/graphql/nadel/engine/transform/NadelTypeRenameResultTransform.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ internal class NadelTypeRenameResultTransform : NadelTransform<State> {
3333
services: Map<String, Service>,
3434
service: Service,
3535
overallField: ExecutableNormalizedField,
36+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
3637
hydrationDetails: ServiceExecutionHydrationDetails?,
3738
): State? {
3839
return if (overallField.fieldName == Introspection.TypeNameMetaFieldDef.name) {
@@ -56,6 +57,7 @@ internal class NadelTypeRenameResultTransform : NadelTransform<State> {
5657
service: Service,
5758
field: ExecutableNormalizedField,
5859
state: State,
60+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
5961
): NadelTransformFieldResult {
6062
return NadelTransformFieldResult.unmodified(field)
6163
}
@@ -70,6 +72,7 @@ internal class NadelTypeRenameResultTransform : NadelTransform<State> {
7072
result: ServiceExecutionResult,
7173
state: State,
7274
nodes: JsonNodes,
75+
serviceExecutionTransformContext: NadelTransformServiceExecutionContext?,
7376
): List<NadelResultInstruction> {
7477
val parentNodes = nodes.getNodesAt(
7578
underlyingParentField?.queryPath ?: NadelQueryPath.root,

0 commit comments

Comments
 (0)