Skip to content

Commit

Permalink
Merge pull request #69 from aPureBase/data-loader-idea-testing
Browse files Browse the repository at this point in the history
New DataLoader executor
  • Loading branch information
jeggy authored Feb 19, 2020
2 parents 3bd2944 + b304b02 commit 21c3d60
Show file tree
Hide file tree
Showing 70 changed files with 1,464 additions and 158 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.idea/vcs.xml
.idea/inspectionProfiles

# Created by https://www.gitignore.io/api/java,gradle,intellij+all
# Edit at https://www.gitignore.io/?templates=java,gradle,intellij+all
Expand Down
2 changes: 1 addition & 1 deletion .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 13 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.3.50"
id "org.jetbrains.kotlin.jvm" version "1.3.61"
id "com.github.ben-manes.versions" version "0.24.0"
id "com.jfrog.bintray" version "1.8.4"
id "maven-publish"
id "jacoco"
}

allprojects {
Expand All @@ -26,9 +27,12 @@ allprojects {


testCompile "io.netty:netty-all:$netty_version"
testCompile "junit:junit:$junit_version"
testCompile "org.hamcrest:hamcrest:$hamcrest_version"
testCompile "org.amshove.kluent:kluent:$kluent_version"
testCompile "org.junit.jupiter:junit-jupiter-api:$junit_version"
testCompile "org.junit.jupiter:junit-jupiter-params:$junit_version"
testRuntime "org.junit.jupiter:junit-jupiter-engine:$junit_version"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-debug:$coroutine_version"
}

task sourcesJar(type: Jar, dependsOn: classes) {
Expand Down Expand Up @@ -75,5 +79,12 @@ allprojects {
}
}
}




test {
useJUnitPlatform()
}
}

7 changes: 4 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# KGraphQL version
version=0.9.2
version=0.10.0

# Dependencies
kotlin_version=1.3.50
coroutine_version=1.3.2
jackson_version=2.9.7
caffeine_version=2.8.0

serialization_version=0.14.0
kDataLoader_version=0.1.1

# Test-Dependencies
kotlin_html_version=0.6.12
netty_version=4.1.42.Final
junit_version=4.12
junit_version=5.5.2
kluent_version=1.56
hamcrest_version=2.2

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.apurebase.kgraphql

import org.amshove.kluent.shouldEqual
import org.junit.Test
import org.junit.jupiter.api.Test

class KtorFeatureTest {
@Test
Expand Down
4 changes: 4 additions & 0 deletions kgraphql/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
dependencies {
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
compile "de.nidomiro:KDataLoader:$kDataLoader_version"

compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version" // JVM dependency
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.apurebase.kgraphql

import com.apurebase.kgraphql.schema.model.FunctionWrapper
import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.jupiter.api.Test
import org.openjdk.jmh.annotations.*
import java.util.concurrent.ThreadLocalRandom
import java.util.concurrent.TimeUnit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import org.openjdk.jmh.annotations.*
import java.util.concurrent.ThreadLocalRandom
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.*
import org.junit.Test
import org.junit.jupiter.api.Test

@State(Scope.Benchmark)
@Warmup(iterations = 5)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.apurebase.kgraphql.schema.Schema
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.jupiter.api.Test
import org.openjdk.jmh.annotations.*
import java.util.concurrent.TimeUnit

Expand Down
34 changes: 34 additions & 0 deletions kgraphql/src/main/kotlin/com/apurebase/kgraphql/Extensions.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.apurebase.kgraphql

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.reflect.KClass
import kotlin.reflect.KParameter
import kotlin.reflect.KType
Expand Down Expand Up @@ -30,3 +33,34 @@ internal fun KType.getIterableElementType(): KType? {

internal fun not(boolean: Boolean) = !boolean



internal suspend fun <T, R> Collection<T>.toMapAsync(
dispatcher: CoroutineDispatcher = Dispatchers.Default,
block: suspend (T) -> R
): Map<T, R> = coroutineScope {
val channel = Channel<Pair<T, R>>()
val jobs = map { item ->
launch(dispatcher) {
try {
val res = block(item)
channel.send(item to res)
} catch (e: Exception) {
channel.close(e)
}
}
}
val resultMap = mutableMapOf<T, R>()
repeat(size) {
try {
val (item, result) = channel.receive()
resultMap[item] = result
} catch (e: Exception) {
jobs.forEach { job: Job -> job.cancel() }
throw e
}
}

channel.close()
resultMap
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.apurebase.kgraphql.configuration

import com.apurebase.kgraphql.schema.execution.Executor
import com.fasterxml.jackson.databind.ObjectMapper
import kotlinx.coroutines.CoroutineDispatcher

Expand All @@ -11,5 +12,8 @@ data class SchemaConfiguration (
val objectMapper: ObjectMapper,
val useDefaultPrettyPrinter: Boolean,
//execution
val coroutineDispatcher: CoroutineDispatcher
val coroutineDispatcher: CoroutineDispatcher,

val executor: Executor,
val timeout: Long?
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import com.apurebase.kgraphql.Context
import com.apurebase.kgraphql.configuration.SchemaConfiguration
import com.apurebase.kgraphql.request.CachingDocumentParser
import com.apurebase.kgraphql.request.VariablesJson
import com.apurebase.kgraphql.schema.execution.ParallelRequestExecutor
import com.apurebase.kgraphql.schema.execution.RequestExecutor
import com.apurebase.kgraphql.schema.introspection.__Schema
import com.apurebase.kgraphql.request.Parser
import com.apurebase.kgraphql.schema.execution.*
import com.apurebase.kgraphql.schema.execution.Executor.*
import com.apurebase.kgraphql.schema.model.ast.NameNode
import com.apurebase.kgraphql.schema.structure.LookupSchema
import com.apurebase.kgraphql.schema.structure.RequestInterpreter
Expand All @@ -26,7 +26,10 @@ class DefaultSchema (
val OPERATION_NAME_PARAM = NameNode("operationName", null)
}

private val requestExecutor : RequestExecutor = ParallelRequestExecutor(this)
private val requestExecutor : RequestExecutor = when (configuration.executor) {
Parallel -> ParallelRequestExecutor(this)
DataLoaderPrepared -> DataLoaderPreparedRequestExecutor(this)
}

private val requestInterpreter : RequestInterpreter = RequestInterpreter(model)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.apurebase.kgraphql.schema.dsl

import com.apurebase.kgraphql.Context
import com.apurebase.kgraphql.schema.model.FunctionWrapper
import com.apurebase.kgraphql.schema.model.InputValueDef
import com.apurebase.kgraphql.schema.model.PropertyDef
import nidomiro.kdataloader.BatchLoader
import nidomiro.kdataloader.dsl.dataLoaderFactory
import kotlin.reflect.KType

class DataLoaderPropertyDSL<T, K, R>(
val name: String,
val returnType: KType,
private val block : DataLoaderPropertyDSL<T, K, R>.() -> Unit
): LimitedAccessItemDSL<T>(), ResolverDSL.Target {

internal var dataLoader: BatchLoader<K, R>? = null
internal var prepareWrapper: FunctionWrapper<K>? = null

private val inputValues = mutableListOf<InputValueDef<*>>()

fun loader(block: BatchLoader<K, R>) {
dataLoader = block
}

fun prepare(block: suspend (T) -> K) {
prepareWrapper = FunctionWrapper.on(block, true)
}

fun <E> prepare(block: suspend (T, E) -> K) {
prepareWrapper = FunctionWrapper.on(block, true)
}

fun accessRule(rule: (T, Context) -> Exception?){
val accessRuleAdapter: (T?, Context) -> Exception? = { parent, ctx ->
if (parent != null) rule(parent, ctx) else IllegalArgumentException("Unexpected null parent of kotlin property")
}
this.accessRuleBlock = accessRuleAdapter
}

fun toKQLProperty(): PropertyDef.DataLoadedFunction<T, K, R> {
block()
requireNotNull(prepareWrapper)
requireNotNull(dataLoader)

return PropertyDef.DataLoadedFunction(
name = name,
description = description,
accessRule = accessRuleBlock,
deprecationReason = deprecationReason,
isDeprecated = isDeprecated,
inputValues = inputValues,
returnType = returnType,
prepare = prepareWrapper!!,
loader = dataLoaderFactory(dataLoader!!)
)
}

override fun addInputValues(inputValues: Collection<InputValueDef<*>>) {
this.inputValues.addAll(inputValues)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ class PropertyDSL<T : Any, R>(val name : String, block : PropertyDSL<T, R>.() ->
override fun addInputValues(inputValues: Collection<InputValueDef<*>>) {
this.inputValues.addAll(inputValues)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.databind.module.SimpleModule
import kotlinx.coroutines.runBlocking
import kotlin.reflect.KClass

/**
Expand All @@ -27,7 +28,10 @@ class SchemaBuilder internal constructor() {
private var configuration = SchemaConfigurationDSL()

fun build(): Schema {
return SchemaCompilation(configuration.build(), model.toSchemaDefinition()).perform()
// TODO: [runBlocking] is a temp fix
return runBlocking {
SchemaCompilation(configuration.build(), model.toSchemaDefinition()).perform()
}
}

fun configure(block: SchemaConfigurationDSL.() -> Unit){
Expand Down Expand Up @@ -187,13 +191,9 @@ class SchemaBuilder internal constructor() {
model.addInputObject(TypeDef.Input(input.name, kClass, input.description))
}

inline fun <reified T : Any> inputType(noinline block : InputTypeDSL<T>.() -> Unit) {
inline fun <reified T : Any> inputType(noinline block : InputTypeDSL<T>.() -> Unit = {}) {
inputType(T::class, block)
}

inline fun <reified T : Any> inputType() {
inputType(T::class) {}
}
}

inline fun <T: Any, reified Raw: Any> SchemaConfigurationDSL.appendMapper(scalar: ScalarDSL<T, Raw>, kClass: KClass<T>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.apurebase.kgraphql.configuration.SchemaConfiguration
import com.apurebase.kgraphql.schema.execution.Executor
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

Expand All @@ -15,17 +16,21 @@ class SchemaConfigurationDSL {
var documentParserCacheMaximumSize: Long = 1000L
var acceptSingleValueAsArray: Boolean = true
var coroutineDispatcher: CoroutineDispatcher = Dispatchers.Default
var executor: Executor = Executor.Parallel
var timeout: Long? = null

internal fun update(block: SchemaConfigurationDSL.() -> Unit) = block()

internal fun build(): SchemaConfiguration {
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, acceptSingleValueAsArray)
return SchemaConfiguration(
useCachingDocumentParser,
documentParserCacheMaximumSize,
objectMapper,
useDefaultPrettyPrinter,
coroutineDispatcher
useCachingDocumentParser,
documentParserCacheMaximumSize,
objectMapper,
useDefaultPrettyPrinter,
coroutineDispatcher,
executor,
timeout
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ import kotlin.reflect.KClass
class InputTypeDSL<T : Any>(val kClass: KClass<T>) : ItemDSL() {

var name = kClass.defaultKQLTypeName()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package com.apurebase.kgraphql.schema.dsl.types

import com.apurebase.kgraphql.defaultKQLTypeName
import com.apurebase.kgraphql.schema.SchemaException
import com.apurebase.kgraphql.schema.dsl.ItemDSL
import com.apurebase.kgraphql.schema.dsl.KotlinPropertyDSL
import com.apurebase.kgraphql.schema.dsl.PropertyDSL
import com.apurebase.kgraphql.schema.dsl.UnionPropertyDSL
import com.apurebase.kgraphql.schema.dsl.*
import com.apurebase.kgraphql.schema.model.FunctionWrapper
import com.apurebase.kgraphql.schema.model.PropertyDef
import com.apurebase.kgraphql.schema.model.Transformation
import com.apurebase.kgraphql.schema.model.TypeDef
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.createType
import kotlin.reflect.typeOf


open class TypeDSL<T : Any>(
Expand All @@ -29,6 +28,8 @@ open class TypeDSL<T : Any>(

internal val describedKotlinProperties = mutableMapOf<KProperty1<T, *>, PropertyDef.Kotlin<T, *>>()

val dataloadedExtensionProperties = mutableSetOf<PropertyDef.DataLoadedFunction<T, *, *>>()

fun <R, E> transformation(kProperty: KProperty1<T, R>, function: suspend (R, E) -> R) {
transformationProperties.add(Transformation(kProperty, FunctionWrapper.on(function, true)))
}
Expand Down Expand Up @@ -61,6 +62,12 @@ open class TypeDSL<T : Any>(
transformationProperties.add(Transformation(kProperty, FunctionWrapper.on(function, true)))
}

@UseExperimental(ExperimentalStdlibApi::class)
inline fun <KEY, reified TYPE> dataProperty(name: String, noinline block: DataLoaderPropertyDSL<T, KEY, TYPE>.() -> Unit) {
dataloadedExtensionProperties.add(
DataLoaderPropertyDSL(name, typeOf<TYPE>(), block).toKQLProperty()
)
}

fun <R> property(kProperty: KProperty1<T, R>, block : KotlinPropertyDSL<T, R>.() -> Unit){
val dsl = KotlinPropertyDSL(kProperty, block)
Expand Down Expand Up @@ -95,6 +102,7 @@ open class TypeDSL<T : Any>(
kClass = kClass,
kotlinProperties = describedKotlinProperties.toMap(),
extensionProperties = extensionProperties.toList(),
dataloadExtensionProperties = dataloadedExtensionProperties.toList(),
unionProperties = unionProperties.toList(),
transformations = transformationProperties.associateBy { it.kProperty },
description = description
Expand Down
Loading

0 comments on commit 21c3d60

Please sign in to comment.