Skip to content
Snippets Groups Projects
Commit c901e20e authored by William Walker's avatar William Walker
Browse files

Set up DI context to be client instance-specific

parent 395d333a
No related branches found
No related tags found
No related merge requests found
......@@ -29,6 +29,7 @@ import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.header
import io.ktor.http.URLProtocol
import org.koin.core.context.GlobalContext.get
import org.koin.core.parameter.parametersOf
import kotlin.time.DurationUnit
import co.touchlab.kermit.Logger as KermitLogger
import io.ktor.client.plugins.logging.Logger as KtorLogger
......@@ -70,7 +71,7 @@ internal object HttpClientFactory {
when (config.httpClientLoggingBlock) {
null -> {
install(Logging) {
val kermit = get().get<KermitLogger>()
val kermit = get().get<KermitLogger> { parametersOf(null, config) }
logger = object : KtorLogger {
override fun log(message: String) {
kermit.d(message)
......
/*
* Designed and developed in 2022-2024 by William Walker (wnwalker@ucsc.edu)
* Copyright 2022-2024 The Regents of the University of California. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package edu.ucsc.its.temerity.core
import edu.ucsc.its.temerity.di.libModule
import edu.ucsc.its.temerity.di.loggerModule
import edu.ucsc.its.temerity.platformModule
import org.koin.core.Koin
import org.koin.core.KoinApplication
import org.koin.dsl.koinApplication
/**
* Factory providing a Koin application for the Temerity library.
*/
internal object KoinAppFactory {
/**
* This function initializes the Koin dependency injection framework
*/
internal fun createKoinApp() = object : TemerityKoinContext() {
override val koinApp = koinApplication {
modules(
loggerModule(),
platformModule(),
libModule,
)
}
override val koin: Koin = koinApp.koin
}
}
internal abstract class TemerityKoinContext {
abstract val koinApp: KoinApplication
abstract val koin: Koin
}
......@@ -31,8 +31,6 @@ import edu.ucsc.its.temerity.TemerityApi
import edu.ucsc.its.temerity.api.PlatformApi
import edu.ucsc.its.temerity.core.JsonFactory.buildJson
import edu.ucsc.its.temerity.createJobScope
import edu.ucsc.its.temerity.di.libModule
import edu.ucsc.its.temerity.di.loggerModule
import edu.ucsc.its.temerity.extensions.applyAuditLogFormat
import edu.ucsc.its.temerity.extensions.applyScheduledSessionDateFormat
import edu.ucsc.its.temerity.model.AuditLogEntry
......@@ -47,7 +45,6 @@ import edu.ucsc.its.temerity.model.User
import edu.ucsc.its.temerity.model.UserGroup
import edu.ucsc.its.temerity.model.UserRecordingSession
import edu.ucsc.its.temerity.model.UserUpdate
import edu.ucsc.its.temerity.platformModule
import edu.ucsc.its.temerity.sortByCreationDate
import io.ktor.client.statement.HttpResponse
import io.ktor.util.cio.toByteArray
......@@ -63,10 +60,10 @@ import kotlinx.serialization.SerializationException
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.koin.core.Koin
import org.koin.core.KoinApplication
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.koin.core.context.GlobalContext.get
import org.koin.core.parameter.parametersOf
import org.koin.dsl.koinApplication
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
import co.touchlab.kermit.Logger as KermitLogger
......@@ -76,7 +73,8 @@ import co.touchlab.kermit.Logger as KermitLogger
*/
public class Temerity internal constructor(
private val config: TemClientConfig,
) : TemerityApi {
) : TemerityApi,
KoinComponent {
/**
* Constructor for Temerity
*/
......@@ -93,10 +91,9 @@ public class Temerity internal constructor(
override fun version(): String = BuildConfig.LIB_VERSION
private val json: Json = buildJson()
internal val koinContext = KoinAppFactory.createKoinApp()
override fun getKoin(): Koin = koinContext.koin
@Suppress("MemberVisibilityCanBePrivate")
internal val temerityKoinApp: KoinApplication
internal val koin: Koin
private var platformApi: PlatformApi
private var cachedUserRoleList: ConcurrentMutableMap<Int, String>
private var clientCoroutineScope: CoroutineScope
......@@ -110,22 +107,14 @@ public class Temerity internal constructor(
"Service url must be provided. Set it using TemClientConfig.serviceUrl(url)"
}
temerityKoinApp = koinApplication {
modules(
loggerModule(),
platformModule(),
libModule,
)
}
koin = temerityKoinApp.koin
clientCoroutineScope = koin.get<CoroutineScope> {
clientCoroutineScope = get<CoroutineScope> {
when (val optThreadCount = config.threadCount) {
null -> parametersOf(DispatcherFactory.calculateMaxThreads(DEFAULT_MINIMUM_THREAD_COUNT))
else -> parametersOf(DispatcherFactory.setThreadCount(optThreadCount))
}
}
platformApi = koin.get<PlatformApi> {
platformApi = get<PlatformApi> {
parametersOf(config)
}
......@@ -164,7 +153,7 @@ public class Temerity internal constructor(
when (exception) {
is SerializationException -> {
// TODO: Implement platform API version checking
get().get<KermitLogger>().d { "Returned JSON object: ${exception.message}" }
get<KermitLogger>().d { "Returned JSON object: ${exception.message}" }
error("Encountered error decoding response from platform API. You likely need to choose a Temerity release that supports the API version implemented by your instance. \nPlatform API response data : $apiResponsePayload")
}
......@@ -252,7 +241,7 @@ public class Temerity internal constructor(
when (e) {
is BreakException -> {
if (config.optDebugEnabled) {
get().get<KermitLogger>().d("Caught BreakException() from decodeResponseCatching() notifying we're done reading groups from API: ${e.page} pages read")
get<KermitLogger>().d("Caught BreakException() from decodeResponseCatching() notifying we're done reading groups from API: ${e.page} pages read")
}
return returnedGroups
}
......@@ -286,7 +275,7 @@ public class Temerity internal constructor(
when (e) {
is BreakException -> {
if (config.optDebugEnabled) {
get().get<KermitLogger>().d("Caught BreakException() from decodeResponseCatching() notifying we're done reading groups from API: $e")
get<KermitLogger>().d("Caught BreakException() from decodeResponseCatching() notifying we're done reading groups from API: $e")
}
return returnedCourses
}
......@@ -368,7 +357,7 @@ public class Temerity internal constructor(
when (e) {
is BreakException -> {
if (config.optDebugEnabled) {
get().get<KermitLogger>().d("Caught BreakException() from decodeResponseCatching() notifying we're done reading audit log entries from API for specific window: ${e.page} pages read")
get<KermitLogger>().d("Caught BreakException() from decodeResponseCatching() notifying we're done reading audit log entries from API for specific window: ${e.page} pages read")
}
break
}
......
......@@ -21,6 +21,7 @@ import co.touchlab.kermit.Logger
import com.skydoves.sandwich.StatusCode
import com.skydoves.sandwich.ktor.getStatusCode
import edu.ucsc.its.temerity.AuditLogSortOrder.NEW_FIRST
import edu.ucsc.its.temerity.core.TemClientConfig
import edu.ucsc.its.temerity.core.Temerity
import edu.ucsc.its.temerity.currentDate
import edu.ucsc.its.temerity.di.loggerModule
......@@ -46,6 +47,7 @@ import org.koin.core.component.inject
import org.koin.core.parameter.parametersOf
import org.koin.test.KoinTest
import java.io.File
import kotlin.test.assertNotEquals
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
......@@ -55,7 +57,7 @@ class TemerityDevTest :
KoinTest {
override fun extensions(): List<Extension> = listOf(koinExtension(loggerModule()))
private val kermit: Logger by inject { parametersOf("TemerityDevTest") }
private val kermit: Logger by inject { parametersOf("TemerityDevTest", TemClientConfig { supportKtxNotebook = false }) }
init {
val dotenv = dotenvVault()
......@@ -76,6 +78,16 @@ class TemerityDevTest :
assert(returnedVersion.isPreRelease)
}
test("Temerity client returns different Koin Application instances on each creation") {
val firstInstance = Temerity {
configureDevEnvironment(dotenv)
}
val secondInstance = Temerity {
configureDevEnvironment(dotenv)
}
assertNotEquals(firstInstance.koinContext, secondInstance.koinContext)
}
test("Get all audit log entries of type \"New Login\" from the past month") {
runBlocking {
val currentDate = currentDate()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment