forked from mirror/MCSM-Daemon
Refactor: install flow and hiper flow
This commit is contained in:
parent
b572c5fe50
commit
13473fba9f
@ -243,6 +243,7 @@
|
||||
},
|
||||
|
||||
"quick_install": {
|
||||
"unzipError": "解压文件失败"
|
||||
"unzipError": "解压文件失败",
|
||||
"hiperError": "HiPer 进程已存在,不可重复启动!"
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import { ProcessConfig } from "../entity/instance/process_config";
|
||||
import RestartCommand from "../entity/commands/restart";
|
||||
import { TaskCenter } from "../service/async_task_service";
|
||||
import { createQuickInstallTask } from "../service/async_task_service/quick_install";
|
||||
import { HiPerTask, openHiPerTask } from "../service/async_task_service/hiper_start";
|
||||
import { QuickInstallTask } from "../service/async_task_service/quick_install";
|
||||
|
||||
// Some instances operate router authentication middleware
|
||||
routerApp.use((event, ctx, data, next) => {
|
||||
@ -296,6 +298,11 @@ routerApp.on("instance/asynchronous", (ctx, data) => {
|
||||
const task = createQuickInstallTask(targetLink, newInstanceName);
|
||||
return protocol.response(ctx, task.toObject());
|
||||
}
|
||||
// Start HiPer Network
|
||||
if (taskName === "hiper") {
|
||||
const indexCode = String(parameter.indexCode);
|
||||
openHiPerTask(indexCode);
|
||||
}
|
||||
protocol.response(ctx, true);
|
||||
});
|
||||
|
||||
@ -330,6 +337,7 @@ routerApp.on("instance/stop_asynchronous", (ctx, data) => {
|
||||
// Query async task status
|
||||
routerApp.on("instance/query_asynchronous", (ctx, data) => {
|
||||
const taskId = data.parameter.taskId as string | undefined;
|
||||
// const type = String(data.parameter.type) || QuickInstallTask.TYPE;
|
||||
if (!taskId) {
|
||||
const result = [];
|
||||
for (const task of TaskCenter.tasks) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ChildProcess } from "child_process";
|
||||
// Copyright (C) 2022 MCSManager <mcsmanager-dev@outlook.com>
|
||||
|
||||
import { v4 } from "uuid";
|
||||
@ -8,26 +7,35 @@ import InstanceSubsystem from "../system_instance";
|
||||
import InstanceConfig from "../../entity/instance/Instance_config";
|
||||
import { $t, i18next } from "../../i18n";
|
||||
import path from "path";
|
||||
|
||||
import { spawn, ChildProcess } from "child_process";
|
||||
import { getFileManager } from "../file_router_service";
|
||||
import EventEmitter from "events";
|
||||
import { IAsyncTask, IAsyncTaskJSON, TaskCenter } from "./index";
|
||||
import { AsyncTask, IAsyncTask, IAsyncTaskJSON, TaskCenter } from "./index";
|
||||
import logger from "../log";
|
||||
import { downloadFileToLocalFile } from "../download";
|
||||
import os from "os";
|
||||
|
||||
// singleton pattern
|
||||
class HiPer {
|
||||
public static hiperProcess: ChildProcess;
|
||||
public static hiperFileName: string = os.platform() === "win32" ? "hiper.exe" : "hiper";
|
||||
public static hiperFilePath: string;
|
||||
|
||||
export class HiPer {
|
||||
public static subProcess: ChildProcess;
|
||||
public static openHiPer(keyPath: string) {
|
||||
if (HiPer.hiperProcess) {
|
||||
throw new Error($t("quick_install.hiperError"));
|
||||
}
|
||||
HiPer.hiperFilePath = path.normalize(path.join(process.cwd(), "lib", HiPer.hiperFileName));
|
||||
HiPer.hiperProcess = spawn("hiper", ["-v", keyPath]);
|
||||
}
|
||||
|
||||
public static openHiPer(keyPath: string) {}
|
||||
|
||||
public static stopHiPer() {}
|
||||
public static stopHiPer() {
|
||||
HiPer.hiperProcess = null;
|
||||
}
|
||||
}
|
||||
|
||||
export class HiPerTask extends EventEmitter implements IAsyncTask {
|
||||
public taskId: string;
|
||||
public instance: Instance;
|
||||
export class HiPerTask extends AsyncTask {
|
||||
public static readonly TYPE = "HiPerTask";
|
||||
|
||||
public readonly KEY_YML = path.normalize(path.join(process.cwd(), "lib", "hiper", "key.yml"));
|
||||
public readonly POINT_YML = path.normalize(path.join(process.cwd(), "lib", "hiper", "point.yml"));
|
||||
@ -35,16 +43,14 @@ export class HiPerTask extends EventEmitter implements IAsyncTask {
|
||||
|
||||
private keyYmlPath: string;
|
||||
private pointYmlPath: string;
|
||||
private _status = 0; // 0=stop 1=running -1=error 2=downloading
|
||||
|
||||
constructor(public readonly instanceUuid: string, public readonly indexCode: string) {
|
||||
constructor(public readonly indexCode: string) {
|
||||
super();
|
||||
this.taskId = `HiPerTask-${instanceUuid}-${v4()}`;
|
||||
this.taskId = `${HiPerTask.TYPE}-${indexCode}-${v4()}`;
|
||||
this.type = HiPerTask.TYPE;
|
||||
}
|
||||
|
||||
async start() {
|
||||
this._status = 1;
|
||||
this.emit("started");
|
||||
async onStarted(): Promise<boolean | void> {
|
||||
try {
|
||||
// Download hiper key.yml
|
||||
await downloadFileToLocalFile(`${this.BASE_URL}/${this.indexCode}.yml`, this.KEY_YML);
|
||||
@ -52,8 +58,7 @@ export class HiPerTask extends EventEmitter implements IAsyncTask {
|
||||
// Download hiper point.yml
|
||||
await downloadFileToLocalFile(`${this.BASE_URL}/point.yml`, this.KEY_YML);
|
||||
|
||||
// TODO: The node information in point.yml is overwritten to key.yml
|
||||
// fs.writeFile()
|
||||
// The node information in point.yml is overwritten to key.yml
|
||||
let keyFile = fs.readFileSync(this.KEY_YML, "utf-8");
|
||||
const pointFile = fs.readFileSync(this.POINT_YML, "utf-8");
|
||||
const START_TEXT = ">>> AUTO SYNC AREA";
|
||||
@ -73,36 +78,27 @@ export class HiPerTask extends EventEmitter implements IAsyncTask {
|
||||
// Start Command: hiper.exe -config .\key.yml
|
||||
HiPer.openHiPer(this.keyYmlPath);
|
||||
} catch (error) {
|
||||
logger.error("HiPer Task Error:", error);
|
||||
this.emit("failure");
|
||||
} finally {
|
||||
this.stop();
|
||||
this.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
this._status = 0;
|
||||
this.emit("stopped");
|
||||
onStopped(): Promise<boolean | void> {
|
||||
HiPer.stopHiPer();
|
||||
return null;
|
||||
}
|
||||
|
||||
failure() {
|
||||
this._status = -1;
|
||||
this.emit("failure");
|
||||
}
|
||||
|
||||
status(): number {
|
||||
return this._status;
|
||||
}
|
||||
onError(): void {}
|
||||
|
||||
toObject(): IAsyncTaskJSON {
|
||||
return JSON.parse(
|
||||
JSON.stringify({
|
||||
taskId: this.taskId,
|
||||
status: this.status(),
|
||||
instanceUuid: this.instance.instanceUuid,
|
||||
instanceStatus: this.instance.status(),
|
||||
instanceConfig: this.instance.config
|
||||
status: this.status()
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function openHiPerTask(indexCode: string) {
|
||||
TaskCenter.addTask(new HiPerTask(indexCode));
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
import EventEmitter from "events";
|
||||
import logger from "../log";
|
||||
|
||||
export interface IAsyncTaskJSON {
|
||||
[key: string]: any;
|
||||
}
|
||||
@ -10,32 +9,78 @@ export interface IAsyncTaskJSON {
|
||||
export interface IAsyncTask extends EventEmitter {
|
||||
// The taskId must be complex enough to prevent other users from accessing the information
|
||||
taskId: string;
|
||||
type: string;
|
||||
start(): Promise<boolean | void>;
|
||||
stop(): Promise<boolean | void>;
|
||||
status(): number;
|
||||
toObject(): IAsyncTaskJSON;
|
||||
}
|
||||
|
||||
export abstract class AsyncTask extends EventEmitter implements IAsyncTask {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public taskId: string;
|
||||
public type: string;
|
||||
|
||||
// 0=stop 1=running -1=error 2=downloading
|
||||
protected _status = 0;
|
||||
|
||||
public start() {
|
||||
return this.onStarted();
|
||||
}
|
||||
public stop() {
|
||||
this.emit("stopped");
|
||||
return this.onStopped();
|
||||
}
|
||||
public error(err: any) {
|
||||
logger.error(`AsyncTask - ID: ${this.taskId} TYPE: ${this.type} Error:`, err);
|
||||
this.emit("error", err);
|
||||
this.stop();
|
||||
}
|
||||
|
||||
status(): number {
|
||||
return this._status;
|
||||
}
|
||||
|
||||
abstract onStarted(): Promise<boolean | void>;
|
||||
abstract onStopped(): Promise<boolean | void>;
|
||||
abstract onError(): void;
|
||||
abstract toObject(): IAsyncTaskJSON;
|
||||
}
|
||||
|
||||
export class TaskCenter {
|
||||
public static tasks = new Array<IAsyncTask>();
|
||||
|
||||
public static addTask(t: IAsyncTask) {
|
||||
TaskCenter.tasks.push(t);
|
||||
t.start();
|
||||
t.on("stopped", () => TaskCenter.onTaskStopped(t));
|
||||
t.on("failure", () => TaskCenter.onTaskFailure(t));
|
||||
t.on("error", () => TaskCenter.onTaskError(t));
|
||||
}
|
||||
|
||||
public static onTaskStopped(t: IAsyncTask) {
|
||||
logger.info("Async Task:", t.taskId, "Stopped.");
|
||||
}
|
||||
|
||||
public static onTaskFailure(t: IAsyncTask) {
|
||||
public static onTaskError(t: IAsyncTask) {
|
||||
logger.info("Async Task:", t.taskId, "Failed.");
|
||||
}
|
||||
|
||||
public static getTask(taskId: string) {
|
||||
public static getTask(taskId: string, type?: string) {
|
||||
for (const iterator of TaskCenter.tasks) {
|
||||
if (iterator.taskId === taskId) return iterator;
|
||||
if (iterator.taskId === taskId && (type == null || iterator.type === type)) return iterator;
|
||||
}
|
||||
}
|
||||
|
||||
public static getTasks(taskId: string, type?: string) {
|
||||
const result: IAsyncTask[] = [];
|
||||
for (const iterator of TaskCenter.tasks) {
|
||||
if (iterator.taskId === taskId && (type == null || iterator.type === type)) {
|
||||
result.push(iterator);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -11,17 +11,17 @@ import { $t, i18next } from "../../i18n";
|
||||
import path from "path";
|
||||
import { getFileManager } from "../file_router_service";
|
||||
import EventEmitter from "events";
|
||||
import { IAsyncTask, IAsyncTaskJSON, TaskCenter } from "./index";
|
||||
import { IAsyncTask, IAsyncTaskJSON, TaskCenter, AsyncTask } from "./index";
|
||||
import logger from "../log";
|
||||
|
||||
export class QuickInstallTask extends EventEmitter implements IAsyncTask {
|
||||
public taskId: string;
|
||||
export class QuickInstallTask extends AsyncTask {
|
||||
public static TYPE = "QuickInstallTask";
|
||||
|
||||
public instance: Instance;
|
||||
public readonly TMP_ZIP_NAME = "mcsm_install_package.zip";
|
||||
public readonly ZIP_CONFIG_JSON = "mcsmanager-config.json";
|
||||
public zipPath = "";
|
||||
|
||||
private _status = 0; // 0=stop 1=running -1=error 2=downloading
|
||||
private downloadStream: fs.WriteStream = null;
|
||||
|
||||
constructor(public instanceName: string, public targetLink: string) {
|
||||
@ -32,7 +32,8 @@ export class QuickInstallTask extends EventEmitter implements IAsyncTask {
|
||||
config.stopCommand = "stop";
|
||||
config.type = Instance.TYPE_MINECRAFT_JAVA;
|
||||
this.instance = InstanceSubsystem.createInstance(config);
|
||||
this.taskId = `QuickInstallTask-${this.instance.instanceUuid}-${v4()}`;
|
||||
this.taskId = `${QuickInstallTask.TYPE}-${this.instance.instanceUuid}-${v4()}`;
|
||||
this.type = QuickInstallTask.TYPE;
|
||||
}
|
||||
|
||||
private download(): Promise<boolean> {
|
||||
@ -53,9 +54,7 @@ export class QuickInstallTask extends EventEmitter implements IAsyncTask {
|
||||
});
|
||||
}
|
||||
|
||||
async start() {
|
||||
this._status = 1;
|
||||
this.emit("started");
|
||||
async onStarted() {
|
||||
const fileManager = getFileManager(this.instance.instanceUuid);
|
||||
try {
|
||||
let result = await this.download();
|
||||
@ -65,29 +64,19 @@ export class QuickInstallTask extends EventEmitter implements IAsyncTask {
|
||||
this.instance.parameters(config);
|
||||
this.stop();
|
||||
} catch (error) {
|
||||
logger.error("QuickInstall Task Error:", error);
|
||||
this.emit("failure");
|
||||
this.error(error);
|
||||
} finally {
|
||||
fs.remove(fileManager.toAbsolutePath(this.TMP_ZIP_NAME), () => {});
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
async onStopped(): Promise<boolean | void> {
|
||||
try {
|
||||
if (this.downloadStream) this.downloadStream.destroy(new Error("STOP TASK"));
|
||||
} catch (error) {}
|
||||
this._status = 0;
|
||||
this.emit("stopped");
|
||||
}
|
||||
|
||||
failure() {
|
||||
this._status = -1;
|
||||
this.emit("failure");
|
||||
}
|
||||
|
||||
status(): number {
|
||||
return this._status;
|
||||
}
|
||||
onError(): void {}
|
||||
|
||||
toObject(): IAsyncTaskJSON {
|
||||
return JSON.parse(
|
||||
|
Loading…
Reference in New Issue
Block a user