diff --git a/temerity/build.gradle.kts b/temerity/build.gradle.kts index 0deccaa3ec015bfdcd317699b9291df1d6666df1..47ae2a134891e484b0d4396aad45149db501a0dc 100644 --- a/temerity/build.gradle.kts +++ b/temerity/build.gradle.kts @@ -46,6 +46,7 @@ buildscript { buildConfig { buildConfigField("LIB_VERSION", provider { "${project.version}" }) + buildConfigField("PACKAGE_NAME", provider { "edu.ucsc.its.${project.name}" }) } gitSemVer { diff --git a/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt b/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt index 32d677f1394f211c1431f9a53e52d769553bb1d8..bb98a1e554585bbdc31135f62c2040b2caac7e78 100644 --- a/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt +++ b/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.android.kt @@ -20,7 +20,7 @@ package edu.ucsc.its.temerity.core import co.touchlab.kermit.Logger import edu.ucsc.its.temerity.TemClientConfig -internal actual fun createLoggerCommon( +internal actual fun createCommonLogger( tag: String?, config: TemClientConfig?, supportKtxNotebook: Boolean, diff --git a/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.android.kt b/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.android.kt index 4c5f5da5d897af76a30dc3872693c611e554948e..36750b7e61051c66cde75e30b06cf92ebf0ae224 100644 --- a/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.android.kt +++ b/temerity/src/androidMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.android.kt @@ -21,13 +21,14 @@ import edu.ucsc.its.temerity.extensions.coroutines.createDispatcher import io.ktor.client.engine.android.Android import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers +import org.koin.core.qualifier.named import org.koin.dsl.module internal actual fun platformModule() = module { - single { (threadCount: Int, dispatcherName: String) -> + single(named("libraryCoroutineDispatcher")) { (threadCount: Int, dispatcherName: String) -> createDispatcher(Dispatchers.IO, threadCount, dispatcherName) } - single { (libraryCoroutineDispatcher: CoroutineDispatcher) -> + single(named("httpClientEngine")) { (libraryCoroutineDispatcher: CoroutineDispatcher) -> Android.create { dispatcher = libraryCoroutineDispatcher } diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt index 1dfefa8148eac95f8e868928369ec90cf27ea0a5..eae0e55d1ac6f140e52c3baaf6a6a7d94766233a 100644 --- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt +++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.kt @@ -21,7 +21,7 @@ import co.touchlab.kermit.Logger import edu.ucsc.its.temerity.TemClientConfig internal object LoggerFactory { - internal fun createLogger(tag: String?, config: TemClientConfig? = null, supportKtxNotebook: Boolean = false) = createLoggerCommon(tag = tag, config = config, supportKtxNotebook = supportKtxNotebook) + internal fun createLogger(tag: String?, config: TemClientConfig? = null, supportKtxNotebook: Boolean = false) = createCommonLogger(tag = tag, config = config, supportKtxNotebook = supportKtxNotebook) } -internal expect fun createLoggerCommon(tag: String?, config: TemClientConfig? = null, supportKtxNotebook: Boolean = false): Logger +internal expect fun createCommonLogger(tag: String?, config: TemClientConfig? = null, supportKtxNotebook: Boolean = false): Logger diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt index 9083faa08333c07d28683ec0f38cf3f4a0f41c64..5c7e2c59ea88ca06dfd4446fff2c5ffda54d99fd 100644 --- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt +++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt @@ -19,7 +19,6 @@ package edu.ucsc.its.temerity.core import co.touchlab.stately.collections.ConcurrentMutableMap import com.skydoves.sandwich.ApiResponse -import com.skydoves.sandwich.StatusCode import com.skydoves.sandwich.StatusCode.NoContent import com.skydoves.sandwich.getOrThrow import com.skydoves.sandwich.ktor.executeApiResponse @@ -32,7 +31,7 @@ import edu.ucsc.its.temerity.TemClientConfig import edu.ucsc.its.temerity.TemerityApi import edu.ucsc.its.temerity.api.PlatformApi import edu.ucsc.its.temerity.core.Temerity.Companion.DEFAULT_WEB_TIMEOUT -import edu.ucsc.its.temerity.di.libModule +import edu.ucsc.its.temerity.di.LibModule.libModule import edu.ucsc.its.temerity.di.platformModule import edu.ucsc.its.temerity.extensions.coroutines.calculateMaxThreads import edu.ucsc.its.temerity.extensions.coroutines.createJobScope @@ -45,7 +44,6 @@ import edu.ucsc.its.temerity.model.Course import edu.ucsc.its.temerity.model.Device import edu.ucsc.its.temerity.model.DeviceRecordingSession import edu.ucsc.its.temerity.model.EventType -import edu.ucsc.its.temerity.model.FolderPermissions import edu.ucsc.its.temerity.model.FolderPermissions.Action import edu.ucsc.its.temerity.model.Group import edu.ucsc.its.temerity.model.NewUser @@ -59,7 +57,6 @@ import io.ktor.client.HttpClientConfig import io.ktor.client.engine.HttpClientEngine import io.ktor.client.plugins.HttpTimeout import io.ktor.client.plugins.defaultRequest -import io.ktor.client.plugins.logging.LogLevel import io.ktor.client.plugins.logging.LogLevel.ALL import io.ktor.client.plugins.logging.Logging import io.ktor.client.request.header @@ -95,9 +92,8 @@ import org.koin.core.parameter.parametersOf import org.koin.dsl.koinApplication import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes -import kotlin.time.DurationUnit import kotlin.time.DurationUnit.MILLISECONDS -import kotlinx.datetime.DateTimeUnit.Companion +import org.koin.core.qualifier.named import co.touchlab.kermit.Logger as KermitLogger import io.ktor.client.plugins.logging.Logger as KtorLogger @@ -121,10 +117,14 @@ public class Temerity internal constructor( internal const val DEFAULT_MINIMUM_THREAD_COUNT: Int = 2 @JvmStatic - internal fun createLogger(): KermitLogger = LoggerFactory.createLogger( - tag = TODO(), - config = TODO (), - supportKtxNotebook = TODO() + internal fun createLogger( + tag: String?, + config: TemClientConfig?, + supportKtxNotebook: Boolean + ): KermitLogger = LoggerFactory.createLogger( + tag = tag, + config = config, + supportKtxNotebook = supportKtxNotebook ) @JvmStatic @@ -138,11 +138,11 @@ public class Temerity internal constructor( /** * This function initializes the Koin dependency injection framework, - * which provides the library's HttpClient and PlatformApi instances - * via factories defined as part of the lib Module. + * which provides the library's [HttpClient] and [PlatformApi] instances + * via factories defined as part of the [libModule]. */ - private fun createKoinApp() = object : TemerityKoinContext() { - override val logger = createLoggerCommon(tag = "TemerityLib Koin DI Context") + private fun createKoinApp(config: TemClientConfig) = object : TemerityKoinContext() { + override val logger = createCommonLogger(tag = BuildConfig.PACKAGE_NAME, config) override val koinApp = koinApplication { logger(object : Logger() { override fun display(level: Level, msg: MESSAGE) { @@ -170,12 +170,14 @@ public class Temerity internal constructor( } override val version: String = BuildConfig.LIB_VERSION - - // Kotlinx-serialization [Json] encoder/decoder object used for serializing/deserializing JSON object responses + + /** + * Kotlinx-serialization [Json] encoder/decoder object used for serializing/deserializing JSON object responses + */ private val json: Json = Json { coerceInputValues = true } - internal val koinContext = createKoinApp() + internal val koinContext = createKoinApp(config) override fun getKoin(): Koin = koinContext.koin private var platformApi: PlatformApi @@ -192,18 +194,18 @@ public class Temerity internal constructor( "Service url must be provided. Set it using TemClientConfig.serviceUrl(url)" } - libraryCoroutineDispatcher = get<CoroutineDispatcher> { + libraryCoroutineDispatcher = get<CoroutineDispatcher>(named("libraryCoroutineDispatcher")) { val dispatcherName = "Temerity Library Dispatcher" when (val optThreadCount = config.threadCount) { null -> parametersOf(calculateMaxThreads(DEFAULT_MINIMUM_THREAD_COUNT), dispatcherName) else -> parametersOf(setThreadCount(optThreadCount), dispatcherName) } } - libraryCoroutineScope = get<CoroutineScope> { + libraryCoroutineScope = get<CoroutineScope>(named("libraryCoroutineScope")) { parametersOf(libraryCoroutineDispatcher) } - platformApi = get<PlatformApi> { + platformApi = get<PlatformApi>(named("ktorfitApi")) { parametersOf(config) } @@ -451,7 +453,7 @@ public class Temerity internal constructor( when (e) { is BreakException -> { if (config.optDebugEnabled) { - 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>(named("libraryLogger")).d("Caught BreakException() from decodeResponseCatching() notifying we're done reading audit log entries from API for specific window: ${e.page} pages read") } break } diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt index f823724a757def6756911d2b8119e53444ac9b78..d27f07b4d96509c2a08c512186290d464e125c73 100644 --- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt +++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/di/LibModule.kt @@ -23,37 +23,46 @@ import edu.ucsc.its.temerity.TemClientConfig import edu.ucsc.its.temerity.api.PlatformApi import edu.ucsc.its.temerity.api.createPlatformApi import edu.ucsc.its.temerity.core.buildHttpClient -import edu.ucsc.its.temerity.core.createLoggerCommon +import edu.ucsc.its.temerity.core.createCommonLogger import edu.ucsc.its.temerity.extensions.coroutines.createLibraryScope import io.ktor.client.HttpClient +import io.ktor.client.engine.HttpClientEngine import kotlinx.coroutines.CoroutineDispatcher import org.koin.core.parameter.parametersOf import org.koin.core.qualifier.named import org.koin.dsl.module +import co.touchlab.kermit.Logger as KermitLogger -/** - * This function provides the Koin module for the Temerity library. - * It includes the platform module and provides factories for [HttpClient] and [PlatformApi]. - */ -internal fun libModule() = module { - factory { (config: TemClientConfig, kermit: co.touchlab.kermit.Logger) -> - buildHttpClient( - httpClientEngine = get(parameters = { parametersOf(get<CoroutineDispatcher>(named("libraryCoroutineDispatcher"))) }), - config = config, - logger = kermit, - ) - } - factory { (config: TemClientConfig) -> - val client: HttpClient = - get { parametersOf(config, createLoggerCommon(tag = "Temerity Library Web Request engine", config = config)) } - val ktorfit = ktorfit { - config.serviceUrl?.let { baseUrl(it) } - httpClient(client) - converterFactories(ApiResponseConverterFactory.create()) + +internal object LibModule { + /** + * This function provides the Koin module for the Temerity library. + * It includes the platform module and provides factories for [HttpClient] and [PlatformApi]. + */ + internal fun libModule() = module { + single(named("libraryLogger")) { (tag: String?, config: TemClientConfig?) -> + createCommonLogger(tag = tag, config = config) + } + single(named("libraryCoroutineScope")) { (dispatcher: CoroutineDispatcher) -> + createLibraryScope(dispatcher) + } + factory(named("httpClient")) { (config: TemClientConfig, kermit: co.touchlab.kermit.Logger) -> + buildHttpClient( + httpClientEngine = get<HttpClientEngine>(named("httpClientEngine"), parameters = { parametersOf(get<CoroutineDispatcher>(named("libraryCoroutineDispatcher"))) }), + config = config, + logger = kermit, + ) + } + factory(named("ktorfitApi")) { (config: TemClientConfig) -> + val logger: KermitLogger = get<KermitLogger>(named("libraryLogger")) + val client: HttpClient = + get<HttpClient>(named("httpClient")) { parametersOf(config, logger) } + val ktorfit = ktorfit { + config.serviceUrl?.let { baseUrl(it) } + httpClient(client) + converterFactories(ApiResponseConverterFactory.create()) + } + ktorfit.createPlatformApi() } - ktorfit.createPlatformApi() - } - single { (dispatcher: CoroutineDispatcher) -> - createLibraryScope(dispatcher) } } diff --git a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt index e6e70b71c5cb8e6be0817e8343a88d54e039af68..9cb64854d8f7a4c32115b92efa2ad55f5cc893cd 100644 --- a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt +++ b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/core/LoggerFactory.jvm.kt @@ -25,7 +25,7 @@ import co.touchlab.kermit.loggerConfigInit import co.touchlab.kermit.platformLogWriter import edu.ucsc.its.temerity.TemClientConfig -internal actual fun createLoggerCommon(tag: String?, config: TemClientConfig?, supportKtxNotebook: Boolean): Logger = when (config) { +internal actual fun createCommonLogger(tag: String?, config: TemClientConfig?, supportKtxNotebook: Boolean): Logger = when (config) { null -> { Logger( config = loggerConfigInit( diff --git a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.jvm.kt b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.jvm.kt index 395475859059a991d03abf620caa4e789158bdba..31a96ac9a19833ca0defc30204aa282f80319f21 100644 --- a/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.jvm.kt +++ b/temerity/src/jvmMain/kotlin/edu/ucsc/its/temerity/di/PlatformModule.jvm.kt @@ -28,7 +28,7 @@ internal actual fun platformModule() = module { single(named("libraryCoroutineDispatcher")) { (threadCount: Int, dispatcherName: String) -> createDispatcher(Dispatchers.IO, threadCount, dispatcherName) } - factory { (libraryCoroutineDispatcher: CoroutineDispatcher) -> + factory(named("httpClientEngine")) { (libraryCoroutineDispatcher: CoroutineDispatcher) -> Java.create { dispatcher = libraryCoroutineDispatcher } diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt index e4c44452ea0700c2cddc58f8e5da79fb847bf1c5..0aee5de6ea58fe497429b5cfbfa0481a209b7264 100644 --- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt +++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/DevUserApiTests.kt @@ -21,7 +21,6 @@ import co.touchlab.kermit.Logger import com.skydoves.sandwich.StatusCode import com.skydoves.sandwich.ktor.getStatusCode import edu.ucsc.its.temerity.core.Temerity -import edu.ucsc.its.temerity.core.Temerity.Companion.createLogger import edu.ucsc.its.temerity.model.NewUser import edu.ucsc.its.temerity.model.UserUpdate import io.kotest.core.spec.style.FunSpec