Skip to content

Commit

Permalink
Merge pull request #743 from simple-robot/dev/ref-blocking-runner
Browse files Browse the repository at this point in the history
调整BlockingRunner内部实现,移除同步代码块和 wait/notify 的使用;为部分配置类增加直接配置 Executor 的API
  • Loading branch information
ForteScarlet authored Sep 24, 2023
2 parents 69a818d + f22b074 commit d160256
Show file tree
Hide file tree
Showing 14 changed files with 504 additions and 100 deletions.
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ if (!System.getenv("IS_CI").toBoolean()) {
include(":simbot-component-http-server-api")
}

//include(":simbot-project-tests:simbot-project-test-j21")


@Suppress("NOTHING_TO_INLINE")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

package love.forte.simboot.spring.autoconfigure.application

import kotlinx.coroutines.Job
import love.forte.simbot.ExperimentalSimbotApi
import love.forte.simbot.application.*
import love.forte.simbot.core.application.*
Expand Down Expand Up @@ -47,7 +48,7 @@ public object SpringBoot :
val configuration = SpringBootApplicationConfiguration().also(configurator)
return create(configuration, builder)
}

/**
* 直接提供配置类进行构建。
*/
Expand Down Expand Up @@ -109,7 +110,7 @@ public interface SpringBootApplication : Application
*/
public interface SpringBootApplicationBuilder : ApplicationBuilder<SpringBootApplication>,
EventProcessableApplicationBuilder<SpringBootApplication> {

/**
* 配置内部的 core listener manager.
*
Expand All @@ -126,88 +127,88 @@ private class SpringBootApplicationBuilderImpl : SpringBootApplicationBuilder,
BaseApplicationBuilder<SpringBootApplication>() {
private var listenerManagerConfigurator: SimpleListenerManagerConfiguration.(environment: Application.Environment) -> Unit =
{}


/**
* 配置内部的 listener manager.
*/
override fun eventProcessor(configurator: SimpleListenerManagerConfiguration.(environment: Application.Environment) -> Unit) {
val old = listenerManagerConfigurator
listenerManagerConfigurator = { env -> old(env); configurator(env) }
}

private fun buildListenerManager(
appConfig: SpringBootApplicationConfiguration,
environment: Application.Environment,
): SimpleEventListenerManager {
val initial = SimpleListenerManagerConfiguration {
// TODO job?
coroutineContext = appConfig.coroutineContext
// Init context from app context (without Job)
coroutineContext = appConfig.coroutineContext.minusKey(Job)
}

return simpleListenerManager(initial = initial, block = fun SimpleListenerManagerConfiguration.() {
listenerManagerConfigurator(environment)
})
}


@OptIn(ExperimentalSimbotApi::class)
@Suppress("DuplicatedCode")
suspend fun build(configuration: SpringBootApplicationConfiguration): SpringBootApplication {
val components = buildComponents()

val logger = configuration.logger

val environment = SpringBootEnvironment(
components, logger, configuration.coroutineContext
)

logger.debug("Building listener manager...")
val listenerManager = buildListenerManager(configuration, environment)
logger.debug("Listener manager is built: {}", listenerManager)


logger.debug("Building providers...")
val providers = buildProviders(listenerManager, components, configuration)
logger.info("The size of providers built is {}", providers.size)
if (providers.isNotEmpty()) {
logger.debug("The built providers: {}", providers)
}

val application = SpringBootApplicationImpl(configuration, environment, listenerManager, providers)
// set application attribute
listenerManager.globalScopeContext[ApplicationAttributes.Application] = application

// complete.
complete(application)

// region register bots
// after complete.
logger.debug("Registering bots...")
val bots = registerBots(providers)

logger.info("Bots all registered. The size of bots: {}", bots.size)
if (bots.isNotEmpty()) {
logger.debug("The all registered bots: {}", bots)
}
val isAutoStartBots = configuration.isAutoStartBots
logger.debug("Auto start bots: {}", isAutoStartBots)
if (isAutoStartBots && bots.isNotEmpty()) {
bots.forEach { bot ->
logger.info("Starting bot {}", bot)
val started = bot.start()
logger.info("Bot [{}] started: {}", bot, started)
}
bots.forEach { bot ->
logger.info("Starting bot {}", bot)
val started = bot.start()
logger.info("Bot [{}] started: {}", bot, started)
}
}

if (isAutoStartBots && bots.isEmpty()) {
logger.debug("But the registered bots are empty.")
}
// endregion

return application
}

}


Expand All @@ -218,7 +219,7 @@ private class SpringBootApplicationImpl(
providerList: List<EventProvider>,
) : SpringBootApplication, BaseApplication() {
override val providers: List<EventProvider> = providerList.view()

override val coroutineContext = environment.coroutineContext
override val logger: Logger = environment.logger
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@

package love.forte.simbot.application

import kotlinx.coroutines.asCoroutineDispatcher
import love.forte.plugin.suspendtrans.annotation.JvmBlocking
import love.forte.simbot.Api4J
import love.forte.simbot.Component
import love.forte.simbot.ComponentFactory
import love.forte.simbot.ability.CompletionPerceivable
import love.forte.simbot.bot.Bot
import love.forte.simbot.bot.BotVerifyInfo
import org.slf4j.Logger
import java.util.concurrent.Executor
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

Expand All @@ -33,7 +36,7 @@ public interface ApplicationFactory<
Builder : ApplicationBuilder<A>,
A : Application,
> {

/**
* 提供配置函数和构建器函数,构建一个 [Application] 实例。
*/
Expand All @@ -51,7 +54,7 @@ public interface ApplicationFactory<
* @param A 目标 [Application] 类型
*/
public interface ApplicationBuilder<A : Application> : CompletionPerceivable<A> {

/**
* 注册一个 [组件][Component].
*/
Expand All @@ -60,7 +63,7 @@ public interface ApplicationBuilder<A : Application> : CompletionPerceivable<A>
componentFactory: ComponentFactory<C, Config>,
configurator: Config.(perceivable: CompletionPerceivable<A>) -> Unit = {},
)

/**
* 注册一个事件提供者。
*/
Expand All @@ -69,15 +72,15 @@ public interface ApplicationBuilder<A : Application> : CompletionPerceivable<A>
eventProviderFactory: EventProviderFactory<P, Config>,
configurator: Config.(perceivable: CompletionPerceivable<A>) -> Unit = {},
)


/**
* 提供一个可以使用 [BotVerifyInfo] 进行通用性bot注册的配置方式。
*/
@ApplicationBuilderDsl
public fun bots(registrar: suspend BotRegistrar.() -> Unit)


/**
* 注册一个当 [Application] 构建完成后的回调函数。
*
Expand All @@ -91,7 +94,7 @@ public interface ApplicationBuilder<A : Application> : CompletionPerceivable<A>
*/
@ApplicationBuilderDsl
override fun onCompletion(handle: suspend (application: A) -> Unit)

}


Expand All @@ -105,7 +108,7 @@ public interface ApplicationBuilder<A : Application> : CompletionPerceivable<A>
*
*/
public interface BotRegistrar {

/**
* 当前环境中的所有事件提供者。
*
Expand All @@ -124,8 +127,8 @@ public interface BotRegistrar {
*
*/
public val providers: List<EventProvider>


/**
* 通过 [BotVerifyInfo] 中的 [组件信息][BotVerifyInfo.componentId]
* 去当前环境中寻找对应组件的、实现了 [Bot注册器][love.forte.simbot.bot.BotRegistrar] 的 [事件提供者][EventProvider],
Expand All @@ -150,7 +153,7 @@ public annotation class ApplicationBuilderDsl
* 整个应用程序进行构建所需的基本配置信息。
*/
public open class ApplicationConfiguration {

/**
* 当前application内所使用的协程上下文。
*
Expand All @@ -159,10 +162,21 @@ public open class ApplicationConfiguration {
*
*/
public open var coroutineContext: CoroutineContext = EmptyCoroutineContext

/**
* 提供一个用于Application内部的日志对象。
*/
public open var logger: Logger = love.forte.simbot.logger.LoggerFactory.getLogger("love.forte.simbot.application.ApplicationConfiguration")

public open var logger: Logger =
love.forte.simbot.logger.LoggerFactory.getLogger("love.forte.simbot.application.ApplicationConfiguration")

/**
* 向 [coroutineContext] 中应用一个 [Executor]。
* 面向Java开发者的友好API,在Java中可以更方便的指定一个调度器。
*
* @since 3.3.0
*/
@Api4J
public open fun appendExecutorToCoroutineContext(executor: Executor) {
coroutineContext += executor.asCoroutineDispatcher()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

package love.forte.simbot.core.application

import kotlinx.coroutines.Job
import love.forte.simbot.application.Application
import love.forte.simbot.application.ApplicationBuilder
import love.forte.simbot.application.ApplicationBuilderDsl
Expand Down Expand Up @@ -71,7 +72,7 @@ public abstract class BaseStandardApplicationBuilder<A : Application> : BaseAppl
environment: Application.Environment,
): SimpleEventListenerManager {
val initial = SimpleListenerManagerConfiguration {
coroutineContext = appConfig.coroutineContext
coroutineContext = appConfig.coroutineContext.minusKey(Job)
}

return simpleListenerManager(initial = initial) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@

package love.forte.simbot.core.event

import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.serialization.modules.EmptySerializersModule
import kotlinx.serialization.modules.SerializersModule
import love.forte.simbot.*
import love.forte.simbot.event.*
import love.forte.simbot.event.EventListenerRegistrationDescription.Companion.toRegistrationDescription
import love.forte.simbot.logger.LoggerFactory
import love.forte.simbot.logger.logger
import java.util.concurrent.Executor
import java.util.function.Function
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
Expand All @@ -43,7 +48,24 @@ public open class SimpleListenerManagerConfiguration {
*/
@SimpleEventManagerConfigDSL
public var coroutineContext: CoroutineContext = EmptyCoroutineContext

set(value) {
if (value[Job] != null) {
logger.warn("Job in SimpleListenerManagerConfiguration.coroutineContext will be dropped.")
}
field = value.minusKey(Job)
}

/**
* 向 [coroutineContext] 中应用一个 [Executor]。
* 面向Java开发者的友好API,在Java中可以更方便的指定一个调度器。
*
* @since 3.3.0
*/
@Api4J
public open fun appendExecutorToCoroutineContext(executor: Executor) {
coroutineContext += executor.asCoroutineDispatcher()
}

/**
* 事件流程拦截器的列表。
*/
Expand Down Expand Up @@ -266,6 +288,8 @@ public open class SimpleListenerManagerConfiguration {
public inline operator fun invoke(block: SimpleListenerManagerConfiguration.() -> Unit): SimpleListenerManagerConfiguration {
return SimpleListenerManagerConfiguration().also(block)
}

private val logger = LoggerFactory.logger<SimpleListenerManagerConfiguration>()
}

}
Expand Down
Loading

0 comments on commit d160256

Please sign in to comment.