Repository: InsertKoinIO/koin
File: projects/ktor/koin-ktor/src/main/kotlin/org/koin/ktor/plugin/KoinPlugin.kt (Kotlin)

Code before:
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.koin.ktor.plugin

import io.ktor.server.application.*
import io.ktor.server.application.hooks.*
import io.ktor.util.*
import org.koin.core.KoinApplication
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.core.scope.Scope
import org.koin.dsl.KoinAppDeclaration

/**
 * @author Arnaud Giuliani
 * @author Vinicius Carvalho
 * @author Victor Alenkov
 * @author Zak Henry
 *
 * Ktor Feature class. Allows Koin Standard Context to start using Ktor default install(<feature>) method.
 *
 */
val Koin = createApplicationPlugin(name = "Koin", createConfiguration = { KoinApplication.init() }) {
    val koinApplication = setupKoinApplication()
    runningKoinApplication?.let { stopKoin() } // for ktor auto-reload
    runningKoinApplication = startKoin(koinApplication)
    setupMonitoring(koinApplication)
    setupKoinScope(koinApplication)
}

internal fun PluginBuilder<KoinApplication>.setupKoinApplication(): KoinApplication {
    val koinApplication = pluginConfig
    koinApplication.createEagerInstances()
    application.setKoinApplication(koinApplication)
    return koinApplication
}

fun Application.setKoinApplication(koinApplication: KoinApplication){
    attributes.put(KOIN_ATTRIBUTE_KEY, koinApplication)
}

internal fun PluginBuilder<KoinApplication>.setupMonitoring(koinApplication: KoinApplication) {
    val monitor = environment?.monitor
    monitor?.raise(KoinApplicationStarted, koinApplication)
    monitor?.subscribe(ApplicationStopping) {
        monitor.raise(KoinApplicationStopPreparing, koinApplication)
        koinApplication.koin.close()
        monitor.raise(KoinApplicationStopped, koinApplication)
    }
}

Review comment (suggestion):
You are keeping a ref on the Koin context instance here. Either I would suggest using `KoinPlatformTools.defaultContext().getOrNull()` to request current Koin context and see if it's null

Code after:
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.koin.ktor.plugin

import io.ktor.server.application.*
import io.ktor.server.application.hooks.*
import io.ktor.util.*
import org.koin.core.KoinApplication
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.core.scope.Scope
import org.koin.dsl.KoinAppDeclaration
import org.koin.mp.KoinPlatformTools

/**
 * @author Arnaud Giuliani
 * @author Vinicius Carvalho
 * @author Victor Alenkov
 * @author Zak Henry
 *
 * Ktor Feature class. Allows Koin Standard Context to start using Ktor default install(<feature>) method.
 *
 */
val Koin = createApplicationPlugin(name = "Koin", createConfiguration = { KoinApplication.init() }) {
    val koinApplication = setupKoinApplication()
    KoinPlatformTools.defaultContext().getOrNull()?.let { stopKoin() } // for ktor auto-reload
    startKoin(koinApplication)
    setupMonitoring(koinApplication)
    setupKoinScope(koinApplication)
}

internal fun PluginBuilder<KoinApplication>.setupKoinApplication(): KoinApplication {
    val koinApplication = pluginConfig
    koinApplication.createEagerInstances()
    application.setKoinApplication(koinApplication)
    return koinApplication
}

fun Application.setKoinApplication(koinApplication: KoinApplication){
    attributes.put(KOIN_ATTRIBUTE_KEY, koinApplication)
}

internal fun PluginBuilder<KoinApplication>.setupMonitoring(koinApplication: KoinApplication) {
    val monitor = environment?.monitor
    monitor?.raise(KoinApplicationStarted, koinApplication)
    monitor?.subscribe(ApplicationStopping) {
        monitor.raise(KoinApplicationStopPreparing, koinApplication)
        koinApplication.koin.close()
        monitor.raise(KoinApplicationStopped, koinApplication)
    }