InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
8.88k stars 707 forks source link

Koin+Ktor: first server reload breaks consequent server responses #1782

Closed Stexxe closed 1 month ago

Stexxe commented 6 months ago

When the Ktor's auto-reloading feature is enabled, and the Koin Ktor plugin is installed, the server doesn't respond after the first reload.

To Reproduce

  1. Run the server with the following code and the auto-reloading enabled:
    fun main() {
    embeddedServer(Netty, port = 8080) {
        install(Koin)
        routing {
            get("/") {
                call.respondText("Hello, world")
            }
        }
    }.start(wait = true)
    }
  2. Make a request to http://localhost:8080
  3. Change the string in call.respondText("Hello, world")
  4. Build the project
  5. Make the request again

Expected behavior: A response with the body is returned from the server Actual behavior: An empty response is returned from the server. Also, I observe the following exception being thrown:

org.koin.core.error.KoinAppAlreadyStartedException: A Koin Application has already been started
    at org.koin.core.context.GlobalContext.register(GlobalContext.kt:44)
    at org.koin.core.context.GlobalContext.startKoin(GlobalContext.kt:56)
    at org.koin.core.context.DefaultContextExtKt.startKoin(DefaultContextExt.kt:34)
    at org.koin.ktor.plugin.KoinPluginKt$Koin$2.invoke(KoinPlugin.kt:37)
    at org.koin.ktor.plugin.KoinPluginKt$Koin$2.invoke(KoinPlugin.kt:35)
    at io.ktor.server.application.CreatePluginUtilsKt.setupPlugin(CreatePluginUtils.kt:301)
    at io.ktor.server.application.CreatePluginUtilsKt.createPluginInstance(CreatePluginUtils.kt:270)
    at io.ktor.server.application.CreatePluginUtilsKt.access$createPluginInstance(CreatePluginUtils.kt:1)
    at io.ktor.server.application.CreatePluginUtilsKt$createApplicationPlugin$2.install(CreatePluginUtils.kt:90)
    at io.ktor.server.application.CreatePluginUtilsKt$createApplicationPlugin$2.install(CreatePluginUtils.kt:83)
    at io.ktor.server.application.ApplicationPluginKt.install(ApplicationPlugin.kt:100)
    at io.ktor.server.application.ApplicationPluginKt.install$default(ApplicationPlugin.kt:88)
    at ServerKt$main$1.invoke(Server.kt:10)
    at ServerKt$main$1.invoke(Server.kt:9)
    at io.ktor.server.engine.internal.CallableUtilsKt.executeModuleFunction(CallableUtils.kt:51)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$launchModuleByName$1.invoke(ApplicationEngineEnvironmentReloading.kt:332)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$launchModuleByName$1.invoke(ApplicationEngineEnvironmentReloading.kt:331)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.avoidingDoubleStartupFor(ApplicationEngineEnvironmentReloading.kt:356)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.launchModuleByName(ApplicationEngineEnvironmentReloading.kt:331)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.access$launchModuleByName(ApplicationEngineEnvironmentReloading.kt:32)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$instantiateAndConfigureApplication$1.invoke(ApplicationEngineEnvironmentReloading.kt:319)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$instantiateAndConfigureApplication$1.invoke(ApplicationEngineEnvironmentReloading.kt:310)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.avoidingDoubleStartup(ApplicationEngineEnvironmentReloading.kt:338)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.instantiateAndConfigureApplication(ApplicationEngineEnvironmentReloading.kt:310)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.createApplication(ApplicationEngineEnvironmentReloading.kt:150)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.currentApplication(ApplicationEngineEnvironmentReloading.kt:135)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.getApplication(ApplicationEngineEnvironmentReloading.kt:90)
    at io.ktor.server.netty.http1.NettyHttp1Handler.prepareCallFromRequest(NettyHttp1Handler.kt:142)
    at io.ktor.server.netty.http1.NettyHttp1Handler.handleRequest(NettyHttp1Handler.kt:116)
    at io.ktor.server.netty.http1.NettyHttp1Handler.channelRead(NettyHttp1Handler.kt:68)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
    at io.netty.handler.codec.http.HttpServerExpectContinueHandler.channelRead(HttpServerExpectContinueHandler.java:95)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda$1$lambda$0(NettyApplicationEngine.kt:296)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)
org.koin.core.error.KoinAppAlreadyStartedException: A Koin Application has already been started
    at org.koin.core.context.GlobalContext.register(GlobalContext.kt:44)
    at org.koin.core.context.GlobalContext.startKoin(GlobalContext.kt:56)
    at org.koin.core.context.DefaultContextExtKt.startKoin(DefaultContextExt.kt:34)
    at org.koin.ktor.plugin.KoinPluginKt$Koin$2.invoke(KoinPlugin.kt:37)
    at org.koin.ktor.plugin.KoinPluginKt$Koin$2.invoke(KoinPlugin.kt:35)
    at io.ktor.server.application.CreatePluginUtilsKt.setupPlugin(CreatePluginUtils.kt:301)
    at io.ktor.server.application.CreatePluginUtilsKt.createPluginInstance(CreatePluginUtils.kt:270)
    at io.ktor.server.application.CreatePluginUtilsKt.access$createPluginInstance(CreatePluginUtils.kt:1)
    at io.ktor.server.application.CreatePluginUtilsKt$createApplicationPlugin$2.install(CreatePluginUtils.kt:90)
    at io.ktor.server.application.CreatePluginUtilsKt$createApplicationPlugin$2.install(CreatePluginUtils.kt:83)
    at io.ktor.server.application.ApplicationPluginKt.install(ApplicationPlugin.kt:100)
    at io.ktor.server.application.ApplicationPluginKt.install$default(ApplicationPlugin.kt:88)
    at ServerKt$main$1.invoke(Server.kt:10)
    at ServerKt$main$1.invoke(Server.kt:9)
    at io.ktor.server.engine.internal.CallableUtilsKt.executeModuleFunction(CallableUtils.kt:51)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$launchModuleByName$1.invoke(ApplicationEngineEnvironmentReloading.kt:332)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$launchModuleByName$1.invoke(ApplicationEngineEnvironmentReloading.kt:331)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.avoidingDoubleStartupFor(ApplicationEngineEnvironmentReloading.kt:356)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.launchModuleByName(ApplicationEngineEnvironmentReloading.kt:331)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.access$launchModuleByName(ApplicationEngineEnvironmentReloading.kt:32)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$instantiateAndConfigureApplication$1.invoke(ApplicationEngineEnvironmentReloading.kt:319)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading$instantiateAndConfigureApplication$1.invoke(ApplicationEngineEnvironmentReloading.kt:310)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.avoidingDoubleStartup(ApplicationEngineEnvironmentReloading.kt:338)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.instantiateAndConfigureApplication(ApplicationEngineEnvironmentReloading.kt:310)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.createApplication(ApplicationEngineEnvironmentReloading.kt:150)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.currentApplication(ApplicationEngineEnvironmentReloading.kt:135)
    at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.getApplication(ApplicationEngineEnvironmentReloading.kt:90)
    at io.ktor.server.netty.http1.NettyHttp1Handler.prepareCallFromRequest(NettyHttp1Handler.kt:142)
    at io.ktor.server.netty.http1.NettyHttp1Handler.handleRequest(NettyHttp1Handler.kt:116)
    at io.ktor.server.netty.http1.NettyHttp1Handler.channelRead(NettyHttp1Handler.kt:68)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
    at io.netty.handler.codec.http.HttpServerExpectContinueHandler.channelRead(HttpServerExpectContinueHandler.java:95)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda$1$lambda$0(NettyApplicationEngine.kt:296)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)

Koin module and version: koin-ktor:3.5.3

stale[bot] commented 1 month ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.