Skip to content

Commit

Permalink
Merge pull request #1659 from InsertKoinIO/3.5.1
Browse files Browse the repository at this point in the history
Merge 3.5.1
  • Loading branch information
arnaudgiuliani committed Sep 15, 2023
2 parents b94245b + 0707242 commit 06de70a
Show file tree
Hide file tree
Showing 17 changed files with 231 additions and 38 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ Badges: `[UPDATED]`, `[FIXED]`, `[NEW]`, `[DEPRECATED]`, `[REMOVED]`, `[BREAKIN

# [3.5]()

## 3.5.1 - 2023-09-15

### [bom-3.5.1]()

* Update to update `koin-ktor` to `3.5.1`

### [ktor-3.5.1]()

* Fix Ktor Koin plugin with the right start process by @arnaudgiuliani in https://github.com/InsertKoinIO/koin/pull/1657
* Bump BOM & koin-ktor to 3.5.1 by @arnaudgiuliani in https://github.com/InsertKoinIO/koin/pull/1658

## 3.5.0 - 2023-09-12

### [bom-3.5.0]()
Expand Down
2 changes: 1 addition & 1 deletion bom/gradle/versions.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ext {
koin_bom_version = '3.5.0'
koin_bom_version = '3.5.1'
}
2 changes: 1 addition & 1 deletion core/koin-core/src/commonMain/kotlin/org/koin/core/Koin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,6 @@ class Koin {
val duration = measureDuration {
instanceRegistry.createAllEagerInstances()
}
logger.debug("Koin created eager instances in $duration ms")
logger.debug("Created eager instances in $duration ms")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class KoinApplication private constructor() {
if (koin.logger.isAt(Level.INFO)) {
val duration = measureDuration { loadModules(modules) }
val count = koin.instanceRegistry.size()
koin.logger.display(Level.INFO, "Koin started with $count definitions in $duration ms")
koin.logger.display(Level.INFO, "Started $count definitions in $duration ms")
} else {
loadModules(modules)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.test.TestResult
import kotlinx.coroutines.test.runTest
import org.koin.Simple
import org.koin.core.annotation.KoinInternalApi
Expand Down Expand Up @@ -355,26 +356,30 @@ class ParametersInjectionTest {

@Test
@OptIn(ExperimentalCoroutinesApi::class)
fun `inject across multiple threads`() = runTest {
val app = koinApplication {
modules(
module {
factory { (i: Int) -> Simple.MyIntFactory(i) }
},
)
}
fun `inject across multiple threads`(): TestResult {
val times = 100

return runTest {
val app = koinApplication {
modules(
module {
factory { (i: Int) -> Simple.MyIntFactory(i) }
},
)
}

val koin = app.koin
val koin = app.koin

repeat(1000) {
val range = (0 until 1000)
val deferreds = range.map {
async(Dispatchers.Default) {
koin.get<Simple.MyIntFactory> { parametersOf(it) }
repeat(times) {
val range = (0 until times)
val deferreds = range.map {
async(Dispatchers.Default) {
koin.get<Simple.MyIntFactory> { parametersOf(it) }
}
}
val values = awaitAll(*deferreds.toTypedArray())
assertEquals(range.map { it }, values.map { it.id })
}
val values = awaitAll(*deferreds.toTypedArray())
assertEquals(range.map { it }, values.map { it.id })
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fun main(args: Array<String>) {
fun Application.mainModule() {
install(CallLogging)
install(Koin) {
slf4jLogger(Level.DEBUG)
printLogger(Level.DEBUG)
modules(appModule)
}

Expand All @@ -42,6 +42,7 @@ fun Application.mainModule() {
get("/hello") {
val newId = call.scope.get<ScopeComponent>().id
println("ScopeComponent.id = $newId")
assert(Counter.init == 1)
call.respondText(helloService.sayHello())
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.koin.sample

import org.koin.sample.Counter.init
import java.util.UUID

class HelloRepository {
Expand All @@ -10,7 +11,15 @@ interface HelloService {
fun sayHello(): String
}

object Counter {
var init = 0
}

class HelloServiceImpl(val helloRepository: HelloRepository) : HelloService {
init {
println("created at start")
init++
}
override fun sayHello() = "Hello ${helloRepository.getHello()}!"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.testing.*
import org.junit.Before
import org.junit.Test
import org.koin.test.AutoCloseKoinTest
import kotlin.test.assertEquals
Expand All @@ -13,6 +14,11 @@ import kotlin.test.assertTrue

class ApplicationJobRoutesTest : AutoCloseKoinTest() {

@Before
fun before(){
Counter.init = 0
}

@Test
fun testHelloRequest() = testApplication {
val response = client.get("/hello")
Expand Down
2 changes: 1 addition & 1 deletion ktor/gradle/versions.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ext {
// Koin
koin_ktor_version = '3.5.0'
koin_ktor_version = '3.5.1'
// Ktor
ktor_version = '2.3.3'
}
3 changes: 2 additions & 1 deletion ktor/koin-ktor/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ repositories {
}

dependencies {
// Koin
api "io.insert-koin:koin-core:$koin_version"
testImplementation "io.insert-koin:koin-test-junit4:$koin_version"

// Ktor
api "io.ktor:ktor-server-core:$ktor_version"
testImplementation "io.ktor:ktor-server-test-host:$ktor_version"
testImplementation "io.ktor:ktor-server-netty:$ktor_version"
}

// Ensure "org.gradle.jvm.version" is set to "8" in Gradle metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import io.ktor.server.application.*
import org.koin.core.Koin
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import org.koin.core.scope.Scope
import org.koin.ktor.plugin.KOIN_ATTRIBUTE_KEY
import org.koin.ktor.plugin.KOIN_KEY
import org.koin.ktor.plugin.KOIN_SCOPE_ATTRIBUTE_KEY

/**
* Ktor Koin extensions for ApplicationCall class
Expand Down Expand Up @@ -71,4 +73,4 @@ fun ApplicationCall.getProperty(key: String, defaultValue: String) =
/**
* Help work on ModuleDefinition
*/
fun ApplicationCall.getKoin(): Koin = application.attributes.get(KOIN_ATTRIBUTE_KEY).koin
fun ApplicationCall.getKoin(): Koin = application.getKoin()
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ package org.koin.ktor.ext

import io.ktor.server.application.*
import org.koin.core.Koin
import org.koin.core.context.GlobalContext
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import org.koin.dsl.KoinAppDeclaration
import org.koin.ktor.plugin.KOIN_ATTRIBUTE_KEY
import org.koin.ktor.plugin.Koin
import org.koin.ktor.plugin.setKoinApplication

/**
* Ktor Koin extensions
Expand All @@ -28,10 +32,17 @@ import org.koin.ktor.plugin.KOIN_ATTRIBUTE_KEY
* @author Laurent Baresse
*/



/**
* Help work on ModuleDefinition
*/
fun Application.getKoin(): Koin = attributes.get(KOIN_ATTRIBUTE_KEY).koin
fun Application.getKoin(): Koin =
attributes.getOrNull(KOIN_ATTRIBUTE_KEY)?.koin ?: run {
val defaultInstance = GlobalContext.getKoinApplicationOrNull() ?: error("No Koin instance started. Use install(Koin) or startKoin()")
setKoinApplication(defaultInstance)
attributes[KOIN_ATTRIBUTE_KEY].koin
}

/**
* inject lazily given dependency
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ fun Route.getProperty(key: String, defaultValue: String) =
/**
* Help work on ModuleDefinition
*/
fun Route.getKoin(): Koin = application.attributes.get(KOIN_ATTRIBUTE_KEY).koin
fun Route.getKoin(): Koin = application.getKoin()
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ inline fun <reified T> Routing.getProperty(key: String, defaultValue: T) =
/**
* Help work on ModuleDefinition
*/
fun Routing.getKoin(): Koin = application.attributes.get(KOIN_ATTRIBUTE_KEY).koin
fun Routing.getKoin(): Koin = application.getKoin()
42 changes: 30 additions & 12 deletions ktor/koin-ktor/src/main/kotlin/org/koin/ktor/plugin/KoinPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import io.ktor.util.*
import org.koin.core.KoinApplication
import org.koin.core.scope.Scope
import org.koin.dsl.KoinAppDeclaration
import org.koin.dsl.koinApplication

/**
* @author Arnaud Giuliani
Expand All @@ -32,21 +31,34 @@ import org.koin.dsl.koinApplication
* Ktor Feature class. Allows Koin Context to start using Ktor default install(<feature>) method.
*
*/
val Koin = createApplicationPlugin(name = "Koin", createConfiguration = { KoinApplication.init() }) {
val koinApplication = setupKoinApplication()
setupMonitoring(koinApplication)
setupKoinScope(koinApplication)
}

// Plugin
val Koin = createApplicationPlugin(name = "Koin", createConfiguration = ::koinApplication) {
private fun PluginBuilder<KoinApplication>.setupKoinApplication(): KoinApplication {
val koinApplication = pluginConfig
application.attributes.put(KOIN_ATTRIBUTE_KEY, koinApplication)
koinApplication.createEagerInstances()
application.setKoinApplication(koinApplication)
return koinApplication
}

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

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

private fun PluginBuilder<KoinApplication>.setupKoinScope(koinApplication: KoinApplication) {
// Scope Handling
on(CallSetup) { call ->
val scopeComponent = RequestScope(koinApplication.koin)
Expand All @@ -57,14 +69,20 @@ val Koin = createApplicationPlugin(name = "Koin", createConfiguration = ::koinAp
}
}

fun Application.koin(configuration: KoinAppDeclaration) = pluginOrNull(Koin)?.let {
attributes.getOrNull(KOIN_ATTRIBUTE_KEY)?.apply(configuration)
} ?: install(Koin, configuration)

const val KOIN_KEY = "KOIN"
val KOIN_ATTRIBUTE_KEY = AttributeKey<KoinApplication>(KOIN_KEY)

val ApplicationCall.scope: Scope get() = this.attributes[KOIN_SCOPE_ATTRIBUTE_KEY]

const val KOIN_SCOPE_KEY = "KOIN_SCOPE"
val KOIN_SCOPE_ATTRIBUTE_KEY = AttributeKey<Scope>(KOIN_SCOPE_KEY)
val KOIN_SCOPE_ATTRIBUTE_KEY = AttributeKey<Scope>(KOIN_SCOPE_KEY)

//TODO move both to ext file
/**
* Scope property to let your resolve dependencies from Request Scope
*/
val ApplicationCall.scope: Scope get() = this.attributes.getOrNull(KOIN_SCOPE_ATTRIBUTE_KEY) ?: error("Koin Request Scope is not ready")
/**
* Run extra koin configuration, like modules()
*/
fun Application.koin(configuration: KoinAppDeclaration) = pluginOrNull(Koin)?.let {
attributes.getOrNull(KOIN_ATTRIBUTE_KEY)?.apply(configuration)
} ?: install(Koin, configuration)
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
/*
* Copyright 2017-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.koin.ktor.plugin

import org.koin.core.Koin
import org.koin.core.component.KoinScopeComponent
import org.koin.core.component.createScope

/**
* Request Scope Holder
*
* @author Arnaud Giuliani
*/
class RequestScope(private val _koin: Koin) : KoinScopeComponent {
override fun getKoin(): Koin = _koin
override val scope = createScope()
Expand Down
Loading

0 comments on commit 06de70a

Please sign in to comment.