Skip to content

Commit

Permalink
Experimental | Optimize Element's Evaluating & Add Script Config
Browse files Browse the repository at this point in the history
Prepare for element re-handle
  • Loading branch information
TheFloodDragon committed Jul 26, 2024
1 parent 9b5fa28 commit 6586bf1
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import cn.fd.ratziel.common.config.Settings
import cn.fd.ratziel.common.element.DefaultElementLoader
import cn.fd.ratziel.common.element.ElementEvaluator
import cn.fd.ratziel.common.event.WorkspaceLoadEvent
import cn.fd.ratziel.core.element.Element
import cn.fd.ratziel.core.util.FutureFactory
import taboolib.common.LifeCycle
import taboolib.common.platform.Awake
import taboolib.common.platform.ProxyCommandSender
import taboolib.common.platform.function.console
import taboolib.module.lang.sendLang
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.Executors
import kotlin.time.Duration
import kotlin.time.TimeSource
Expand All @@ -23,7 +21,8 @@ object WorkspaceLoader {
/**
* 缓存的元素
*/
val cachedElements = ConcurrentLinkedQueue<Element>()
lateinit var lastEvaluator: ElementEvaluator
private set

/**
* 线程池
Expand All @@ -46,20 +45,20 @@ object WorkspaceLoader {
* 加载工作空间中的元素
*/
fun load(sender: ProxyCommandSender): CompletableFuture<Duration> {
cachedElements.clear() // 清空缓存
WorkspaceLoadEvent.Start().call() // 事件 - 开始加载
val timeMark = TimeSource.Monotonic.markNow() // 开始记录时间
val result = CompletableFuture<Duration>()
val evaluator = ElementEvaluator(executor) // 创建评估器
// 创建异步工厂
// 创建评估器
val evaluator = ElementEvaluator(executor)
lastEvaluator = evaluator
// 创建任务工厂
FutureFactory {
for (file in WorkspaceManager.getFilteredFiles()) {
submitAsync(executor) {
try {
// 加载元素文件
DefaultElementLoader.load(file).onEach {
evaluator.submitWith(it) // 提交到评估器
cachedElements.add(it) // 插入缓存
}
} catch (ex: Exception) {
ex.printStackTrace()
Expand All @@ -71,7 +70,7 @@ object WorkspaceLoader {
// 评估器开始评估
evaluator.evaluate().thenAccept {
val time = loadTime.plus(it) // 计算最终时间 = 加载时间 + 评估时间
sender.sendLang("Workspace-Finished", cachedElements.size, time.inWholeMilliseconds)
sender.sendLang("Workspace-Finished", evaluator.evaluatedElements.size, time.inWholeMilliseconds)
WorkspaceLoadEvent.End().call() // 事件 - 结束加载
result.complete(time) // 完成最后任务
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ object CommandElement {
val list = subCommand {
executeAsync<ProxyCommandSender> { sender, _, _ ->
sender.sendLang("Element-Header")
WorkspaceLoader.cachedElements.forEach {
WorkspaceLoader.lastEvaluator.evaluatedElements.values.forEach {
sender.sendLang("Element-Identifier-Format", it.name) // 名称
sender.sendLang(
"Element-Info-Format",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package cn.fd.ratziel.common.element

import cn.fd.ratziel.common.element.registry.ElementConfig
import cn.fd.ratziel.core.element.Element
import cn.fd.ratziel.core.element.ElementIdentifier
import cn.fd.ratziel.core.element.api.ElementHandler
import cn.fd.ratziel.core.element.service.ElementRegistry
import cn.fd.ratziel.core.util.FutureFactory
import cn.fd.ratziel.function.ArgumentContext
import cn.fd.ratziel.function.SimpleArgumentContext
import cn.fd.ratziel.function.popOrNull
import taboolib.common.LifeCycle
import taboolib.common.TabooLib
import taboolib.common.platform.function.severe
Expand All @@ -26,6 +24,14 @@ import kotlin.time.TimeSource
*/
class ElementEvaluator(val executor: Executor) {

/**
* 加载过的元素表
*/
val evaluatedElements: MutableMap<ElementIdentifier, Element> = ConcurrentHashMap()

/**
* 评估任务表
*/
val evaluations: MutableMap<LifeCycle, MutableList<EvaluationTask>> = ConcurrentHashMap()

/**
Expand Down Expand Up @@ -55,7 +61,7 @@ class ElementEvaluator(val executor: Executor) {
val factory = FutureFactory<Throwable?>()
// 遍历任务单个处理
tasks.forEach { task ->
factory += handleElement(task.handler, task.element) // 提交任务
factory += handleTask(task) // 提交任务
}
factory.thenRun {
// 完成后完成传入任务, 返回时间
Expand All @@ -65,62 +71,58 @@ class ElementEvaluator(val executor: Executor) {

/**
* 调用 [ElementHandler] 处理 [Element]
* @param handler 元素处理器
* @param element 要处理的元素
* @return [CompletableFuture] - 过程的中可能存在的异常
*/
fun handleElement(handler: ElementHandler, element: Element, async: Boolean = false): CompletableFuture<Throwable?> {
fun handleTask(task: EvaluationTask): CompletableFuture<Throwable?> {
// 创建处理任务
val future = CompletableFuture<Throwable?>()
// 处理函数 (非立即执行)
val function = Runnable {
try {
handler.handle(element)
future.complete(null) // 完成任务
val element = task.element
// 处理元素
task.handler.handle(element)
// 缓存评估过的元素
evaluatedElements[element.identifier] = element
// 完成任务
future.complete(null)
} catch (ex: Throwable) {
severe("Couldn't handle element by $handler!")
severe("Couldn't handle element by ${task.handler}!")
ex.printStackTrace()
future.complete(ex) // 异常时返回(尽管已经处理过了)
}
}
// 异步 & 同步 处理
if (async) {
if (task.config.async) {
CompletableFuture.runAsync(function, executor)
} else {
function.run()
}
return future // 返回任务
}

/**
* 提交评估任务
*/
fun submitTask(task: EvaluationTask) =
evaluations.computeIfAbsent(popConfig(task.args).lifeCycle) { CopyOnWriteArrayList() }.add(task)

/**
* 解析 [Element] 并提交评估任务
*/
fun submitWith(element: Element) {
// 注册到处理器表
for (handler in ElementRegistry.getHandlersByType(element.type)) {
val args = SimpleArgumentContext(findConfig(handler))
submitTask(EvaluationTask(element, handler, args))
submitTask(EvaluationTask(element, handler, findConfig(handler)))
}
}

/**
* 提交评估任务
*/
fun submitTask(task: EvaluationTask) = evaluations.computeIfAbsent(task.config.lifeCycle) { CopyOnWriteArrayList() }.add(task)

/**
* 评估任务
*/
class EvaluationTask(val element: Element, val handler: ElementHandler, val args: ArgumentContext)
class EvaluationTask(val element: Element, val handler: ElementHandler, val config: ElementConfig)

companion object {

/**
* 弹出 [ElementConfig]
*/
fun popConfig(args: ArgumentContext): ElementConfig = args.popOrNull<ElementConfig>() ?: ElementConfig()

/**
* 获取[ElementHandler]的[ElementConfig]
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ class ElementRegister : ClassVisitor(0) {
if (clazz.isAnnotationPresent(NewElement::class.java)) {
val anno = clazz.getAnnotation(NewElement::class.java)
try {
val etype = ElementType(anno.space, anno.name, anno.alias)
val type = ElementType(anno.space, anno.name, anno.alias)
/**
* 处理器
*/
if (ElementHandler::class.java.isAssignableFrom(clazz)) {
// 获取实例
val handler = clazz.asSubclass(ElementHandler::class.java).getInstance(true)!!.get()
ElementRegistry.register(etype, handler, anno.priority)
} else ElementRegistry.register(etype)
ElementRegistry.register(type, handler, anno.priority)
} else ElementRegistry.register(type)
} catch (e: Exception) {
severe("Unable to register element form class $clazz!")
e.printStackTrace()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ annotation class NewElement(
/**
* 命名空间
*/
val space: String = "ez",
val space: String = "ratziel",
/**
* 如果使用此注解的类是元素处理器
* 则该项代表着元素处理器的优先级
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package cn.fd.ratziel.script

import cn.fd.ratziel.common.config.Settings
import cn.fd.ratziel.script.api.ScriptType
import taboolib.common.LifeCycle
import taboolib.common.env.RuntimeEnv
import taboolib.common.platform.Awake
import taboolib.library.configuration.ConfigurationSection

/**
* ScriptManager
Expand All @@ -15,11 +18,37 @@ object ScriptManager {
var defaultScriptLanguage: ScriptType = ScriptTypes.KETHER
internal set

@Awake
private fun initLanguages() {
// Load Env
@Awake(LifeCycle.LOAD)
private fun init() {
// Read config
val conf = Settings.conf.getConfigurationSection("Script")

// Default Language
val defLanguage = conf?.getString("Default")?.let { ScriptTypes.match(it) }
if (defLanguage != null) defaultScriptLanguage = defLanguage

// Options
val optionsConf = conf?.getConfigurationSection("Options")

// Function - get script options from conf
fun getOptions(names: Array<out String>): ConfigurationSection? {
if (optionsConf != null) {
for (entry in optionsConf.getValues(false)) {
if (names.contains(entry.key)) return entry.value as ConfigurationSection
}
}
return null
}

// Init
for (lang in ScriptTypes.entries) {
if (lang.enabled) RuntimeEnv.ENV.loadDependency(lang.executor::class.java)
val options = getOptions(lang.names)
lang.enabled = options?.getBoolean("enabled", true) ?: true
// If the script is enabled
if (lang.enabled) {
// LoadEnv
RuntimeEnv.ENV.loadDependency(lang.executor::class.java)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package cn.fd.ratziel.script
import cn.fd.ratziel.script.api.ScriptEnvironment
import cn.fd.ratziel.script.api.ScriptExecutor
import cn.fd.ratziel.script.api.ScriptType
import cn.fd.ratziel.script.js.JavaScriptExecutor
import cn.fd.ratziel.script.jexl.JexlExecutor
import cn.fd.ratziel.script.js.JavaScriptExecutor
import cn.fd.ratziel.script.kether.KetherExecutor
import cn.fd.ratziel.script.kts.KotlinScriptExecutor
import java.util.concurrent.CopyOnWriteArrayList
Expand Down Expand Up @@ -34,7 +34,7 @@ enum class ScriptTypes(
val appliers: MutableList<ScriptEnvironment.Applier> = CopyOnWriteArrayList()
) : ScriptType {

JAVASCRIPT(JavaScriptExecutor, "js", "JavaScript", "javascript", "java-script", "JS"),
JAVASCRIPT(JavaScriptExecutor, "js", "JavaScript", "javascript", "java-script", "JS", "Js"),
KETHER(KetherExecutor, "Kether", "kether", "ke", "ks"),
JEXL(JexlExecutor, "Jexl", "jexl", "Jexl3", "jexl3"),
KOTLIN_SCRIPTING(KotlinScriptExecutor, "Kotlin", "kotlin", "kts", "KTS");
Expand Down
12 changes: 12 additions & 0 deletions project/module-script/src/main/resources/settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 脚本相关内容配置
Script:
Default: Kether # 默认使用的脚本引擎
Options:
JavaScript:
enabled: true
Kether:
enabled: true
Jexl:
enabled: true
Kotlin:
enabled: true

0 comments on commit 6586bf1

Please sign in to comment.