Skip to content

Commit

Permalink
Delete old blueprint code (#656)
Browse files Browse the repository at this point in the history
* Delete old blueprint code

* Delete blueprint hint

* Delete unused shadowing flag

* Delete more of that flag
  • Loading branch information
gnawf authored Dec 18, 2024
1 parent 1030fc8 commit 157423c
Show file tree
Hide file tree
Showing 15 changed files with 50 additions and 1,171 deletions.
11 changes: 0 additions & 11 deletions lib/src/main/java/graphql/nadel/Nadel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import graphql.language.Document
import graphql.nadel.engine.blueprint.NadelDefaultIntrospectionRunner
import graphql.nadel.engine.blueprint.NadelIntrospectionRunnerFactory
import graphql.nadel.engine.transform.NadelTransform
import graphql.nadel.hints.NadelValidationBlueprintHint
import graphql.nadel.hooks.NadelExecutionHooks
import graphql.nadel.instrumentation.NadelInstrumentation
import graphql.nadel.instrumentation.parameters.NadelInstrumentationCreateStateParameters
Expand Down Expand Up @@ -247,12 +246,8 @@ class Nadel private constructor(
private var maxQueryDepth = Integer.MAX_VALUE
private var maxFieldCount = Integer.MAX_VALUE

private var blueprintHint = NadelValidationBlueprintHint { false }

private var nadelValidation: NadelSchemaValidation? = null

private var latencyTracker: NadelInternalLatencyTracker? = null

fun schemas(schemas: NadelSchemas): Builder {
this.schemas = schemas
return this
Expand Down Expand Up @@ -373,11 +368,6 @@ class Nadel private constructor(
return this
}

fun blueprintHint(hint: NadelValidationBlueprintHint): Builder {
this.blueprintHint = hint
return this
}

fun schemaValidation(nadelValidation: NadelSchemaValidation): Builder {
this.nadelValidation = nadelValidation
return this
Expand All @@ -400,7 +390,6 @@ class Nadel private constructor(
services = services,
transforms = transforms,
introspectionRunnerFactory = introspectionRunnerFactory,
blueprintHint = blueprintHint,
nadelValidation = nadelValidation ?: NadelSchemaValidationFactory.create(),
),
services = services,
Expand Down
9 changes: 0 additions & 9 deletions lib/src/main/java/graphql/nadel/NadelExecutionHints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package graphql.nadel
import graphql.nadel.hints.AllDocumentVariablesHint
import graphql.nadel.hints.LegacyOperationNamesHint
import graphql.nadel.hints.NadelDeferSupportHint
import graphql.nadel.hints.NadelServiceTypenameShadowingHint
import graphql.nadel.hints.NadelSharedTypeRenamesHint
import graphql.nadel.hints.NadelShortCircuitEmptyQueryHint
import graphql.nadel.hints.NadelVirtualTypeSupportHint
Expand All @@ -17,7 +16,6 @@ data class NadelExecutionHints(
val sharedTypeRenames: NadelSharedTypeRenamesHint,
val shortCircuitEmptyQuery: NadelShortCircuitEmptyQueryHint,
val virtualTypeSupport: NadelVirtualTypeSupportHint,
val serviceTypenameShadowing: NadelServiceTypenameShadowingHint,
) {
/**
* Returns a builder with the same field values as this object.
Expand All @@ -37,7 +35,6 @@ data class NadelExecutionHints(
private var shortCircuitEmptyQuery = NadelShortCircuitEmptyQueryHint { false }
private var sharedTypeRenames = NadelSharedTypeRenamesHint { false }
private var virtualTypeSupport = NadelVirtualTypeSupportHint { false }
private var serviceTypenameShadowing = NadelServiceTypenameShadowingHint.default

constructor()

Expand Down Expand Up @@ -83,11 +80,6 @@ data class NadelExecutionHints(
return this
}

fun serviceTypenameShadowing(flag: NadelServiceTypenameShadowingHint): Builder {
serviceTypenameShadowing = flag
return this
}

fun build(): NadelExecutionHints {
return NadelExecutionHints(
legacyOperationNames,
Expand All @@ -97,7 +89,6 @@ data class NadelExecutionHints(
sharedTypeRenames,
shortCircuitEmptyQuery,
virtualTypeSupport,
serviceTypenameShadowing,
)
}
}
Expand Down
23 changes: 2 additions & 21 deletions lib/src/main/java/graphql/nadel/NextgenEngine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ import graphql.nadel.engine.NadelExecutionContext
import graphql.nadel.engine.NadelIncrementalResultSupport
import graphql.nadel.engine.NadelServiceExecutionContext
import graphql.nadel.engine.blueprint.IntrospectionService
import graphql.nadel.engine.blueprint.NadelExecutionBlueprintFactory
import graphql.nadel.engine.blueprint.NadelIntrospectionRunnerFactory
import graphql.nadel.engine.blueprint.NadelOverallExecutionBlueprintMigrator
import graphql.nadel.engine.document.DocumentPredicates
import graphql.nadel.engine.instrumentation.NadelInstrumentationTimer
import graphql.nadel.engine.plan.NadelExecutionPlan
Expand All @@ -40,7 +38,6 @@ import graphql.nadel.engine.util.newServiceExecutionResult
import graphql.nadel.engine.util.provide
import graphql.nadel.engine.util.singleOfType
import graphql.nadel.engine.util.strictAssociateBy
import graphql.nadel.hints.NadelValidationBlueprintHint
import graphql.nadel.hooks.NadelExecutionHooks
import graphql.nadel.hooks.createServiceExecutionContext
import graphql.nadel.instrumentation.NadelInstrumentation
Expand All @@ -55,7 +52,6 @@ import graphql.nadel.result.NadelResultMerger
import graphql.nadel.result.NadelResultTracker
import graphql.nadel.time.NadelInternalLatencyTracker
import graphql.nadel.util.OperationNameUtil
import graphql.nadel.util.getLogger
import graphql.nadel.validation.NadelSchemaValidation
import graphql.normalized.ExecutableNormalizedField
import graphql.normalized.ExecutableNormalizedOperationFactory.createExecutableNormalizedOperationWithRawVariables
Expand All @@ -73,7 +69,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.future.asCompletableFuture
import kotlinx.coroutines.future.asDeferred
import kotlinx.coroutines.future.await
import kotlinx.coroutines.launch
import kotlinx.coroutines.reactive.asFlow
import kotlinx.coroutines.reactive.asPublisher
Expand All @@ -92,27 +87,13 @@ internal class NextgenEngine(
services: List<Service>,
transforms: List<NadelTransform<out Any>>,
introspectionRunnerFactory: NadelIntrospectionRunnerFactory,
blueprintHint: NadelValidationBlueprintHint,
nadelValidation: NadelSchemaValidation,
) {
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
private val services: Map<String, Service> = services.strictAssociateBy { it.name }
private val engineSchemaIntrospectionService = IntrospectionService(engineSchema, introspectionRunnerFactory)
private val overallExecutionBlueprint = NadelOverallExecutionBlueprintMigrator(
hint = blueprintHint,
old = NadelExecutionBlueprintFactory.create(
engineSchema = engineSchema,
services = services,
),
new = lazy {
try {
nadelValidation.validateAndGenerateBlueprint(NadelSchemas(engineSchema, services))
} catch (e: Exception) {
getLogger<NextgenEngine>().error("Unable to create validated blueprint", e)
null
}
},
)
private val overallExecutionBlueprint = nadelValidation
.validateAndGenerateBlueprint(NadelSchemas(engineSchema, services))
private val executionPlanner = NadelExecutionPlanFactory.create(
executionBlueprint = overallExecutionBlueprint,
engine = this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,154 +7,38 @@ import graphql.nadel.engine.util.emptyOrSingle
import graphql.nadel.engine.util.makeFieldCoordinates
import graphql.nadel.engine.util.mapFrom
import graphql.nadel.engine.util.strictAssociateBy
import graphql.nadel.hints.NadelValidationBlueprintHint
import graphql.normalized.ExecutableNormalizedField
import graphql.schema.FieldCoordinates
import graphql.schema.GraphQLSchema

/**
* Execution blueprint where keys are in terms of the overall schema.
*/
interface NadelOverallExecutionBlueprint {
val engineSchema: GraphQLSchema

val fieldInstructions: Map<FieldCoordinates, List<NadelFieldInstruction>>

fun getUnderlyingTypeNamesForService(service: Service): Set<String>

fun getOverAllTypeNamesForService(service: Service): Set<String>

fun getUnderlyingTypeName(
service: Service,
overallTypeName: String,
): String

fun getUnderlyingTypeName(overallTypeName: String): String

fun getRename(overallTypeName: String): NadelTypeRenameInstruction?

fun getOverallTypeName(
service: Service,
underlyingTypeName: String,
): String

fun getServiceOwning(fieldCoordinates: FieldCoordinates): Service?
}

/**
* Can't put inline function inside interface, so made it an extension function.
*
* This is temporary until we delete [NadelOverallExecutionBlueprintMigrator].
*/
inline fun <reified T : NadelFieldInstruction> NadelOverallExecutionBlueprint.getInstructionInsideVirtualType(
hydrationDetails: ServiceExecutionHydrationDetails?,
backingField: ExecutableNormalizedField,
): Map<GraphQLObjectTypeName, List<T>> {
hydrationDetails ?: return emptyMap() // Need hydration to provide virtual hydration context

val backingFieldParentTypeName = backingField.objectTypeNames.singleOrNull()
?: return emptyMap() // Don't support abstract types for now

val nadelHydrationContext = fieldInstructions[hydrationDetails.hydrationVirtualField]!!
.asSequence()
.filterIsInstance<NadelGenericHydrationInstruction>()
.first() as? NadelHydrationFieldInstruction
?: return emptyMap() // Virtual types only come about from standard hydrations, not batched

val virtualTypeContext = nadelHydrationContext.virtualTypeContext
?: return emptyMap() // Not all hydrations create virtual types

val virtualType = virtualTypeContext.backingTypeToVirtualType[backingFieldParentTypeName]
?: return emptyMap() // Not a virtual type

val fieldCoordinatesInVirtualType = makeFieldCoordinates(virtualType, backingField.name)

val instructions = fieldInstructions[fieldCoordinatesInVirtualType]
?.filterIsInstance<T>()
?.takeIf {
it.isNotEmpty()
}
?: return emptyMap()

return mapOf(
backingField.objectTypeNames.single() to instructions,
)
}

internal class NadelOverallExecutionBlueprintMigrator(
private val hint: NadelValidationBlueprintHint,
val old: NadelOverallExecutionBlueprint,
val new: Lazy<NadelOverallExecutionBlueprint?>,
) : NadelOverallExecutionBlueprint {
private val impl: NadelOverallExecutionBlueprint
get() {
return if (hint.isNewBlueprintEnabled()) {
new.value ?: old
} else {
old
}
}

override val engineSchema: GraphQLSchema
get() = impl.engineSchema

override val fieldInstructions: Map<FieldCoordinates, List<NadelFieldInstruction>>
get() = impl.fieldInstructions

override fun getUnderlyingTypeNamesForService(service: Service): Set<String> {
return impl.getUnderlyingTypeNamesForService(service)
}

override fun getOverAllTypeNamesForService(service: Service): Set<String> {
return impl.getOverAllTypeNamesForService(service)
}

override fun getUnderlyingTypeName(service: Service, overallTypeName: String): String {
return impl.getUnderlyingTypeName(service, overallTypeName)
}

override fun getUnderlyingTypeName(overallTypeName: String): String {
return impl.getUnderlyingTypeName(overallTypeName)
}

override fun getRename(overallTypeName: String): NadelTypeRenameInstruction? {
return impl.getRename(overallTypeName)
}

override fun getOverallTypeName(service: Service, underlyingTypeName: String): String {
return impl.getOverallTypeName(service, underlyingTypeName)
}

override fun getServiceOwning(fieldCoordinates: FieldCoordinates): Service? {
return impl.getServiceOwning(fieldCoordinates)
}
}

internal data class NadelOverallExecutionBlueprintImpl(
override val engineSchema: GraphQLSchema,
override val fieldInstructions: Map<FieldCoordinates, List<NadelFieldInstruction>>,
data class NadelOverallExecutionBlueprint(
val engineSchema: GraphQLSchema,
val fieldInstructions: Map<FieldCoordinates, List<NadelFieldInstruction>>,
private val underlyingTypeNamesByService: Map<Service, Set<String>>,
private val overallTypeNamesByService: Map<Service, Set<String>>,
private val underlyingBlueprints: Map<String, NadelUnderlyingExecutionBlueprint>,
private val coordinatesToService: Map<FieldCoordinates, Service>,
private val typeRenamesByOverallTypeName: Map<String, NadelTypeRenameInstruction>,
) : NadelOverallExecutionBlueprint {
) {
private fun setOfServiceTypes(
map: Map<Service, Set<String>>,
service: Service,
): Set<String> {
return (map[service] ?: error("Could not find service: ${service.name}"))
}

override fun getUnderlyingTypeNamesForService(service: Service): Set<String> {
fun getUnderlyingTypeNamesForService(service: Service): Set<String> {
return setOfServiceTypes(underlyingTypeNamesByService, service)
}

override fun getOverAllTypeNamesForService(service: Service): Set<String> {
fun getOverAllTypeNamesForService(service: Service): Set<String> {
return setOfServiceTypes(overallTypeNamesByService, service)
}

override fun getUnderlyingTypeName(
fun getUnderlyingTypeName(
service: Service,
overallTypeName: String,
): String {
Expand All @@ -165,15 +49,15 @@ internal data class NadelOverallExecutionBlueprintImpl(
return getUnderlyingBlueprint(service).typeInstructions.getUnderlyingName(overallTypeName)
}

override fun getUnderlyingTypeName(overallTypeName: String): String {
fun getUnderlyingTypeName(overallTypeName: String): String {
return typeRenamesByOverallTypeName[overallTypeName]?.underlyingName ?: overallTypeName
}

override fun getRename(overallTypeName: String): NadelTypeRenameInstruction? {
fun getRename(overallTypeName: String): NadelTypeRenameInstruction? {
return typeRenamesByOverallTypeName[overallTypeName]
}

override fun getOverallTypeName(
fun getOverallTypeName(
service: Service,
underlyingTypeName: String,
): String {
Expand All @@ -184,10 +68,45 @@ internal data class NadelOverallExecutionBlueprintImpl(
return getUnderlyingBlueprint(service).typeInstructions.getOverallName(underlyingTypeName)
}

override fun getServiceOwning(fieldCoordinates: FieldCoordinates): Service? {
fun getServiceOwning(fieldCoordinates: FieldCoordinates): Service? {
return coordinatesToService[fieldCoordinates]
}

inline fun <reified T : NadelFieldInstruction> getInstructionInsideVirtualType(
hydrationDetails: ServiceExecutionHydrationDetails?,
backingField: ExecutableNormalizedField,
): Map<GraphQLObjectTypeName, List<T>> {
hydrationDetails ?: return emptyMap() // Need hydration to provide virtual hydration context

val backingFieldParentTypeName = backingField.objectTypeNames.singleOrNull()
?: return emptyMap() // Don't support abstract types for now

val nadelHydrationContext = fieldInstructions[hydrationDetails.hydrationVirtualField]!!
.asSequence()
.filterIsInstance<NadelGenericHydrationInstruction>()
.first() as? NadelHydrationFieldInstruction
?: return emptyMap() // Virtual types only come about from standard hydrations, not batched

val virtualTypeContext = nadelHydrationContext.virtualTypeContext
?: return emptyMap() // Not all hydrations create virtual types

val virtualType = virtualTypeContext.backingTypeToVirtualType[backingFieldParentTypeName]
?: return emptyMap() // Not a virtual type

val fieldCoordinatesInVirtualType = makeFieldCoordinates(virtualType, backingField.name)

val instructions = fieldInstructions[fieldCoordinatesInVirtualType]
?.filterIsInstance<T>()
?.takeIf {
it.isNotEmpty()
}
?: return emptyMap()

return mapOf(
backingField.objectTypeNames.single() to instructions,
)
}

private fun getUnderlyingBlueprint(service: Service): NadelUnderlyingExecutionBlueprint {
val name = service.name
return underlyingBlueprints[name] ?: error("Could not find service: $name")
Expand Down
Loading

0 comments on commit 157423c

Please sign in to comment.