Skip to content

Commit

Permalink
feat: cherry-pick DataLoaderSyncExhaustionExhaustedInstrumentation (#…
Browse files Browse the repository at this point in the history
…1613)

* feat: add missing async leafs use case to sync exhaustion (#1612)

* feat: cherry-pick syncExhaustionInstrumentation fix

* feat: remove Test file
  • Loading branch information
samuelAndalon authored Dec 8, 2022
1 parent a059442 commit f1fb84c
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class ExecutionBatchState {
state.isCompletedComplexObject() -> {
isSyncExecutionExhausted(state.executionStrategyPaths.first())
}
state.isCompletedLeafOrNull() || state.isAsyncDispatchedNotLeaf() -> {
state.isCompletedLeafOrNull() || state.isAsyncDispatched() -> {
true
}
else -> false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,50 +172,50 @@ class ExecutionStrategyState(
* }
* ```
*/
fun addExecutionStrategyPath(
executionStrategyPath: String
) {
fun addExecutionStrategyPath(executionStrategyPath: String) {
executionStrategyPaths.add(executionStrategyPath)
}

/**
* field [fetchState] is completed with a non null [result] and
* field [fetchState] is completed with a non-null [result] and
* [graphQLType] is not a leaf [GraphQLList] and
* all non null complex objects inside the [result] list started their own executionStrategy
* all non-null complex objects inside the [result] list started their own executionStrategy
*
* @return Boolean indicating if above sentence result
* @return Boolean indicating if above conditions met
*/
fun isCompletedListOfComplexObjects(): Boolean =
fetchState == FieldFetchState.COMPLETED && result != null &&
GraphQLTypeUtil.isList(graphQLType) && !GraphQLTypeUtil.isLeaf(graphQLType) &&
(result as? List<*>)?.filterNotNull()?.size == executionStrategyPaths.size

/**
* field [fetchState] is completed with a non null [result] and
* field [fetchState] is completed with a non-null [result] and
* [graphQLType] is not a leaf complex type which executionStrategy was started.
*
* @return Boolean indicating if above sentence result
* @return Boolean indicating if above conditions met
*/
fun isCompletedComplexObject(): Boolean =
fetchState == FieldFetchState.COMPLETED && result != null &&
!GraphQLTypeUtil.isList(graphQLType) && !GraphQLTypeUtil.isLeaf(graphQLType) &&
executionStrategyPaths.isNotEmpty()

/**
* field [fetchState] is completed and [graphQLType] is a Leaf or null.
* field [fetchState] is [FieldFetchState.COMPLETED]
* field [graphQLType] is a Leaf or null.
*
* @return Boolean indicating if above sentence result
* @return Boolean indicating if above conditions met
*/
fun isCompletedLeafOrNull(): Boolean =
fetchState == FieldFetchState.COMPLETED &&
(GraphQLTypeUtil.isLeaf(graphQLType) || result == null)

/**
* field [fetchType] is Async and [fetchState] is dispatched and
* is not a leaf
* field [fetchType] is [FieldFetchType.ASYNC],
* field [fetchState] is [FieldFetchState.DISPATCHED]
*
* @return Boolean indicating if above conditions met
*/
fun isAsyncDispatchedNotLeaf(): Boolean =
fetchType == FieldFetchType.ASYNC && fetchState == FieldFetchState.DISPATCHED &&
!GraphQLTypeUtil.isLeaf(graphQLType)
fun isAsyncDispatched(): Boolean =
fetchType == FieldFetchType.ASYNC && fetchState == FieldFetchState.DISPATCHED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ object AstronautGraphQL {
missions(ids: [ID!]): [Mission]!
address: Address!
phoneNumber: String!
twitter: String!
}
type Astronaut {
id: ID!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@

package com.expediagroup.graphql.dataloader.instrumentation.fixture.domain

import reactor.kotlin.core.publisher.toMono
import java.time.Duration
import java.util.concurrent.CompletableFuture

data class Address(
val street: String = "300 E Street SW",
val zipCode: String = "98004"
)

data class Nasa(
class Nasa(
val address: Address = Address(),
val phoneNumber: String = "+1 123-456-7890"
)
) {
fun getTwitter(): CompletableFuture<String> =
"https://twitter.com/NASA".toMono().delayElement(Duration.ofMillis(100)).toFuture()
}
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,44 @@ class DataLoaderSyncExecutionExhaustedInstrumentationTest {
}
}

@Test
fun `Instrumentation should batch transactions after exhausting a single ExecutionInput with async Leafs`() {
val queries = listOf(
"""
fragment AstronautFragment on Astronaut { name missions { designation } }
query ComplexQuery {
astronaut1: astronaut(id: 1) { ...AstronautFragment }
nasa {
astronaut(id: 2) {...AstronautFragment }
phoneNumber
twitter
}
}
""".trimIndent()
)

val (results, kotlinDataLoaderRegistry) = AstronautGraphQL.execute(
graphQL,
queries,
DataLoaderInstrumentationStrategy.SYNC_EXHAUSTION
)

assertEquals(1, results.size)

val astronautStatistics = kotlinDataLoaderRegistry.dataLoadersMap["AstronautDataLoader"]?.statistics
val missionsByAstronautStatistics = kotlinDataLoaderRegistry.dataLoadersMap["MissionsByAstronautDataLoader"]?.statistics

assertEquals(1, astronautStatistics?.batchInvokeCount)
assertEquals(2, astronautStatistics?.batchLoadCount)

assertEquals(1, missionsByAstronautStatistics?.batchInvokeCount)
assertEquals(2, missionsByAstronautStatistics?.batchLoadCount)

verify(exactly = 3) {
kotlinDataLoaderRegistry.dispatchAll()
}
}

@Test
fun `Instrumentation should batch transactions after exhausting multiple ExecutionInput`() {
val queries = listOf(
Expand Down

0 comments on commit f1fb84c

Please sign in to comment.