From 4bb2337f3997d8b4b2f8c868e6662a1fe86f8957 Mon Sep 17 00:00:00 2001 From: MiaoWoo Date: Wed, 18 Nov 2020 16:32:09 +0800 Subject: [PATCH] refactor(core): core task function move event loop task to @ccms/micro-task thread BREAKING CHANGE: setTimeout & setInterval no longer run on main thread Signed-off-by: MiaoWoo --- packages/core/src/index.ts | 23 +++++------------ packages/ployfill/src/node-shim.ts | 41 +++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7f7cc27f..feddb291 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,25 +1,23 @@ let containerStartTime = Date.now() console.i18n("ms.core.ioc.initialize", { scope: global.scope }) import { plugin, server, task, constants } from '@ccms/api' -import { DefaultContainer as container, inject, provideSingleton, ContainerInstance, buildProviderModule } from '@ccms/container' +import { DefaultContainer as container, inject, provideSingleton, ContainerInstance, buildProviderModule, Autowired } from '@ccms/container' console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 }) import http from '@ccms/common/dist/http' @provideSingleton(MiaoScriptCore) class MiaoScriptCore { - @inject(server.Console) + @Autowired(server.Console) private Console: Console - @inject(task.TaskManager) - private taskManager: task.TaskManager - @inject(plugin.PluginFolder) + @Autowired(plugin.PluginFolder) private pluginFolder: string - @inject(plugin.PluginManager) + @Autowired() + private taskManager: task.TaskManager + @Autowired() private pluginManager: plugin.PluginManager enable() { this.loadServerConsole() - this.loadTaskFunction() - global.level = "TRACE" this.loadPlugins() return () => this.disable() } @@ -29,15 +27,6 @@ class MiaoScriptCore { global.setGlobal('console', new this.Console(), { writable: false, configurable: false }) } - loadTaskFunction() { - global.setGlobal('setTimeout', (func: Function, tick: number, ...args: any[]) => { - return this.taskManager.create(func).later(tick).submit(...args) - }, { writable: false, configurable: false }) - global.setGlobal('setInterval', (func: Function, tick: number, ...args: any[]) => { - return this.taskManager.create(func).timer(tick).submit(...args) - }, { writable: false, configurable: false }) - } - loadPlugins() { let loadPluginStartTime = new Date().getTime() console.i18n("ms.core.plugin.initialize") diff --git a/packages/ployfill/src/node-shim.ts b/packages/ployfill/src/node-shim.ts index 3c4018ec..2d81d1fe 100644 --- a/packages/ployfill/src/node-shim.ts +++ b/packages/ployfill/src/node-shim.ts @@ -5,6 +5,7 @@ const ThreadGroup = Java.type("java.lang.ThreadGroup") const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger") const ThreadPoolExecutor = Java.type('java.util.concurrent.ThreadPoolExecutor') const LinkedBlockingQueue = Java.type("java.util.concurrent.LinkedBlockingQueue") +const TimeUnit = Java.type("java.util.concurrent.TimeUnit") const threadCount = new AtomicInteger(0) const threadGroup = new ThreadGroup("@ccms/ployfill-micro-task") @@ -14,7 +15,6 @@ const microTaskPool = new ThreadPoolExecutor( (run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()), new ThreadPoolExecutor.CallerRunsPolicy() ) - class Process extends EventEmitter { env = { __noSuchProperty__: (prop) => { @@ -44,7 +44,46 @@ class Process extends EventEmitter { exit(code: number) { process.emit('exit', code) microTaskPool.shutdown() + console.log('await microTaskPool termination...') + microTaskPool.awaitTermination(5000, TimeUnit.MILLISECONDS) } } +const timeoutCount = new AtomicInteger(0) +const timeoutTasks = [] +function setTimeout(func: Function, time: number, ...args: any[]) { + let taskId = timeoutCount.incrementAndGet() + timeoutTasks[taskId] = func + process.nextTick(() => { + Thread.sleep(time) + if (timeoutTasks[taskId]) { func(...args) } + }) + return taskId +} +function clearTimeout(taskId: number) { + delete timeoutTasks[taskId] +} +const intervalCount = new AtomicInteger(0) +const intervalTasks = [] +function setInterval(func: Function, time: number, ...args: any[]) { + let taskId = intervalCount.incrementAndGet() + intervalTasks[taskId] = func + process.nextTick(() => { + Thread.sleep(time) + while (intervalTasks[taskId]) { + func(...args) + Thread.sleep(time) + } + }) + return taskId +} +function clearInterval(taskId: number) { + delete intervalTasks[taskId] +} global.setGlobal('process', new Process(), {}) global.setGlobal('queueMicrotask', (func: any) => microTaskPool.execute(func), {}) +global.setGlobal('setTimeout', setTimeout, {}) +global.setGlobal('clearTimeout', clearTimeout, {}) +global.setGlobal('setImmediate', (func: Function, ...args: any[]) => setTimeout(func, 0, ...args), {}) +global.setGlobal('clearImmediate ', clearTimeout, {}) +global.setGlobal('setInterval', setInterval, {}) +global.setGlobal('clearInterval', clearInterval, {})