Skip to content

Commit

Permalink
[build] update to Kotlin 1.4, Spring Boot 2.4.2 and Ktor 1.5 (Expedia…
Browse files Browse the repository at this point in the history
…Group#1007)

* [build] update to Kotlin 1.4, Spring Boot 2.4.1 and Ktor 1.5

JaCoCo branch coverage dropped because of jacoco/jacoco#1126, once new version of Jacoco is released we can bump it up again.

* use mavenLocal last and only for graphql-kotlin artifacts

The underlying issue with Gradle being unable to resolve Kotlin platform specific modules was misconfiguration to first look at maven local directory. It was problematic as Gradle uses module metadata to resolve target platform specific (-jvm) modules. Since this metadata is not used by Maven, once Maven integration tests kicked in and downloaded the dependencies, Gradle no longer was able to resolve those platform libs.

See gradle/gradle#15893 for details.

* update to spring boot 2.4.2

* disable flaky tests

Unsure whats causing the race condition on those subscription integration tests when run from GH actions. It appears that some websocket messages are randomly dropped. Cannot reproduce it locally. Disabling the test for now as subscription logic is already covered by tests in spring-server module.

Co-authored-by: Dariusz Kuc <dkuc@expedia.com>
  • Loading branch information
2 people authored and huehnerlady committed Apr 27, 2021
1 parent 349b188 commit 2485266
Show file tree
Hide file tree
Showing 15 changed files with 64 additions and 56 deletions.
6 changes: 5 additions & 1 deletion build.gradle.kts
Expand Up @@ -29,9 +29,13 @@ allprojects {
}

repositories {
mavenLocal()
mavenCentral()
jcenter()
mavenLocal {
content {
includeGroup("com.expediagroup")
}
}
}

apply(plugin = "de.marcphilipp.nexus-publish")
Expand Down
3 changes: 1 addition & 2 deletions clients/graphql-kotlin-ktor-client/build.gradle.kts
Expand Up @@ -6,9 +6,8 @@ val wireMockVersion: String by project
dependencies {
api(project(path = ":graphql-kotlin-client"))
api("io.ktor:ktor-client-cio:$ktorVersion")
api("io.ktor:ktor-client-json:$ktorVersion")
api("io.ktor:ktor-client-jackson:$ktorVersion")
testImplementation("io.ktor:ktor-client-okhttp:$ktorVersion")
testImplementation("io.ktor:ktor-client-logging-jvm:$ktorVersion")
testImplementation("io.ktor:ktor-client-logging:$ktorVersion")
testImplementation("com.github.tomakehurst:wiremock-jre8:$wireMockVersion")
}
Expand Up @@ -28,19 +28,19 @@ import com.github.tomakehurst.wiremock.core.WireMockConfiguration
import com.github.tomakehurst.wiremock.matching.EqualToPattern
import io.netty.channel.ChannelOption
import io.netty.handler.timeout.ReadTimeoutException
import io.netty.handler.timeout.ReadTimeoutHandler
import io.netty.handler.timeout.WriteTimeoutHandler
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.http.client.reactive.ClientHttpConnector
import org.springframework.http.client.reactive.ReactorClientHttpConnector
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.WebClientRequestException
import org.springframework.web.reactive.function.client.WebClientResponseException
import reactor.netty.http.client.HttpClient
import java.util.concurrent.TimeUnit
import java.time.Duration
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNotNull
Expand Down Expand Up @@ -104,13 +104,8 @@ class GraphQLWebClientTest {
WireMock.stubFor(stubResponse(response = expectedResponse, delayMillis = 50))

val httpClient: HttpClient = HttpClient.create()
.tcpConfiguration { client ->
client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10)
.doOnConnected { conn ->
conn.addHandlerLast(ReadTimeoutHandler(10, TimeUnit.MILLISECONDS))
conn.addHandlerLast(WriteTimeoutHandler(10, TimeUnit.MILLISECONDS))
}
}
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10)
.responseTimeout(Duration.ofMillis(10))
val connector: ClientHttpConnector = ReactorClientHttpConnector(httpClient.wiretap(true))
val webClientBuilder = WebClient.builder()
.clientConnector(connector)
Expand All @@ -120,12 +115,13 @@ class GraphQLWebClientTest {
builder = webClientBuilder
)
runBlocking {
assertFailsWith(ReadTimeoutException::class) {
val exception = assertFailsWith(WebClientRequestException::class) {
client.execute<GraphQLResponse<HelloWorldResult>>(
query = "query HelloWorldQuery { helloWorld }",
operationName = "HelloWorldQuery"
)
}
assertTrue(exception.cause is ReadTimeoutException)
}
}

Expand Down
9 changes: 2 additions & 7 deletions docs/client/client-customization.md
Expand Up @@ -81,13 +81,8 @@ Example below configures `GraphQLWebClient` with custom timeouts and adds a defa

```kotlin
val httpClient: HttpClient = HttpClient.create()
.tcpConfiguration { client ->
client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000)
.doOnConnected { conn ->
conn.addHandlerLast(ReadTimeoutHandler(60_000, TimeUnit.MILLISECONDS))
conn.addHandlerLast(WriteTimeoutHandler(60_000, TimeUnit.MILLISECONDS))
}
}
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000)
.responseTimeout(Duration.ofMillis(10_000))
val connector: ClientHttpConnector = ReactorClientHttpConnector(httpClient.wiretap(true))
val webClientBuilder = WebClient.builder()
.clientConnector(connector)
Expand Down
16 changes: 12 additions & 4 deletions examples/build.gradle.kts
Expand Up @@ -10,16 +10,24 @@ plugins {
allprojects {
buildscript {
repositories {
mavenLocal()
jcenter()
mavenCentral()
jcenter()
mavenLocal {
content {
includeGroup("com.expediagroup")
}
}
}
}

repositories {
mavenLocal()
jcenter()
mavenCentral()
jcenter()
mavenLocal {
content {
includeGroup("com.expediagroup")
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion examples/server/ktor-server/build.gradle.kts
Expand Up @@ -6,7 +6,7 @@ plugins {
}

application {
mainClassName = "io.ktor.server.netty.EngineMain"
mainClass.set("io.ktor.server.netty.EngineMain")
}

val kotlinCoroutinesVersion: String by project
Expand Down
1 change: 0 additions & 1 deletion examples/server/ktor-server/gradle.properties
@@ -1,2 +1 @@
ktorVersion=1.4.2
logbackVersion=1.2.1
Expand Up @@ -24,6 +24,7 @@ import com.expediagroup.graphql.server.spring.subscriptions.SubscriptionOperatio
import com.expediagroup.graphql.types.GraphQLRequest
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.MethodOrderer
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
Expand All @@ -46,7 +47,8 @@ import kotlin.random.Random
)
@EnableAutoConfiguration
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.Alphanumeric::class)
@TestMethodOrder(MethodOrderer.MethodName::class)
@Disabled("unknown race condition is causing random failures when run using GH action, cannot reproduce it locally")
class SimpleSubscriptionIT(@LocalServerPort private var port: Int) {

private val objectMapper = jacksonObjectMapper()
Expand Down
2 changes: 1 addition & 1 deletion generator/graphql-kotlin-federation/build.gradle.kts
Expand Up @@ -19,7 +19,7 @@ tasks {
limit {
counter = "BRANCH"
value = "COVEREDRATIO"
minimum = "0.94".toBigDecimal()
minimum = "0.93".toBigDecimal()
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion generator/graphql-kotlin-schema-generator/build.gradle.kts
Expand Up @@ -28,7 +28,7 @@ tasks {
limit {
counter = "BRANCH"
value = "COVEREDRATIO"
minimum = "0.95".toBigDecimal()
minimum = "0.94".toBigDecimal()
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions gradle.properties
Expand Up @@ -15,23 +15,23 @@ org.gradle.jvmargs=-Xmx2g -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError

# dependencies
kotlinJvmVersion = 1.8
kotlinVersion = 1.3.72
kotlinCoroutinesVersion = 1.3.8
kotlinVersion = 1.4.21
kotlinCoroutinesVersion = 1.4.2

classGraphVersion = 4.8.87
classGraphVersion = 4.8.98
graphQLJavaVersion = 16.1
jacksonVersion = 2.11.3
kotlinPoetVersion = 1.6.0
ktorVersion = 1.3.1
reactorVersion = 3.3.10.RELEASE
reactorExtensionsVersion = 1.0.2.RELEASE
ktorVersion = 1.5.0
reactorVersion = 3.4.2
reactorExtensionsVersion = 1.1.2
slf4jVersion = 1.7.30
springBootVersion = 2.3.4.RELEASE
springVersion = 5.2.9.RELEASE
springBootVersion = 2.4.2
springVersion = 5.3.3

# test dependency versions
junitVersion = 5.6.2
mockkVersion = 1.10.0
junitVersion = 5.7.0
mockkVersion = 1.10.4
mustacheVersion = 0.9.6
rxjavaVersion = 3.0.4
wireMockVersion = 2.26.3
Expand Down
Expand Up @@ -17,7 +17,6 @@ dependencies {
}
api("com.squareup:kotlinpoet:$kotlinPoetVersion")
implementation("io.ktor:ktor-client-cio:$ktorVersion")
implementation("io.ktor:ktor-client-json:$ktorVersion")
implementation("io.ktor:ktor-client-jackson:$ktorVersion")
testImplementation("com.github.tomakehurst:wiremock-jre8:$wireMockVersion")
}
Expand Down
Expand Up @@ -136,8 +136,12 @@ abstract class GraphQLGradlePluginAbstractIT {
$plugins
repositories {
mavenLocal()
mavenCentral()
mavenLocal {
content {
includeGroup("com.expediagroup")
}
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
Expand Down Expand Up @@ -212,8 +216,12 @@ abstract class GraphQLGradlePluginAbstractIT {
$plugins
repositories {
mavenLocal()
mavenCentral()
mavenLocal {
content {
includeGroup "com.expediagroup"
}
}
}
compileKotlin {
Expand Down
2 changes: 1 addition & 1 deletion servers/graphql-kotlin-spring-server/build.gradle.kts
Expand Up @@ -35,7 +35,7 @@ tasks {
limit {
counter = "BRANCH"
value = "COVEREDRATIO"
minimum = "0.85".toBigDecimal()
minimum = "0.74".toBigDecimal()
}
}
}
Expand Down
Expand Up @@ -27,23 +27,21 @@ import graphql.ExecutionResult
import graphql.GraphQL
import org.reactivestreams.Publisher
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toFlux

/**
* Default Spring implementation of GraphQL subscription handler.
*/
open class SpringGraphQLSubscriptionHandler(private val graphQL: GraphQL) {

fun executeSubscription(graphQLRequest: GraphQLRequest, graphQLContext: GraphQLContext?): Flux<GraphQLResponse<*>> = Mono.subscriberContext()
.flatMapMany {
graphQL.execute(graphQLRequest.toExecutionInput(graphQLContext))
.getData<Publisher<ExecutionResult>>()
.toFlux()
.map { result -> result.toGraphQLResponse() }
.onErrorResume { throwable ->
val error = KotlinGraphQLError(throwable).toGraphQLKotlinType()
Flux.just(GraphQLResponse<Any>(errors = listOf(error)))
}
}
fun executeSubscription(graphQLRequest: GraphQLRequest, graphQLContext: GraphQLContext?): Flux<GraphQLResponse<*>> = Flux.deferContextual {
graphQL.execute(graphQLRequest.toExecutionInput(graphQLContext))
.getData<Publisher<ExecutionResult>>()
.toFlux()
.map { result -> result.toGraphQLResponse() }
.onErrorResume { throwable ->
val error = KotlinGraphQLError(throwable).toGraphQLKotlinType()
Flux.just(GraphQLResponse<Any>(errors = listOf(error)))
}
}
}

0 comments on commit 2485266

Please sign in to comment.