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.Bot
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
import net.mamoe.mirai.console.command.ConsoleCommandSender 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.data.PluginDataStorage
import net.mamoe.mirai.console.extension.ComponentStorage import net.mamoe.mirai.console.extension.ComponentStorage
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge 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.extension.GlobalComponentStorage
import net.mamoe.mirai.console.internal.logging.LoggerControllerImpl 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.internal.pluginManagerImpl
import net.mamoe.mirai.console.logging.LoggerController import net.mamoe.mirai.console.logging.LoggerController
import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.Plugin
@ -85,6 +89,18 @@ public interface MiraiConsoleImplementation : CoroutineScope {
*/ */
public val builtInPluginLoaders: List<Lazy<PluginLoader<*, *>>> 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 用户实现 * Kotlin 用户实现
* *
@ -188,6 +204,54 @@ public interface MiraiConsoleImplementation : CoroutineScope {
*/ */
public val loggerController: LoggerController get() = LoggerControllerImpl 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 /// Hooks & Backend Access
/** /**
@ -231,6 +295,12 @@ public interface MiraiConsoleImplementation : CoroutineScope {
// PluginManagerImpl.resolvedPlugins // PluginManagerImpl.resolvedPlugins
public val resolvedPlugins: MutableList<Plugin> 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.ConfigurationKey
import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig.Account.PasswordKind.MD5 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.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.data.builtins.LoggerConfig
import net.mamoe.mirai.console.internal.extension.BuiltInSingletonExtensionSelector import net.mamoe.mirai.console.internal.extension.BuiltInSingletonExtensionSelector
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
@ -82,8 +81,6 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope,
override val mainLogger: MiraiLogger by lazy { createLogger("main") } override val mainLogger: MiraiLogger by lazy { createLogger("main") }
val consoleDataScope by lazy { ConsoleDataScope(coroutineContext, dataStorageForBuiltIns, dataStorageForBuiltIns) }
init { init {
// TODO: Replace to standard api // TODO: Replace to standard api
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")

View File

@ -10,6 +10,7 @@
package net.mamoe.mirai.console.internal.data.builtins package net.mamoe.mirai.console.internal.data.builtins
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.console.MiraiConsoleImplementation
import net.mamoe.mirai.console.data.AutoSavePluginDataHolder import net.mamoe.mirai.console.data.AutoSavePluginDataHolder
import net.mamoe.mirai.console.data.PluginConfig import net.mamoe.mirai.console.data.PluginConfig
import net.mamoe.mirai.console.data.PluginData import net.mamoe.mirai.console.data.PluginData
@ -19,23 +20,23 @@ import net.mamoe.mirai.utils.minutesToMillis
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
internal class ConsoleDataScope( internal class ConsoleDataScopeImpl(
parentCoroutineContext: CoroutineContext, parentCoroutineContext: CoroutineContext,
private val dataStorage: PluginDataStorage, private val dataStorage: PluginDataStorage,
private val configStorage: PluginDataStorage, private val configStorage: PluginDataStorage,
) : CoroutineScope by parentCoroutineContext.childScope("ConsoleDataScope") { ) : CoroutineScope by parentCoroutineContext.childScope("ConsoleDataScope"), MiraiConsoleImplementation.ConsoleDataScope {
val dataHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginDataHolder(this.coroutineContext) override val dataHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginDataHolder(this.coroutineContext)
val configHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginConfigHolder(this.coroutineContext) override val configHolder: AutoSavePluginDataHolder = ConsoleBuiltInPluginConfigHolder(this.coroutineContext)
private val data: List<PluginData> = mutableListOf() private val data: List<PluginData> = mutableListOf()
private val configs: MutableList<PluginConfig> = mutableListOf(AutoLoginConfig) private val configs: MutableList<PluginConfig> = mutableListOf(AutoLoginConfig)
fun addAndReloadConfig(config: PluginConfig) { override fun addAndReloadConfig(config: PluginConfig) {
configs.add(config) configs.add(config)
configStorage.load(configHolder, config) configStorage.load(configHolder, config)
} }
fun reloadAll() { override fun reloadAll() {
data.forEach { dt -> data.forEach { dt ->
dataStorage.load(dataHolder, 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.AbstractFilePluginLoader
import net.mamoe.mirai.console.plugin.loader.PluginLoadException import net.mamoe.mirai.console.plugin.loader.PluginLoadException
import net.mamoe.mirai.console.plugin.name import net.mamoe.mirai.console.plugin.name
import net.mamoe.mirai.utils.childScope
import net.mamoe.mirai.utils.MiraiLogger 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 net.mamoe.mirai.utils.verbose
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlin.coroutines.CoroutineContext
internal object BuiltInJvmPluginLoaderImpl : internal val JvmPluginLoader.implOrNull get() = this.castOrNull<BuiltInJvmPluginLoaderImpl>()
AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"),
CoroutineScope by MiraiConsole.childScope("JvmPluginLoader", CoroutineExceptionHandler { _, throwable -> internal class BuiltInJvmPluginLoaderImpl(
BuiltInJvmPluginLoaderImpl.logger.error("Unhandled Jar plugin exception: ${throwable.message}", throwable) parentCoroutineContext: CoroutineContext
) : AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"),
CoroutineScope by parentCoroutineContext.childScope("JvmPluginLoader", CoroutineExceptionHandler { _, throwable ->
logger.error("Unhandled Jar plugin exception: ${throwable.message}", throwable)
}), }),
JvmPluginLoader { JvmPluginLoader {
companion object {
internal val logger: MiraiLogger = MiraiConsole.createLogger(JvmPluginLoader::class.simpleName!!)
}
override val configStorage: PluginDataStorage override val configStorage: PluginDataStorage
get() = MiraiConsoleImplementationBridge.configStorageForJvmPluginLoader get() = MiraiConsoleImplementationBridge.configStorageForJvmPluginLoader
@JvmStatic
internal val logger: MiraiLogger = MiraiConsole.createLogger(JvmPluginLoader::class.simpleName!!)
override val dataStorage: PluginDataStorage override val dataStorage: PluginDataStorage
get() = MiraiConsoleImplementationBridge.dataStorageForJvmPluginLoader get() = MiraiConsoleImplementationBridge.dataStorageForJvmPluginLoader
internal val classLoaders: MutableList<JvmPluginClassLoader> = mutableListOf() override val classLoaders: MutableList<JvmPluginClassLoader> = mutableListOf()
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // doesn't matter @Suppress("EXTENSION_SHADOWED_BY_MEMBER") // doesn't matter
override fun getPluginDescription(plugin: JvmPlugin): JvmPluginDescription = plugin.description 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.MiraiConsole
import net.mamoe.mirai.console.data.runCatchingLog import net.mamoe.mirai.console.data.runCatchingLog
import net.mamoe.mirai.console.extension.PluginComponentStorage 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.data.mkdir
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
import net.mamoe.mirai.console.permission.Permission 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.AbstractJvmPlugin
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin.Companion.onLoad 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 net.mamoe.mirai.utils.MiraiLogger
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
@ -144,15 +145,13 @@ internal abstract class JvmPluginInternal(
) )
} }
.plus(parentCoroutineContext) .plus(parentCoroutineContext)
.plus(CoroutineName("Plugin ${(this as AbstractJvmPlugin).dataHolderName}"))
.plus( .plus(
NamedSupervisorJob( SupervisorJob(parentCoroutineContext[Job] ?: JvmPluginLoader.coroutineContext[Job]!!)
"Plugin ${(this as AbstractJvmPlugin).dataHolderName}",
parentCoroutineContext[Job] ?: BuiltInJvmPluginLoaderImpl.coroutineContext[Job]!!
)
) )
.also { .also {
if (!MiraiConsole.isActive) return@also if (!MiraiConsole.isActive) return@also
BuiltInJvmPluginLoaderImpl.coroutineContext[Job]!!.invokeOnCompletion { JvmPluginLoader.coroutineContext[Job]!!.invokeOnCompletion {
this.cancel() this.cancel()
} }
} }

View File

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

View File

@ -12,7 +12,7 @@
package net.mamoe.mirai.console.internal.util package net.mamoe.mirai.console.internal.util
import net.mamoe.mirai.console.internal.data.cast 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 net.mamoe.mirai.utils.createInstanceOrNull
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.* import java.util.*
@ -39,7 +39,7 @@ internal object PluginServiceHelper {
}.let { ServiceList(this, it) } }.let { ServiceList(this, it) }
fun <T : Any> ServiceList<T>.loadAllServices(): List<T> { 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( private fun <T : Any> ClassLoader.loadService(
@ -69,7 +69,7 @@ internal object PluginServiceHelper {
fun <T : Any> loadAllServicesFromMemoryAndPluginClassLoaders(service: KClass<T>): List<T> { fun <T : Any> loadAllServicesFromMemoryAndPluginClassLoaders(service: KClass<T>): List<T> {
val list = ServiceLoader.load(service.java, this::class.java.classLoader).toList() 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 package net.mamoe.mirai.console.plugin.jvm
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import me.him188.kotlin.dynamic.delegation.dynamicDelegation
import net.mamoe.mirai.console.data.PluginDataStorage 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.internal.plugin.BuiltInJvmPluginLoaderImpl
import net.mamoe.mirai.console.plugin.loader.FilePluginLoader import net.mamoe.mirai.console.plugin.loader.FilePluginLoader
import net.mamoe.mirai.utils.MiraiInternalApi
import net.mamoe.mirai.utils.NotStableForInheritance
/** /**
* JVM 插件加载器 * JVM 插件加载器
*/ */
@NotStableForInheritance
public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> { public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> {
/** /**
* ".jar" * ".jar"
@ -33,7 +38,15 @@ public interface JvmPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, J
*/ */
public val configStorage: PluginDataStorage 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") @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
override fun getPluginDescription(plugin: JvmPlugin): JvmPluginDescription = override fun getPluginDescription(plugin: JvmPlugin): JvmPluginDescription =
BuiltInJvmPluginLoaderImpl.run { plugin.description } BuiltInJvmPluginLoaderImpl.run { plugin.description }

View File

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

View File

@ -74,8 +74,17 @@ open class MiraiConsoleImplementationTerminal
val coroutineName = coroutineContext[CoroutineName]?.name ?: "<unnamed>" val coroutineName = coroutineContext[CoroutineName]?.name ?: "<unnamed>"
MiraiConsole.mainLogger.error("Exception in coroutine $coroutineName", throwable) 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 consoleInput: ConsoleInput get() = ConsoleInputImpl
override val isAnsiSupported: Boolean get() = true 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 { override fun createLoginSolver(requesterBot: Long, configuration: BotConfiguration): LoginSolver {
LoginSolver.Default?.takeIf { it !is StandardCharImageLoginSolver }?.let { return it } LoginSolver.Default?.takeIf { it !is StandardCharImageLoginSolver }?.let { return it }