Skip to content

Commit e9abff7

Browse files
committed
Update DataLoaderExecutor to be auto timed
1 parent c6d0556 commit e9abff7

File tree

8 files changed

+52
-264
lines changed

8 files changed

+52
-264
lines changed

gradle.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ coroutine_version=1.5.0
66
jackson_version=2.12.3
77
caffeine_version=3.0.2
88
serialization_version=1.2.1
9-
kDataLoader_version=0.3.0
9+
kDataLoader_version=0.4.0
10+
deferredJsonBuilder_version=1.0.0
1011
ktor_version=1.6.0
1112

1213
# Test-Dependencies

kgraphql/build.gradle.kts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ plugins {
88

99
val caffeine_version: String by project
1010
val kDataLoader_version: String by project
11+
val deferredJsonBuilder_version: String by project
1112
val kotlin_version: String by project
1213
val serialization_version: String by project
1314
val coroutine_version: String by project
@@ -25,11 +26,14 @@ dependencies {
2526
implementation(kotlin("reflect"))
2627

2728
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version")
29+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version") // JVM dependency
30+
2831
implementation("com.fasterxml.jackson.core:jackson-databind:$jackson_version")
2932
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version")
33+
3034
implementation("com.github.ben-manes.caffeine:caffeine:$caffeine_version")
35+
implementation("com.apurebase:DeferredJsonBuilder:$deferredJsonBuilder_version")
3136
api("de.nidomiro:KDataLoader:$kDataLoader_version")
32-
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version") // JVM dependency
3337

3438

3539
testImplementation("io.netty:netty-all:$netty_version")

kgraphql/src/main/kotlin/com/apurebase/kgraphql/schema/dsl/DataLoaderPropertyDSL.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import com.apurebase.kgraphql.schema.model.FunctionWrapper
55
import com.apurebase.kgraphql.schema.model.InputValueDef
66
import com.apurebase.kgraphql.schema.model.PropertyDef
77
import nidomiro.kdataloader.BatchLoader
8-
import nidomiro.kdataloader.dsl.dataLoaderFactory
8+
import nidomiro.kdataloader.TimedAutoDispatcherDataLoaderOptions
9+
import nidomiro.kdataloader.factories.TimedAutoDispatcherDataLoaderFactory
910
import kotlin.reflect.KType
1011

1112
class DataLoaderPropertyDSL<T, K, R>(
@@ -80,7 +81,12 @@ class DataLoaderPropertyDSL<T, K, R>(
8081
inputValues = inputValues,
8182
returnType = returnType,
8283
prepare = prepareWrapper!!,
83-
loader = dataLoaderFactory(dataLoader!!)
84+
loader = TimedAutoDispatcherDataLoaderFactory(
85+
{ TimedAutoDispatcherDataLoaderOptions() },
86+
mapOf(),
87+
dataLoader!!,
88+
null,
89+
)
8490
)
8591
}
8692

kgraphql/src/main/kotlin/com/apurebase/kgraphql/schema/execution/DataLoaderPreparedRequestExecutor.kt

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.apurebase.kgraphql.schema.execution
22

3+
import com.apurebase.deferredJson.DeferredJsonMap
4+
import com.apurebase.deferredJson.deferredJsonBuilder
35
import com.apurebase.kgraphql.Context
46
import com.apurebase.kgraphql.ExecutionException
57
import com.apurebase.kgraphql.GraphQLError
@@ -14,14 +16,11 @@ import com.apurebase.kgraphql.schema.scalar.serializeScalar
1416
import com.apurebase.kgraphql.schema.structure.Field
1517
import com.apurebase.kgraphql.schema.structure.InputValue
1618
import com.apurebase.kgraphql.schema.structure.Type
17-
import kotlinx.coroutines.*
18-
import kotlinx.coroutines.sync.Mutex
19-
import kotlinx.coroutines.sync.withLock
19+
import kotlinx.coroutines.CompletableDeferred
20+
import kotlinx.coroutines.Deferred
21+
import kotlinx.coroutines.coroutineScope
2022
import kotlinx.serialization.json.*
2123
import nidomiro.kdataloader.DataLoader
22-
import nidomiro.kdataloader.factories.DataLoaderFactory
23-
import java.util.concurrent.ConcurrentHashMap
24-
import java.util.concurrent.atomic.AtomicLong
2524
import kotlin.reflect.KProperty1
2625

2726

@@ -32,46 +31,30 @@ class DataLoaderPreparedRequestExecutor(val schema: DefaultSchema) : RequestExec
3231
inner class ExecutionContext(
3332
val variables: Variables,
3433
val requestContext: Context,
35-
private val dataCounters: ConcurrentHashMap<DataLoader<*, *>, AtomicLong> = ConcurrentHashMap(),
36-
private val loaders: ConcurrentHashMap<DataLoaderFactory<Any?, *>, DataLoader<Any?, *>> = ConcurrentHashMap()
37-
) : Mutex by Mutex() {
38-
39-
40-
suspend fun get(loader: DataLoader<*, *>): Long = withLock {
41-
dataCounters[loader]?.get() ?: throw IllegalArgumentException("Something went wrong with execution")
42-
}
43-
suspend fun add(loader: DataLoader<*, *>, check: Pair<*, String>, count: Long) = withLock {
44-
if (dataCounters[loader] == null) {
45-
/** TODO: There shouldn't be a need for Atomic here as we are using [withLock] */
46-
dataCounters[loader] = AtomicLong(count)
47-
} else {
48-
val counter = dataCounters[loader]!!
49-
counter.getAndUpdate {
50-
it + count
34+
val loaders: Map<Field.DataLoader<*, *, *>, DataLoader<Any?, *>>
35+
)
36+
37+
private suspend fun ExecutionPlan.constructLoaders(): Map<Field.DataLoader<*, *, *>, DataLoader<Any?, *>> {
38+
val loaders = mutableMapOf<Field.DataLoader<*, *, *>, DataLoader<Any?, *>>()
39+
40+
suspend fun Collection<Execution>.look() {
41+
forEach { ex ->
42+
ex.selectionNode
43+
when (ex) {
44+
is Execution.Fragment -> ex.elements.look()
45+
is Execution.Node -> {
46+
ex.children.look()
47+
if (ex.field is Field.DataLoader<*, *, *>) {
48+
loaders[ex.field] = ex.field.loader.constructNew() as DataLoader<Any?, *>
49+
}
50+
}
5151
}
5252
}
5353
}
54-
55-
suspend fun load(builder: DeferredJsonMap, loaderfactory: DataLoaderFactory<Any?, Any?>, node: Execution.Node, preparedValue: Any?): Deferred<Any?> {
56-
val loader = loaders.getOrPut(loaderfactory) { loaderfactory.constructNew() }
57-
add(loader, preparedValue to node.selectionNode.fullPath, 1) // parentCount)
58-
59-
val value = loader.loadAsync(preparedValue)
60-
61-
builder.deferredLaunch {
62-
val count = get(loader)
63-
val stats = loader.createStatisticsSnapshot()
64-
if (stats.objectsRequested >= count) {
65-
loader.dispatch()
66-
} // else if (stats.objectsRequested > count) throw TODO("This should never happen!!!")
67-
}
68-
69-
70-
return value
71-
}
54+
operations.look()
55+
return loaders
7256
}
7357

74-
7558
private suspend fun <T> DeferredJsonMap.writeOperation(
7659
ctx: ExecutionContext,
7760
node: Execution.Node,
@@ -212,7 +195,11 @@ class DataLoaderPreparedRequestExecutor(val schema: DefaultSchema) : RequestExec
212195
}
213196
}
214197
}
215-
} else {
198+
} else if (expectedType.kind == TypeKind.UNION) return handleFragment(
199+
ctx,
200+
value,
201+
container.elements.first { expectedType.name == expectedType.name } as Execution.Fragment
202+
) else {
216203
throw IllegalStateException("fragments can be specified on object types, interfaces, and unions")
217204
}
218205
}
@@ -326,7 +313,7 @@ class DataLoaderPreparedRequestExecutor(val schema: DefaultSchema) : RequestExec
326313
) // ?: TODO("Nullable prepare functions isn't supported")
327314

328315

329-
val value = ctx.load(this, field.loader as DataLoaderFactory<Any?, Any?>, node, preparedValue)
316+
val value = ctx.loaders[field]!!.loadAsync(preparedValue)
330317

331318

332319
applyKeyToElement(ctx, value, node, field.returnType, parentCount)
@@ -360,10 +347,11 @@ class DataLoaderPreparedRequestExecutor(val schema: DefaultSchema) : RequestExec
360347
}
361348

362349
override suspend fun suspendExecute(plan: ExecutionPlan, variables: VariablesJson, context: Context) = coroutineScope {
363-
deferredJsonBuilder(timeout = plan.options.timeout ?: schema.configuration.timeout) {
350+
val result = deferredJsonBuilder(timeout = plan.options.timeout ?: schema.configuration.timeout) {
364351
val ctx = ExecutionContext(
365352
Variables(schema, variables, plan.firstOrNull { it.variables != null }?.variables),
366-
context
353+
context,
354+
plan.constructLoaders(),
367355
)
368356

369357

@@ -372,7 +360,10 @@ class DataLoaderPreparedRequestExecutor(val schema: DefaultSchema) : RequestExec
372360
if (shouldInclude(ctx, node)) writeOperation(ctx, node, node.field as Field.Function<*, *>)
373361
}
374362
}
375-
}.toString()
363+
ctx.loaders.values.map { it.dispatch() }
364+
}
365+
366+
result.await().toString()
376367
}
377368

378369
private fun createNullNode(node: Execution.Node, returnType: Type): JsonNull = if (returnType !is Type.NonNull) {

kgraphql/src/main/kotlin/com/apurebase/kgraphql/schema/execution/DeferredJsonArray.kt

Lines changed: 0 additions & 56 deletions
This file was deleted.

kgraphql/src/main/kotlin/com/apurebase/kgraphql/schema/execution/DeferredJsonMap.kt

Lines changed: 0 additions & 75 deletions
This file was deleted.

kgraphql/src/main/kotlin/com/apurebase/kgraphql/schema/execution/Utils.kt

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)