Skip to content

Commit

Permalink
Add NadelResultPath value type so it doesn't feed into List params
Browse files Browse the repository at this point in the history
  • Loading branch information
gnawf committed Aug 5, 2024
1 parent 2bd7638 commit 073fcaf
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import graphql.nadel.engine.util.toBuilder
import graphql.nadel.engine.util.toGraphQLError
import graphql.nadel.engine.util.unwrapNonNull
import graphql.nadel.hooks.NadelExecutionHooks
import graphql.nadel.result.NadelResultPath
import graphql.nadel.result.NadelResultPathSegment
import graphql.normalized.ExecutableNormalizedField
import graphql.schema.FieldCoordinates
import kotlinx.coroutines.async
Expand Down Expand Up @@ -263,13 +265,13 @@ internal class NadelHydrationTransform(
overallField.resultKey to data?.value,
),
)
.path(parentPath)
.path(parentPath.toRawPath())
.errors(
hydration.errors
.map {
toGraphQLError(
raw = it,
path = path,
path = path.toRawPath(),
)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import graphql.nadel.engine.transform.result.json.NadelEphemeralJsonNode.Compani
import graphql.nadel.engine.transform.result.json.NadelEphemeralJsonNode.Companion.component3
import graphql.nadel.engine.util.AnyList
import graphql.nadel.engine.util.AnyMap
import graphql.nadel.result.NadelResultPath
import graphql.nadel.result.NadelResultPathSegment

/**
Expand Down Expand Up @@ -56,12 +57,12 @@ internal class NadelIteratingJsonNodes(
*/
internal abstract class NadelEphemeralJsonNode {
abstract val queryPath: List<String>
abstract val resultPath: List<NadelResultPathSegment>
abstract val resultPath: NadelResultPath
abstract val value: Any?

companion object {
operator fun NadelEphemeralJsonNode.component1(): List<String> = queryPath
operator fun NadelEphemeralJsonNode.component2(): List<NadelResultPathSegment> = resultPath
operator fun NadelEphemeralJsonNode.component2(): NadelResultPath = resultPath
operator fun NadelEphemeralJsonNode.component3(): Any? = value
}
}
Expand Down Expand Up @@ -113,7 +114,7 @@ internal class NadelJsonNodeIterator(

private val ephemeralJsonNode = object : NadelEphemeralJsonNode() {
override val queryPath get() = currentQueryPathSegments
override val resultPath get() = currentResultPathSegments
override val resultPath get() = NadelResultPath(currentResultPathSegments)
override var value: Any? = NONE
}

Expand Down
31 changes: 31 additions & 0 deletions lib/src/main/java/graphql/nadel/result/NadelResultPath.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package graphql.nadel.result

@JvmInline
internal value class NadelResultPath(
val value: List<NadelResultPathSegment>,
) {
operator fun plus(key: String): NadelResultPath {
return NadelResultPath(value + NadelResultPathSegment.Object(key))
}

operator fun plus(key: Int): NadelResultPath {
return NadelResultPath(value + NadelResultPathSegment.Array(key))
}

fun clone(): NadelResultPath {
return NadelResultPath(value = value.toList())
}

fun toRawPath(): List<Any> {
return value.map {
when (it) {
is NadelResultPathSegment.Array -> it.index
is NadelResultPathSegment.Object -> it.key
}
}
}

companion object {
val empty = NadelResultPath(value = emptyList())
}
}
10 changes: 7 additions & 3 deletions lib/src/main/java/graphql/nadel/result/NadelResultPathBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package graphql.nadel.result
internal interface NadelResultPathBuilder {
fun add(key: String): NadelResultPathBuilder
fun add(index: Int): NadelResultPathBuilder
fun build(): List<NadelResultPathSegment>
fun build(): NadelResultPath

companion object {
operator fun invoke(
Expand All @@ -22,14 +22,18 @@ internal interface NadelResultPathBuilder {
return this
}

override fun build(): List<NadelResultPathSegment> {
return segments
override fun build(): NadelResultPath {
return NadelResultPath(segments)
}
}
}
}
}

internal fun NadelResultPath.toBuilder(): NadelResultPathBuilder {
return NadelResultPathBuilder(value)
}

internal fun List<NadelResultPathSegment>.toBuilder(): NadelResultPathBuilder {
return NadelResultPathBuilder(this)
}
4 changes: 2 additions & 2 deletions lib/src/main/java/graphql/nadel/result/NadelResultTracker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ internal class NadelResultTracker {
suspend fun getResultPath(
queryPath: NadelQueryPath,
node: JsonNode,
): List<NadelResultPathSegment>? {
): NadelResultPath? {
val result = result.await()
val data = result.toSpecification()["data"]

val jsonNodeIterator = NadelJsonNodeIterator(root = data, queryPath = queryPath, flatten = true)
for (ephemeralNode in jsonNodeIterator) {
if (ephemeralNode.queryPath.size == queryPath.segments.size && ephemeralNode.value === node.value) {
// Clone because underlying values are ephemeral too
return ephemeralNode.resultPath.toList()
return ephemeralNode.resultPath.clone()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import com.fasterxml.jackson.module.kotlin.readValue
import graphql.nadel.engine.transform.query.NadelQueryPath
import graphql.nadel.engine.util.JsonMap
import graphql.nadel.jsonObjectMapper
import graphql.nadel.result.NadelResultPath
import graphql.nadel.result.NadelResultPathBuilder
import graphql.nadel.result.NadelResultPathSegment
import org.junit.jupiter.api.Test
import kotlin.test.assertTrue

class NadelJsonNodeIteratorTest {
private data class TraversedJsonNode(
override val queryPath: List<String>,
override val resultPath: List<NadelResultPathSegment>,
override val resultPath: NadelResultPath,
override val value: Any?,
) : NadelEphemeralJsonNode() {
constructor(other: NadelEphemeralJsonNode) : this(
queryPath = other.queryPath.toList(),
resultPath = other.resultPath.toList(),
resultPath = other.resultPath.clone(),
value = other.value,
)
}
Expand Down Expand Up @@ -45,7 +45,7 @@ class NadelJsonNodeIteratorTest {
val expectedTraversals = listOf(
TraversedJsonNode(
queryPath = emptyList(),
resultPath = emptyList(),
resultPath = NadelResultPath.empty,
value = root,
),
TraversedJsonNode(
Expand Down Expand Up @@ -123,7 +123,7 @@ class NadelJsonNodeIteratorTest {
val expectedTraversals = listOf(
TraversedJsonNode(
queryPath = emptyList(),
resultPath = emptyList(),
resultPath = NadelResultPath.empty,
value = root,
),
TraversedJsonNode(
Expand Down
14 changes: 11 additions & 3 deletions lib/src/test/kotlin/graphql/nadel/result/NadelResultTrackerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ class NadelResultTrackerTest {
if (value is AnyList || value is AnyMap) {
val queryPath = NadelQueryPath(
path
.value
.filterIsInstance<NadelResultPathSegment.Object>()
.map(NadelResultPathSegment.Object::key),
)
Expand Down Expand Up @@ -379,6 +380,7 @@ class NadelResultTrackerTest {
if (value is AnyList || value is AnyMap) {
val queryPath = NadelQueryPath(
path
.value
.filterIsInstance<NadelResultPathSegment.Object>()
.map(NadelResultPathSegment.Object::key),
)
Expand Down Expand Up @@ -439,7 +441,7 @@ class NadelResultTrackerTest {
val data = result.getData<JsonMap>()

// When
val visited = mutableListOf<Pair<List<NadelResultPathSegment>, Any?>>()
val visited = mutableListOf<Pair<NadelResultPath, Any?>>()
JsonNode(data).dfs { path, value ->
visited.add(path to value)
}
Expand Down Expand Up @@ -529,8 +531,8 @@ class NadelResultTrackerTest {
* It's much easier to reason the logic in this recursive function.
*/
private suspend fun JsonNode.dfs(
path: List<NadelResultPathSegment> = emptyList(),
onConsume: suspend (List<NadelResultPathSegment>, Any?) -> Unit,
path: NadelResultPath = NadelResultPath.empty,
onConsume: suspend (NadelResultPath, Any?) -> Unit,
) {
onConsume(path, value)

Expand All @@ -545,6 +547,12 @@ class NadelResultTrackerTest {
}
}

private fun JsonNode.getAt(
path: NadelResultPath,
): Any? {
return getAt(path.value)
}

private fun JsonNode.getAt(
path: List<NadelResultPathSegment>,
): Any? {
Expand Down

0 comments on commit 073fcaf

Please sign in to comment.