From 4b48053ae743dbd717db4badcdcd008c9b401485 Mon Sep 17 00:00:00 2001 From: Suwings Date: Wed, 16 Mar 2022 09:15:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E7=BB=88=E6=AD=A2?= =?UTF-8?q?=E5=BC=82=E6=AD=A5=E4=BB=BB=E5=8A=A1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entity/commands/base/command.ts | 1 + src/entity/commands/general/general_update.ts | 26 +++++++++++++++---- src/entity/instance/instance.ts | 4 ++- src/entity/instance/preset.ts | 3 ++- src/routers/Instance_router.ts | 26 +++++++++++++++++-- 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/entity/commands/base/command.ts b/src/entity/commands/base/command.ts index 4c6e15d..bfffa89 100644 --- a/src/entity/commands/base/command.ts +++ b/src/entity/commands/base/command.ts @@ -22,4 +22,5 @@ export default class InstanceCommand { constructor(public info?: string) {} async exec(instance: any): Promise {} + async stop(instance: any) {} } diff --git a/src/entity/commands/general/general_update.ts b/src/entity/commands/general/general_update.ts index 951cf19..83b39fd 100644 --- a/src/entity/commands/general/general_update.ts +++ b/src/entity/commands/general/general_update.ts @@ -26,12 +26,21 @@ import InstanceCommand from "../base/command"; import { commandStringToArray } from "../base/command_parser"; import iconv from "iconv-lite"; export default class GeneralUpdateCommand extends InstanceCommand { + private pid: number = null; + constructor() { super("GeneralUpdateCommand"); } + private stoped(instance: Instance) { + instance.asynchronousTask = null; + instance.setLock(false); + instance.status(Instance.STATUS_STOP); + } + async exec(instance: Instance) { if (instance.status() !== Instance.STATUS_STOP) return instance.failure(new Error("实例状态不正确,无法执行更新任务,必须停止实例")); + if (instance.asynchronousTask !== null) return instance.failure(new Error("实例状态不正确,有其他任务正在运行中")); try { instance.setLock(true); const updateCommand = instance.config.updateCommand; @@ -54,10 +63,15 @@ export default class GeneralUpdateCommand extends InstanceCommand { windowsHide: true }); if (!process || !process.pid) { - instance.setLock(false); + this.stoped(instance); return instance.println("错误", "更新失败,更新命令启动失败,请联系管理员"); } + //pid 保存 + this.pid = process.pid; + + // 设置实例正在运行的异步任务 + instance.asynchronousTask = this; instance.status(Instance.STATUS_BUSY); process.stdout.on("data", (text) => { @@ -67,8 +81,7 @@ export default class GeneralUpdateCommand extends InstanceCommand { instance.println("异常", iconv.decode(text, instance.config.oe)); }); process.on("exit", (code) => { - instance.setLock(false); - instance.status(Instance.STATUS_STOP); + this.stoped(instance); if (code === 0) { instance.println("更新", "更新成功!"); } else { @@ -76,8 +89,11 @@ export default class GeneralUpdateCommand extends InstanceCommand { } }); } catch { - instance.setLock(false); - instance.status(Instance.STATUS_STOP); + this.stoped(instance); } } + + async stop(instance: Instance): Promise { + logger.info(`用户请求终止实例 ${instance.instanceUuid} 的 update 异步任务`); + } } diff --git a/src/entity/instance/instance.ts b/src/entity/instance/instance.ts index 8d8c13a..de9e2c7 100644 --- a/src/entity/instance/instance.ts +++ b/src/entity/instance/instance.ts @@ -22,7 +22,7 @@ import { EventEmitter } from "events"; import iconv from "iconv-lite"; import path from "path"; - +import { IExecutable } from "./preset"; import InstanceCommand from "../commands/base/command"; import InstanceConfig from "./Instance_config"; import StorageSubsystem from "../../common/system_storage"; @@ -64,6 +64,8 @@ export default class Instance extends EventEmitter { public lock: boolean; public startCount: number; public startTimestamp: number = 0; + // 正在进行的异步任务 + public asynchronousTask: IExecutable = null; // 生命周期任务,定时任务管理器 public readonly lifeCycleTaskManager = new LifeCycleTaskManager(this); diff --git a/src/entity/instance/preset.ts b/src/entity/instance/preset.ts index b1d3bbd..fe137c4 100644 --- a/src/entity/instance/preset.ts +++ b/src/entity/instance/preset.ts @@ -19,8 +19,9 @@ 可以前往 https://mcsmanager.com/ 阅读用户协议,申请闭源开发授权等。 */ -interface IExecutable { +export interface IExecutable { exec: (a: any, b?: any) => Promise; + stop?: (a: any) => Promise; } export class PresetCommandManager { diff --git a/src/routers/Instance_router.ts b/src/routers/Instance_router.ts index 3826838..07b4106 100644 --- a/src/routers/Instance_router.ts +++ b/src/routers/Instance_router.ts @@ -285,13 +285,35 @@ routerApp.on("instance/asynchronous", (ctx, data) => { const instanceUuid = data.instanceUuid; const taskName = data.taskName; const parameter = data.parameter; + const instance = InstanceSubsystem.getInstance(instanceUuid); + logger.info(`会话 ${ctx.socket.id} 要求实例 ${instance.instanceUuid} 执行异步 ${taskName} 异步任务`); if (taskName === "update") { - const instance = InstanceSubsystem.getInstance(instanceUuid); - instance.execPreset("update", parameter).then(() => {}); + instance + .execPreset("update", parameter) + .then(() => {}) + .catch((err) => { + logger.error(`实例 ${instance.instanceUuid} ${taskName} 异步任务执行异常: ${err}`); + }); } protocol.msg(ctx, "instance/asynchronous", true); }); +// 终止执行复杂异步任务 +routerApp.on("instance/stop_asynchronous", (ctx, data) => { + const instanceUuid = data.instanceUuid; + const instance = InstanceSubsystem.getInstance(instanceUuid); + const task = instance.asynchronousTask; + if (task && task.stop) { + task + .stop(instance) + .then(() => {}) + .catch((err) => {}); + } else { + return protocol.error(ctx, "instance/stop_asynchronous", "无任务异步任务正在运行"); + } + protocol.msg(ctx, "instance/stop_asynchronous", true); +}); + // 向应用实例发送数据流 routerApp.on("instance/stdin", (ctx, data) => { // 本路由采用兼容性低且直接原始的方式来进行写数据