From fa152a45e74cba4f7d0c6c70aa2e05e45ab7b0ee Mon Sep 17 00:00:00 2001 From: Yang Date: Fri, 8 Dec 2023 18:18:15 +1100 Subject: [PATCH] WIP - add RuntimeHints, and reflection bindings. `nativeRun` still failing. Readings: - https://www.graalvm.org/22.2/reference-manual/native-image/guides/use-native-image-gradle-plugin/ - https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.advanced.custom-hints - https://github.com/oracle/graalvm-reachability-metadata - https://github.com/spring-projects/spring-boot/issues/34157 - https://docs.spring.io/spring-framework/reference/core/aot.html#aot.hints.register-reflection-for-binding - https://docs.spring.io/spring-framework/reference/core/aot.html - https://betterprogramming.pub/experience-in-migrating-an-application-to-native-image-with-spring-boot-3-422d15efa31 --- build.gradle.kts | 20 ++++++++++++++++ .../kstreamlined/backend/KSConfiguration.kt | 12 +++++++++- .../backend/KStreamlinedRuntimeHints.kt | 24 +++++++++++++++++++ .../datafetcher/FeedEntryDataFetcher.kt | 3 ++- 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KStreamlinedRuntimeHints.kt diff --git a/build.gradle.kts b/build.gradle.kts index 6845fb5..33d7ed5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,6 +24,26 @@ dependencyManagement { group = "io.github.reactivecircus.kstreamlined.backend" version = "0.0.1-SNAPSHOT" +graalvmNative { + metadataRepository { + enabled.set(true) + } + binaries.configureEach { + resources.autodetect() + } + binaries.named("main") { + buildArgs( + "--strict-image-heap", + "-march=native", + "-R:MaxHeapSize=10m", + ) + javaLauncher = javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(21)) + vendor.set(JvmVendorSpec.GRAAL_VM) + } + } +} + tasks.withType().configureEach { packageName = "io.github.reactivecircus.kstreamlined.backend.schema.generated" } diff --git a/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KSConfiguration.kt b/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KSConfiguration.kt index 2bf4bae..e13a92e 100644 --- a/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KSConfiguration.kt +++ b/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KSConfiguration.kt @@ -1,14 +1,24 @@ package io.github.reactivecircus.kstreamlined.backend +import com.netflix.graphql.dgs.webflux.autoconfiguration.DgsWebfluxConfigurationProperties import io.github.reactivecircus.kstreamlined.backend.client.ClientConfigs import io.github.reactivecircus.kstreamlined.backend.client.FeedClient import io.github.reactivecircus.kstreamlined.backend.client.RealFeedClient -import io.ktor.client.engine.cio.CIO +import io.ktor.client.engine.cio.* +import org.springframework.aot.hint.annotation.RegisterReflectionForBinding import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.ImportRuntimeHints @Configuration +@ImportRuntimeHints(KStreamlinedRuntimeHints::class) +@RegisterReflectionForBinding( + DgsWebfluxConfigurationProperties::class, + DgsWebfluxConfigurationProperties.DgsWebsocketConfigurationProperties::class, + DgsWebfluxConfigurationProperties.DgsGraphiQLConfigurationProperties::class, + DgsWebfluxConfigurationProperties.DgsSchemaJsonConfigurationProperties::class, +) class KSConfiguration { @Bean diff --git a/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KStreamlinedRuntimeHints.kt b/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KStreamlinedRuntimeHints.kt new file mode 100644 index 0000000..a9d13fe --- /dev/null +++ b/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/KStreamlinedRuntimeHints.kt @@ -0,0 +1,24 @@ +package io.github.reactivecircus.kstreamlined.backend + +import org.springframework.aot.hint.ExecutableMode +import org.springframework.aot.hint.RuntimeHints +import org.springframework.aot.hint.RuntimeHintsRegistrar +import org.springframework.aot.hint.TypeReference + +object KStreamlinedRuntimeHints : RuntimeHintsRegistrar { + override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) { + hints.reflection() + .registerType( + TypeReference.of("com.github.benmanes.caffeine.cache.SSA") + ) { builder -> + builder.withConstructor( + listOf( + TypeReference.of("com.github.benmanes.caffeine.cache.Caffeine"), + TypeReference.of("com.github.benmanes.caffeine.cache.AsyncCacheLoader"), + TypeReference.of("boolean"), + ), + ExecutableMode.INVOKE, + ) + } + } +} diff --git a/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/datafetcher/FeedEntryDataFetcher.kt b/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/datafetcher/FeedEntryDataFetcher.kt index d2954e3..01a4229 100644 --- a/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/datafetcher/FeedEntryDataFetcher.kt +++ b/src/main/kotlin/io/github/reactivecircus/kstreamlined/backend/datafetcher/FeedEntryDataFetcher.kt @@ -33,8 +33,9 @@ import java.time.Duration @DgsComponent class FeedEntryDataFetcher( private val feedClient: FeedClient, - private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, ) { + private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO + private val kotlinBlogCacheContext = object : CacheContext { override val cache: Cache> = Caffeine .newBuilder()