Change JvmPluginLoader and ConsoleDataScope from singleton to instances.

This commit is contained in:
Him188 2021-12-26 18:44:33 +00:00
parent 05187f5162
commit 8435131499
10 changed files with 137 additions and 31 deletions

View File

@ -16,12 +16,16 @@ import kotlinx.coroutines.*
import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
import net.mamoe.mirai.console.command.ConsoleCommandSender
import net.mamoe.mirai.console.data.PluginDataHolder
import net.mamoe.mirai.console.data.AutoSavePluginDataHolder
import net.mamoe.mirai.console.data.PluginConfig
import net.mamoe.mirai.console.data.PluginData
import net.mamoe.mirai.console.data.PluginDataStorage
import net.mamoe.mirai.console.extension.ComponentStorage
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
import net.mamoe.mirai.console.internal.data.builtins.ConsoleDataScopeImpl
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
import net.mamoe.mirai.console.internal.logging.LoggerControllerImpl
import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
import net.mamoe.mirai.console.internal.pluginManagerImpl
import net.mamoe.mirai.console.logging.LoggerController
import net.mamoe.mirai.console.plugin.Plugin
@ -85,6 +89,18 @@ public interface MiraiConsoleImplementation : CoroutineScope {
*/
public val builtInPluginLoaders: List<Lazy<PluginLoader<*, *>>>
/**
* [JvmPluginLoader] 实例. 建议实现为 lazy:
*
* ```
* override val jvmPluginLoader: JvmPluginLoader by lazy { backendAccess.createDefaultJvmPluginLoader(coroutineContext) }
* ```
*
* @see BackendAccess.createDefaultJvmPluginLoader
* @since 2.10.0-RC
*/
public val jvmPluginLoader: JvmPluginLoader
/**
* Kotlin 用户实现
*
@ -188,6 +204,54 @@ public interface MiraiConsoleImplementation : CoroutineScope {
*/
public val loggerController: LoggerController get() = LoggerControllerImpl
///////////////////////////////////////////////////////////////////////////
// ConsoleDataScope
///////////////////////////////////////////////////////////////////////////
/**
* Mirai Console 内置的一些 [PluginConfig] [PluginData] 的管理器.
*
* 建议实现为 lazy:
* ```
* override val consoleDataScope: MiraiConsoleImplementation.ConsoleDataScope by lazy {
* MiraiConsoleImplementation.ConsoleDataScope.createDefault(
* coroutineContext,
* dataStorageForBuiltIns,
* configStorageForBuiltIns
* )
* }
* ```
*
* @since 2.10.0-RC
*/
public val consoleDataScope: ConsoleDataScope
/**
* Mirai Console 内置的一些 [PluginConfig] [PluginData] 的管理器.
*
* @since 2.10.0-RC
*/
@ConsoleFrontEndImplementation
public interface ConsoleDataScope {
public val dataHolder: AutoSavePluginDataHolder
public val configHolder: AutoSavePluginDataHolder
public fun addAndReloadConfig(config: PluginConfig)
public fun reloadAll()
/**
* @since 2.10.0-RCl
*/
@ConsoleFrontEndImplementation
public companion object {
@JvmStatic
public fun createDefault(
coroutineContext: CoroutineContext,
dataStorage: PluginDataStorage,
configStorage: PluginDataStorage
): ConsoleDataScope = ConsoleDataScopeImpl(coroutineContext, dataStorage, configStorage)
}
}
/// Hooks & Backend Access
/**
@ -231,6 +295,12 @@ public interface MiraiConsoleImplementation : CoroutineScope {
// PluginManagerImpl.resolvedPlugins
public val resolvedPlugins: MutableList<Plugin>
/**
* @since 2.10.0-RC
*/
public fun createDefaultJvmPluginLoader(coroutineContext: CoroutineContext): JvmPluginLoader =
BuiltInJvmPluginLoaderImpl(coroutineContext)
}
/**

View File

@ -31,7 +31,6 @@ import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.ConfigurationKey
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.PasswordKind.MD5
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.PasswordKind.PLAIN
import net.mamoe.mirai.console.internal.data.builtins.ConsoleDataScope
import net.mamoe.mirai.console.internal.data.builtins.LoggerConfig
import net.mamoe.mirai.console.internal.extension.BuiltInSingletonExtensionSelector
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
@ -82,8 +81,6 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope,
override val mainLogger: MiraiLogger by lazy { createLogger("main") }
val consoleDataScope by lazy { ConsoleDataScope(coroutineContext, dataStorageForBuiltIns, dataStorageForBuiltIns) }
init {
// TODO: Replace to standard api
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")

View File

@ -10,6 +10,7 @@
package net.mamoe.mirai.console.internal.data.builtins
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.console.MiraiConsoleImplementation
import net.mamoe.mirai.console.data.AutoSavePluginDataHolder
import net.mamoe.mirai.console.data.PluginConfig
import net.mamoe.mirai.console.data.PluginData
@ -19,23 +20,23 @@ import net.mamoe.mirai.utils.minutesToMillis
import kotlin.coroutines.CoroutineContext
internal class ConsoleDataScope(
internal class ConsoleDataScopeImpl(
parentCoroutineContext: CoroutineContext,
private val dataStorage: PluginDataStorage,
private val configStorage: PluginDataStorage,
) : CoroutineScope by parentCoroutineContext.childScope("ConsoleDataScope") {
val dataHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginDataHolder(this.coroutineContext)
val configHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginConfigHolder(this.coroutineContext)
) : CoroutineScope by parentCoroutineContext.childScope("ConsoleDataScope"), MiraiConsoleImplementation.ConsoleDataScope {
override val dataHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginDataHolder(this.coroutineContext)
override val configHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginConfigHolder(this.coroutineContext)
private val data: List<PluginData> = mutableListOf()
private val configs: MutableList<PluginConfig> = mutableListOf(AutoLoginConfig)
fun addAndReloadConfig(config: PluginConfig) {
override fun addAndReloadConfig(config: PluginConfig) {
configs.add(config)
configStorage.load(configHolder, config)
}
fun reloadAll() {
override fun reloadAll() {
data.forEach { dt ->
dataStorage.load(dataHolder, dt)
}

View File

@ -22,30 +22,36 @@ import net.mamoe.mirai.console.plugin.jvm.*
import net.mamoe.mirai.console.plugin.loader.AbstractFilePluginLoader
import net.mamoe.mirai.console.plugin.loader.PluginLoadException
import net.mamoe.mirai.console.plugin.name
import net.mamoe.mirai.utils.childScope
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.castOrNull
import net.mamoe.mirai.utils.childScope
import net.mamoe.mirai.utils.verbose
import java.io.File
import java.nio.file.Path
import java.util.concurrent.ConcurrentHashMap
import kotlin.coroutines.CoroutineContext
internal object BuiltInJvmPluginLoaderImpl :
AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"),
CoroutineScope by MiraiConsole.childScope("JvmPluginLoader", CoroutineExceptionHandler { _, throwable ->
BuiltInJvmPluginLoaderImpl.logger.error("Unhandled Jar plugin exception: ${throwable.message}", throwable)
internal val JvmPluginLoader.implOrNull get() = this.castOrNull<BuiltInJvmPluginLoaderImpl>()
internal class BuiltInJvmPluginLoaderImpl(
parentCoroutineContext: CoroutineContext
) : AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"),
CoroutineScope by parentCoroutineContext.childScope("JvmPluginLoader", CoroutineExceptionHandler { _, throwable ->
logger.error("Unhandled Jar plugin exception: ${throwable.message}", throwable)
}),
JvmPluginLoader {
companion object {
internal val logger: MiraiLogger = MiraiConsole.createLogger(JvmPluginLoader::class.simpleName!!)
}
override val configStorage: PluginDataStorage
get() = MiraiConsoleImplementationBridge.configStorageForJvmPluginLoader
@JvmStatic
internal val logger: MiraiLogger = MiraiConsole.createLogger(JvmPluginLoader::class.simpleName!!)
override val dataStorage: PluginDataStorage
get() = MiraiConsoleImplementationBridge.dataStorageForJvmPluginLoader
internal val classLoaders: MutableList<JvmPluginClassLoader> = mutableListOf()
override val classLoaders: MutableList<JvmPluginClassLoader> = mutableListOf()
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // doesn't matter
override fun getPluginDescription(plugin: JvmPlugin): JvmPluginDescription = plugin.description

View File

@ -15,6 +15,7 @@ import kotlinx.coroutines.*
import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.data.runCatchingLog
import net.mamoe.mirai.console.extension.PluginComponentStorage
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
import net.mamoe.mirai.console.internal.data.mkdir
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
import net.mamoe.mirai.console.permission.Permission
@ -26,7 +27,7 @@ import net.mamoe.mirai.console.plugin.ResourceContainer.Companion.asResourceCont
import net.mamoe.mirai.console.plugin.jvm.AbstractJvmPlugin
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin.Companion.onLoad
import net.mamoe.mirai.console.util.NamedSupervisorJob
import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.utils.MiraiLogger
import java.io.File
import java.io.InputStream
@ -144,15 +145,13 @@ internal abstract class JvmPluginInternal(
)
}
.plus(parentCoroutineContext)
.plus(CoroutineName("Plugin ${(this as AbstractJvmPlugin).dataHolderName}"))
.plus(
NamedSupervisorJob(
"Plugin ${(this as AbstractJvmPlugin).dataHolderName}",
parentCoroutineContext[Job] ?: BuiltInJvmPluginLoaderImpl.coroutineContext[Job]!!
)
SupervisorJob(parentCoroutineContext[Job] ?: JvmPluginLoader.coroutineContext[Job]!!)
)
.also {
if (!MiraiConsole.isActive) return@also
BuiltInJvmPluginLoaderImpl.coroutineContext[Job]!!.invokeOnCompletion {
JvmPluginLoader.coroutineContext[Job]!!.invokeOnCompletion {
this.cancel()
}
}

View File

@ -12,7 +12,8 @@
package net.mamoe.mirai.console.internal.util
import io.github.karlatemp.caller.StackFrame
import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
import net.mamoe.mirai.console.internal.plugin.implOrNull
import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
@ -37,7 +38,7 @@ internal inline fun <reified E : Throwable> runIgnoreException(block: () -> Unit
internal fun StackFrame.findLoader(): ClassLoader? {
classInstance?.let { return it.classLoader }
return runCatching {
BuiltInJvmPluginLoaderImpl.classLoaders.firstOrNull { it.findClass(className, true) != null }
JvmPluginLoader.implOrNull?.classLoaders?.firstOrNull { it.findClass(className, true) != null }
}.getOrNull()
}

View File

@ -12,7 +12,7 @@
package net.mamoe.mirai.console.internal.util
import net.mamoe.mirai.console.internal.data.cast
import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.utils.createInstanceOrNull
import java.lang.reflect.Modifier
import java.util.*
@ -39,7 +39,7 @@ internal object PluginServiceHelper {
}.let { ServiceList(this, it) }
fun <T : Any> ServiceList<T>.loadAllServices(): List<T> {
return delegate.mapNotNull { classLoader.loadService<T>(it) }
return delegate.mapNotNull { classLoader.loadService(it) }
}
private fun <T : Any> ClassLoader.loadService(
@ -69,7 +69,7 @@ internal object PluginServiceHelper {
fun <T : Any> loadAllServicesFromMemoryAndPluginClassLoaders(service: KClass<T>): List<T> {
val list = ServiceLoader.load(service.java, this::class.java.classLoader).toList()
return list + BuiltInJvmPluginLoaderImpl.classLoaders.flatMap { it.findServices(service).loadAllServices() }
return list + JvmPluginLoader.classLoaders.flatMap { it.findServices(service).loadAllServices() }
}
}

View File

@ -10,13 +10,18 @@
package net.mamoe.mirai.console.plugin.jvm
import kotlinx.coroutines.CoroutineScope
import me.him188.kotlin.dynamic.delegation.dynamicDelegation
import net.mamoe.mirai.console.data.PluginDataStorage
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
import net.mamoe.mirai.console.plugin.loader.FilePluginLoader
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.NotStableForInheritance
/**
* JVM 插件加载器
*/
@NotStableForInheritance
public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> {
/**
* ".jar"
@ -33,7 +38,15 @@ public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, J
*/
public val configStorage: PluginDataStorage
public companion object BuiltIn : JvmPluginLoader by BuiltInJvmPluginLoaderImpl {
/**
* @since 2.10
*/
@MiraiInternalApi
public val classLoaders: List<ClassLoader>
public companion object BuiltIn :
JvmPluginLoader by (dynamicDelegation { MiraiConsoleImplementationBridge.jvmPluginLoader }) {
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
override fun getPluginDescription(plugin: JvmPlugin): JvmPluginDescription =
BuiltInJvmPluginLoaderImpl.run { plugin.description }

View File

@ -47,6 +47,9 @@ fun initTestEnvironment() {
}
override val builtInPluginLoaders: List<Lazy<PluginLoader<*, *>>> = listOf(lazy { JvmPluginLoader })
override val jvmPluginLoader: JvmPluginLoader by lazy {
backendAccess.createDefaultJvmPluginLoader(coroutineContext)
}
override val consoleCommandSender: MiraiConsoleImplementation.ConsoleCommandSenderImpl =
object : MiraiConsoleImplementation.ConsoleCommandSenderImpl {
override suspend fun sendMessage(message: Message) {
@ -76,6 +79,13 @@ fun initTestEnvironment() {
return PlatformLogger(identity)
}
override val consoleDataScope: MiraiConsoleImplementation.ConsoleDataScope by lazy {
MiraiConsoleImplementation.ConsoleDataScope.createDefault(
coroutineContext,
dataStorageForBuiltIns,
configStorageForBuiltIns
)
}
override val coroutineContext: CoroutineContext =
CoroutineName("Console Main") + SupervisorJob() + CoroutineExceptionHandler { _, throwable ->
throwable.printStackTrace()

View File

@ -74,8 +74,17 @@ open class MiraiConsoleImplementationTerminal
val coroutineName = coroutineContext[CoroutineName]?.name ?: "<unnamed>"
MiraiConsole.mainLogger.error("Exception in coroutine $coroutineName", throwable)
}) {
override val jvmPluginLoader: JvmPluginLoader by lazy { backendAccess.createDefaultJvmPluginLoader(coroutineContext) }
override val consoleInput: ConsoleInput get() = ConsoleInputImpl
override val isAnsiSupported: Boolean get() = true
override val consoleDataScope: MiraiConsoleImplementation.ConsoleDataScope by lazy {
MiraiConsoleImplementation.ConsoleDataScope.createDefault(
coroutineContext,
dataStorageForBuiltIns,
configStorageForBuiltIns
)
}
override fun createLoginSolver(requesterBot: Long, configuration: BotConfiguration): LoginSolver {
LoginSolver.Default?.takeIf { it !is StandardCharImageLoginSolver }?.let { return it }