add kdocs to the startup module

This commit is contained in:
InsanusMokrassar 2022-12-06 13:06:21 +06:00
parent 02dbd493c2
commit 09d1047260
8 changed files with 69 additions and 25 deletions

View File

@ -1,9 +1,9 @@
package dev.inmo.micro_utils.startup.launcher package dev.inmo.micro_utils.startup.launcher
import dev.inmo.micro_utils.startup.plugin.ServerPlugin import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class Config( data class Config(
val plugins: List<ServerPlugin> val plugins: List<StartPlugin>
) )

View File

@ -2,10 +2,10 @@ package dev.inmo.micro_utils.startup.launcher
import dev.inmo.kslog.common.i import dev.inmo.kslog.common.i
import dev.inmo.kslog.common.logger import dev.inmo.kslog.common.logger
import dev.inmo.micro_utils.startup.plugin.ServerPlugin import dev.inmo.micro_utils.startup.plugin.StartPlugin
import org.koin.core.Koin import org.koin.core.Koin
object HelloWorldPlugin : ServerPlugin { object HelloWorldPlugin : StartPlugin {
override suspend fun startPlugin(koin: Koin) { override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin) super.startPlugin(koin)
logger.i("Hello world") logger.i("Hello world")

View File

@ -6,8 +6,15 @@ import org.koin.core.KoinApplication
import org.koin.core.context.GlobalContext import org.koin.core.context.GlobalContext
import org.koin.dsl.module import org.koin.dsl.module
/**
* Will create [KoinApplication], init, load modules using [StartLauncherPlugin] and start plugins using the same base
* plugin
*
* @param rawConfig It is expected that this [JsonObject] will contain serialized [Config] ([StartLauncherPlugin] will
* deserialize it in its [StartLauncherPlugin.setupDI]
*/
suspend fun start(rawConfig: JsonObject) { suspend fun start(rawConfig: JsonObject) {
with(StartupLauncherPlugin) { with(StartLauncherPlugin) {
logger.i("Start initialization") logger.i("Start initialization")
val koinApp = KoinApplication.init() val koinApp = KoinApplication.init()
koinApp.modules( koinApp.modules(

View File

@ -4,23 +4,38 @@ import dev.inmo.kslog.common.i
import dev.inmo.kslog.common.taggedLogger import dev.inmo.kslog.common.taggedLogger
import dev.inmo.kslog.common.w import dev.inmo.kslog.common.w
import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.startup.plugin.ServerPlugin import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.joinAll import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.serialization.SerialFormat
import kotlinx.serialization.StringFormat
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.dsl.binds
import org.koin.dsl.module import org.koin.dsl.module
object StartupLauncherPlugin : ServerPlugin { /**
* Default startup plugin. See [setupDI] and [startPlugin] for more info
*/
object StartLauncherPlugin : StartPlugin {
internal val logger = taggedLogger(this) internal val logger = taggedLogger(this)
/**
* Will deserialize [Config] from [config], register it in receiver [Module] (as well as [CoroutineScope] and
* [kotlinx.serialization.json.Json])
*
* Besides, in this method will be called [StartPlugin.setupDI] on each plugin from [Config.plugins]. In case when
* some plugin will not be loaded correctly it will be reported throw the [logger]
*/
override fun Module.setupDI(config: JsonObject) { override fun Module.setupDI(config: JsonObject) {
val pluginsConfig = defaultJson.decodeFromJsonElement(Config.serializer(), config) val pluginsConfig = defaultJson.decodeFromJsonElement(Config.serializer(), config)
single { pluginsConfig } single { pluginsConfig }
single { CoroutineScope(Dispatchers.Default) } single { CoroutineScope(Dispatchers.Default) }
single { defaultJson } binds arrayOf(StringFormat::class, SerialFormat::class)
includes( includes(
pluginsConfig.plugins.mapNotNull { pluginsConfig.plugins.mapNotNull {
@ -37,6 +52,10 @@ object StartupLauncherPlugin : ServerPlugin {
) )
} }
/**
* Takes [CoroutineScope] and [Config] from the [koin], and call starting of each plugin from [Config.plugins]
* ASYNCHRONOUSLY. Just like in [setupDI], in case of fail in some plugin it will be reported using [logger]
*/
override suspend fun startPlugin(koin: Koin) { override suspend fun startPlugin(koin: Koin) {
val scope = koin.get<CoroutineScope>() val scope = koin.get<CoroutineScope>()
koin.get<Config>().plugins.map { plugin -> koin.get<Config>().plugins.map { plugin ->

View File

@ -1,13 +0,0 @@
package dev.inmo.micro_utils.startup.plugin
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
@Serializable(ServerPluginSerializer::class)
interface ServerPlugin {
fun Module.setupDI(config: JsonObject) {}
suspend fun startPlugin(koin: Koin) {}
}

View File

@ -0,0 +1,31 @@
package dev.inmo.micro_utils.startup.plugin
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
/**
* Default plugin for start of your app
*/
@Serializable(StartPluginSerializer::class)
interface StartPlugin {
/**
* This method will be called first to configure [Koin] [Module] related to this plugin. You may use
* [org.koin.core.scope.Scope.get] in your koin definitions like [Module.single] to retrieve
* [kotlinx.coroutines.CoroutineScope], [kotlinx.serialization.json.Json] or [dev.inmo.micro_utils.startup.launcher.Config]
*/
fun Module.setupDI(config: JsonObject) {}
/**
* This method will be called after all other [StartPlugin] will [setupDI]
*
* It is allowed to lock end of this method in case you require to prevent application to end its run (for example,
* you are starting some web server)
*
* @param koin Will contains everything you will register in [setupDI] (as well as other [StartPlugin]s) and
* [kotlinx.coroutines.CoroutineScope], [kotlinx.serialization.json.Json] and [dev.inmo.micro_utils.startup.launcher.Config]
* by their types
*/
suspend fun startPlugin(koin: Koin) {}
}

View File

@ -2,4 +2,4 @@ package dev.inmo.micro_utils.startup.plugin
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
expect object ServerPluginSerializer : KSerializer<ServerPlugin> expect object StartPluginSerializer : KSerializer<StartPlugin>

View File

@ -6,16 +6,16 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
actual object ServerPluginSerializer : KSerializer<ServerPlugin> { actual object StartPluginSerializer : KSerializer<StartPlugin> {
override val descriptor: SerialDescriptor override val descriptor: SerialDescriptor
get() = String.serializer().descriptor get() = String.serializer().descriptor
override fun deserialize(decoder: Decoder): ServerPlugin { override fun deserialize(decoder: Decoder): StartPlugin {
val kclass = Class.forName(decoder.decodeString()).kotlin val kclass = Class.forName(decoder.decodeString()).kotlin
return (kclass.objectInstance ?: kclass.constructors.first { it.parameters.isEmpty() }.call()) as ServerPlugin return (kclass.objectInstance ?: kclass.constructors.first { it.parameters.isEmpty() }.call()) as StartPlugin
} }
override fun serialize(encoder: Encoder, value: ServerPlugin) { override fun serialize(encoder: Encoder, value: StartPlugin) {
encoder.encodeString( encoder.encodeString(
value::class.java.canonicalName value::class.java.canonicalName
) )