@elementspanel/epanel-plugin-instance 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/daemon/backend/index.cjs
CHANGED
|
@@ -226,9 +226,26 @@ function commandStringToArray(cmd) {
|
|
|
226
226
|
|
|
227
227
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
228
228
|
exports.ChildProcessAdapter = void 0;
|
|
229
|
+
exports.instanceProcessHost = instanceProcessHost;
|
|
230
|
+
exports.spawnInstanceProcess = spawnInstanceProcess;
|
|
229
231
|
exports.waitForSpawn = waitForSpawn;
|
|
230
232
|
const events_1 = __webpack_require__("events");
|
|
231
233
|
const mcsmanager_common_1 = __webpack_require__("../common/src/index.ts");
|
|
234
|
+
const INSTANCE_HOST = Symbol.for("elementspanel.instance-process-host");
|
|
235
|
+
function instanceProcessHost() {
|
|
236
|
+
return globalThis[INSTANCE_HOST];
|
|
237
|
+
}
|
|
238
|
+
function spawnInstanceProcess(instance, fallback, file, args, options, metadata = {}) {
|
|
239
|
+
const host = instanceProcessHost();
|
|
240
|
+
return host
|
|
241
|
+
? host.spawn(instance.instanceUuid, file, args, options, {
|
|
242
|
+
startTimestamp: instance.startTimestamp,
|
|
243
|
+
startCount: instance.startCount,
|
|
244
|
+
autoRestartCount: instance.autoRestartCount,
|
|
245
|
+
...metadata
|
|
246
|
+
})
|
|
247
|
+
: fallback(file, args, options);
|
|
248
|
+
}
|
|
232
249
|
/** spawn() reports failures asynchronously, including a missing executable. */
|
|
233
250
|
function waitForSpawn(process) {
|
|
234
251
|
return new Promise((resolve, reject) => {
|
|
@@ -266,7 +283,9 @@ class ChildProcessAdapter extends events_1.EventEmitter {
|
|
|
266
283
|
super();
|
|
267
284
|
this.child = child;
|
|
268
285
|
this.pid = child.pid;
|
|
269
|
-
child.once("close", () => {
|
|
286
|
+
child.once("close", () => {
|
|
287
|
+
this.closed = true;
|
|
288
|
+
});
|
|
270
289
|
// close follows the final stdout/stderr data; exit can arrive before it.
|
|
271
290
|
child.on("close", this.onExit);
|
|
272
291
|
child.on("error", this.onError);
|
|
@@ -292,6 +311,9 @@ class ChildProcessAdapter extends events_1.EventEmitter {
|
|
|
292
311
|
if (this.pid)
|
|
293
312
|
return (0, mcsmanager_common_1.killProcess)(this.pid, this.child, signal);
|
|
294
313
|
}
|
|
314
|
+
snapshot(metadata) {
|
|
315
|
+
this.child.setMetadata?.(metadata);
|
|
316
|
+
}
|
|
295
317
|
destroy() {
|
|
296
318
|
if (this.disposed)
|
|
297
319
|
return;
|
|
@@ -326,6 +348,7 @@ class ChildProcessAdapter extends events_1.EventEmitter {
|
|
|
326
348
|
this.child.stdin?.destroy();
|
|
327
349
|
this.child.stdout?.destroy();
|
|
328
350
|
this.child.stderr?.destroy();
|
|
351
|
+
this.child.release?.();
|
|
329
352
|
}
|
|
330
353
|
}
|
|
331
354
|
}
|
|
@@ -1030,20 +1053,19 @@ class GeneralStartCommand extends start_1.default {
|
|
|
1030
1053
|
instance.println("INFO", (0, i18n_1.$t)("TXT_CODE_ba09da46", { name: runAsConfig.runAsName }));
|
|
1031
1054
|
}
|
|
1032
1055
|
// create child process
|
|
1033
|
-
const subProcess = (0, child_process_1.spawn
|
|
1056
|
+
const subProcess = (0, process_adapter_1.spawnInstanceProcess)(instance, child_process_1.spawn, commandExeFile, commandParameters, {
|
|
1034
1057
|
...runAsConfig,
|
|
1035
1058
|
cwd: instance.absoluteCwdPath(),
|
|
1036
1059
|
stdio: "pipe",
|
|
1037
1060
|
windowsHide: true,
|
|
1038
1061
|
env: instance.generateEnv(),
|
|
1039
|
-
// Do not detach the child process;
|
|
1040
|
-
// otherwise, an abnormal exit of the parent process may cause the child process to continue running,
|
|
1041
|
-
// leading to an abnormal instance state.
|
|
1042
1062
|
detached: false
|
|
1043
1063
|
});
|
|
1044
1064
|
const processAdapter = new process_adapter_1.ChildProcessAdapter(subProcess);
|
|
1045
1065
|
try {
|
|
1046
1066
|
await (0, process_adapter_1.waitForSpawn)(subProcess);
|
|
1067
|
+
processAdapter.pid = subProcess.pid;
|
|
1068
|
+
subProcess.setMetadata?.({ pid: subProcess.pid });
|
|
1047
1069
|
instance.started(processAdapter);
|
|
1048
1070
|
}
|
|
1049
1071
|
catch (error) {
|
|
@@ -1470,17 +1492,14 @@ class PtyStartCommand extends start_1.default {
|
|
|
1470
1492
|
}
|
|
1471
1493
|
instance.println("INFO", "> " + commandList.join(" "));
|
|
1472
1494
|
// create pty child process
|
|
1473
|
-
const subProcess = (0, child_process_1.spawn
|
|
1495
|
+
const subProcess = (0, process_adapter_1.spawnInstanceProcess)(instance, child_process_1.spawn, const_1.PTY_PATH, ptyParameter, {
|
|
1474
1496
|
...runAsConfig,
|
|
1475
1497
|
cwd: path_1.default.dirname(const_1.PTY_PATH),
|
|
1476
1498
|
stdio: "pipe",
|
|
1477
1499
|
windowsHide: true,
|
|
1478
1500
|
env: instance.generateEnv(),
|
|
1479
|
-
// Do not detach the child process;
|
|
1480
|
-
// otherwise, an abnormal exit of the parent process may cause the child process to continue running,
|
|
1481
|
-
// leading to an abnormal instance state.
|
|
1482
1501
|
detached: false
|
|
1483
|
-
});
|
|
1502
|
+
}, { pipeName });
|
|
1484
1503
|
const processAdapter = new GoPtyProcessAdapter(subProcess, subProcess.pid, pipeName);
|
|
1485
1504
|
try {
|
|
1486
1505
|
const [, config] = await Promise.all([
|
|
@@ -1488,6 +1507,7 @@ class PtyStartCommand extends start_1.default {
|
|
|
1488
1507
|
this.readPtySubProcessConfig(subProcess)
|
|
1489
1508
|
]);
|
|
1490
1509
|
processAdapter.pid = config.pid;
|
|
1510
|
+
subProcess.setMetadata?.({ pid: config.pid });
|
|
1491
1511
|
if (subProcess.exitCode !== null || subProcess.signalCode !== null)
|
|
1492
1512
|
throw new StartupError((0, i18n_1.$t)("TXT_CODE_pty_start.instanceStartErr"));
|
|
1493
1513
|
instance.started(processAdapter);
|
|
@@ -1547,6 +1567,17 @@ class AbsStartCommand extends command_1.default {
|
|
|
1547
1567
|
// Claim the state before the first await so two starts cannot both proceed.
|
|
1548
1568
|
instance.setLock(true);
|
|
1549
1569
|
instance.status(instance_1.default.STATUS_STARTING);
|
|
1570
|
+
const starting = this.start(instance);
|
|
1571
|
+
instance.starting = starting;
|
|
1572
|
+
try {
|
|
1573
|
+
return await starting;
|
|
1574
|
+
}
|
|
1575
|
+
finally {
|
|
1576
|
+
instance.starting = undefined;
|
|
1577
|
+
instance.setLock(false);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
async start(instance) {
|
|
1550
1581
|
try {
|
|
1551
1582
|
if (!fs_extra_1.default.existsSync(instance.absoluteCwdPath())) {
|
|
1552
1583
|
await fs_extra_1.default.mkdirs(instance.absoluteCwdPath());
|
|
@@ -1595,9 +1626,6 @@ class AbsStartCommand extends command_1.default {
|
|
|
1595
1626
|
instance.startTimestamp = 0;
|
|
1596
1627
|
instance.failure(error);
|
|
1597
1628
|
}
|
|
1598
|
-
finally {
|
|
1599
|
-
instance.setLock(false);
|
|
1600
|
-
}
|
|
1601
1629
|
}
|
|
1602
1630
|
}
|
|
1603
1631
|
exports["default"] = AbsStartCommand;
|
|
@@ -2138,6 +2166,7 @@ class Instance extends events_1.EventEmitter {
|
|
|
2138
2166
|
};
|
|
2139
2167
|
watchers = new Map();
|
|
2140
2168
|
process;
|
|
2169
|
+
starting;
|
|
2141
2170
|
outputLoopTask;
|
|
2142
2171
|
outputBuffer;
|
|
2143
2172
|
stopping;
|
|
@@ -2336,9 +2365,22 @@ class Instance extends events_1.EventEmitter {
|
|
|
2336
2365
|
}
|
|
2337
2366
|
// function that must be executed after the instance starts
|
|
2338
2367
|
// Trigger the open event and bind the data and exit events, etc.
|
|
2339
|
-
started(process) {
|
|
2340
|
-
this.startTimestamp = this.config.lastDatetime = Date.now();
|
|
2341
|
-
|
|
2368
|
+
started(process, previous) {
|
|
2369
|
+
this.startTimestamp = this.config.lastDatetime = previous?.startTimestamp || Date.now();
|
|
2370
|
+
if (previous) {
|
|
2371
|
+
this.startCount = previous.startCount;
|
|
2372
|
+
this.autoRestartCount = previous.autoRestartCount;
|
|
2373
|
+
}
|
|
2374
|
+
this.userRequestedStop = previous?.userRequestedStop ?? false;
|
|
2375
|
+
if (this.userRequestedStop)
|
|
2376
|
+
this.ignoreEventTaskOnce();
|
|
2377
|
+
process.snapshot?.({
|
|
2378
|
+
pid: Number(process.pid),
|
|
2379
|
+
startTimestamp: this.startTimestamp,
|
|
2380
|
+
startCount: this.startCount,
|
|
2381
|
+
autoRestartCount: this.autoRestartCount,
|
|
2382
|
+
userRequestedStop: this.userRequestedStop
|
|
2383
|
+
});
|
|
2342
2384
|
const outputCode = this.config.terminalOption.pty ? "utf-8" : this.config.oe;
|
|
2343
2385
|
process.on("data", (text) => {
|
|
2344
2386
|
this.pushOutput(iconv_lite_1.default.decode(text, outputCode));
|
|
@@ -2442,6 +2484,7 @@ class Instance extends events_1.EventEmitter {
|
|
|
2442
2484
|
this.stopOutputLoop();
|
|
2443
2485
|
this.reloading = true;
|
|
2444
2486
|
this.watchers.clear();
|
|
2487
|
+
await this.starting?.catch(() => { });
|
|
2445
2488
|
await this.lifeCycleTaskManager.clearLifeCycleTask();
|
|
2446
2489
|
}
|
|
2447
2490
|
async resumeAfterReload(dispatcher) {
|
|
@@ -2479,6 +2522,7 @@ class Instance extends events_1.EventEmitter {
|
|
|
2479
2522
|
}
|
|
2480
2523
|
setUserRequestedStop(value) {
|
|
2481
2524
|
this.userRequestedStop = value;
|
|
2525
|
+
this.process?.snapshot?.({ userRequestedStop: value });
|
|
2482
2526
|
}
|
|
2483
2527
|
getUserRequestedStop() {
|
|
2484
2528
|
return this.userRequestedStop;
|
|
@@ -2995,6 +3039,17 @@ function apply(ctx) {
|
|
|
2995
3039
|
let preserving = false;
|
|
2996
3040
|
let subsystem;
|
|
2997
3041
|
let disposeSchedules;
|
|
3042
|
+
let initializing;
|
|
3043
|
+
ctx.on("process/starting", async () => {
|
|
3044
|
+
if (!initializing)
|
|
3045
|
+
throw new Error("Instance services failed to initialize.");
|
|
3046
|
+
await initializing;
|
|
3047
|
+
await subsystem?.waitForTakeover();
|
|
3048
|
+
});
|
|
3049
|
+
ctx.on("process/restarting", async () => {
|
|
3050
|
+
disposeSchedules?.();
|
|
3051
|
+
await subsystem?.prepareForRestart();
|
|
3052
|
+
});
|
|
2998
3053
|
ctx.on("plugins/reloading", async () => {
|
|
2999
3054
|
const inventory = ctx.get("plugins")?.inventory();
|
|
3000
3055
|
preserving = inventory?.some((plugin) => plugin.id === "instance" && plugin.enabled) ?? true;
|
|
@@ -3009,7 +3064,11 @@ function apply(ctx) {
|
|
|
3009
3064
|
// are available on the next turn rather than synchronously in this function.
|
|
3010
3065
|
// Restoring instances before that point makes the legacy dispatcher read
|
|
3011
3066
|
// missing `presets` and `instanceLifecycle` services and emit warnings.
|
|
3012
|
-
ctx.inject(["tasks", "instanceLifecycle", "presets", "schedules"],
|
|
3067
|
+
ctx.inject(["tasks", "instanceLifecycle", "presets", "schedules"], (instanceCtx) => {
|
|
3068
|
+
initializing = initialize(instanceCtx);
|
|
3069
|
+
return initializing;
|
|
3070
|
+
});
|
|
3071
|
+
async function initialize(instanceCtx) {
|
|
3013
3072
|
// The modules are required only after the context has been set and the
|
|
3014
3073
|
// instance registries are ready. Keeping these synchronous requires keeps
|
|
3015
3074
|
// webpack's output self-contained and avoids a second copy of the context.
|
|
@@ -3063,7 +3122,12 @@ function apply(ctx) {
|
|
|
3063
3122
|
await disposeInstanceEvents?.();
|
|
3064
3123
|
InstanceControlSubsystem.dispose();
|
|
3065
3124
|
router_1.routerApp.dispose();
|
|
3066
|
-
if (
|
|
3125
|
+
if (runtime.restarting) {
|
|
3126
|
+
// The launcher owns general/PTY processes; Docker is reattached at
|
|
3127
|
+
// startup. Disposing adapters here would terminate those live owners.
|
|
3128
|
+
await InstanceSubsystem.prepareForRestart();
|
|
3129
|
+
}
|
|
3130
|
+
else if ((preserving || recovering) && !runtime.stopping && ctx.root.scope.isActive) {
|
|
3067
3131
|
await InstanceSubsystem.suspendForReload();
|
|
3068
3132
|
retain();
|
|
3069
3133
|
}
|
|
@@ -3161,7 +3225,7 @@ function apply(ctx) {
|
|
|
3161
3225
|
// Also allow recovery by enabling/retrying only the instance plugin.
|
|
3162
3226
|
instanceCtx.on("ready", resume);
|
|
3163
3227
|
}
|
|
3164
|
-
}
|
|
3228
|
+
}
|
|
3165
3229
|
}
|
|
3166
3230
|
|
|
3167
3231
|
|
|
@@ -5551,14 +5615,19 @@ function setPluginContext(value) {
|
|
|
5551
5615
|
context: value,
|
|
5552
5616
|
settings: value.settings,
|
|
5553
5617
|
storage: value.storage,
|
|
5554
|
-
stopping: false
|
|
5618
|
+
stopping: false,
|
|
5619
|
+
restarting: false
|
|
5555
5620
|
};
|
|
5556
5621
|
host[INSTANCE_RUNTIME] = runtime = state;
|
|
5622
|
+
host.on("process/restarting", () => {
|
|
5623
|
+
state.restarting = true;
|
|
5624
|
+
});
|
|
5557
5625
|
host.on("dispose", async () => {
|
|
5558
5626
|
state.stopping = true;
|
|
5559
5627
|
// A replacement may fail before it can claim the retained processes.
|
|
5560
5628
|
// The daemon still owns them and must stop them during real shutdown.
|
|
5561
|
-
|
|
5629
|
+
if (!state.restarting)
|
|
5630
|
+
await state.handover?.shutdown();
|
|
5562
5631
|
state.handover = undefined;
|
|
5563
5632
|
});
|
|
5564
5633
|
}
|
|
@@ -7356,6 +7425,7 @@ const sleep_1 = __webpack_require__("../../plugins/instance/daemon/src/backend/u
|
|
|
7356
7425
|
const log_1 = __importDefault(__webpack_require__("../../plugins/instance/daemon/src/backend/service/log.ts"));
|
|
7357
7426
|
const system_instance_control_1 = __importDefault(__webpack_require__("../../plugins/instance/daemon/src/backend/service/system_instance_control.ts"));
|
|
7358
7427
|
const takeover_container_1 = __importDefault(__webpack_require__("../../plugins/instance/daemon/src/backend/service/takeover_container.ts"));
|
|
7428
|
+
const takeover_processes_1 = __importDefault(__webpack_require__("../../plugins/instance/daemon/src/backend/service/takeover_processes.ts"));
|
|
7359
7429
|
class InstanceSubsystem extends events_1.default {
|
|
7360
7430
|
GLOBAL_INSTANCE = "__MCSM_GLOBAL_INSTANCE__";
|
|
7361
7431
|
GLOBAL_INSTANCE_UUID = "global0001";
|
|
@@ -7464,14 +7534,26 @@ class InstanceSubsystem extends events_1.default {
|
|
|
7464
7534
|
processType: globalConfig.processType
|
|
7465
7535
|
}, true, // allow persistence
|
|
7466
7536
|
this.GLOBAL_INSTANCE_UUID);
|
|
7467
|
-
this.takeover = (
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7537
|
+
this.takeover = (async () => {
|
|
7538
|
+
await (0, takeover_processes_1.default)(() => !this.startupCancelled);
|
|
7539
|
+
try {
|
|
7540
|
+
await (0, takeover_container_1.default)(() => !this.startupCancelled);
|
|
7471
7541
|
}
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7542
|
+
catch (error) {
|
|
7543
|
+
const reason = error.message || error;
|
|
7544
|
+
if (typeof reason == "string" && reason.includes("connect ENOENT"))
|
|
7545
|
+
return;
|
|
7546
|
+
log_1.default.error(`${(0, i18n_1.$t)("TXT_CODE_8d4c8f7e")}: ${reason}`);
|
|
7547
|
+
}
|
|
7548
|
+
})();
|
|
7549
|
+
void this.takeover
|
|
7550
|
+
.then(() => {
|
|
7551
|
+
// A worker replacement must also preserve intentionally stopped
|
|
7552
|
+
// instances, even when their next full launcher startup is automatic.
|
|
7553
|
+
if (process.env.EPANEL_RESTARTED !== "1")
|
|
7554
|
+
return this.autoStart();
|
|
7555
|
+
})
|
|
7556
|
+
.catch((error) => log_1.default.error(error));
|
|
7475
7557
|
}
|
|
7476
7558
|
createInstance(cfg, persistence = true, uuid) {
|
|
7477
7559
|
const newUuid = uuid || (0, uuid_1.v4)().replace(/-/gim, "");
|
|
@@ -7546,6 +7628,22 @@ class InstanceSubsystem extends events_1.default {
|
|
|
7546
7628
|
await Promise.all([...this.instances.values()].map((instance) => instance.suspendForReload()));
|
|
7547
7629
|
await this.takeover;
|
|
7548
7630
|
}
|
|
7631
|
+
async waitForTakeover() {
|
|
7632
|
+
await this.takeover;
|
|
7633
|
+
}
|
|
7634
|
+
async prepareForRestart() {
|
|
7635
|
+
await this.suspendForReload();
|
|
7636
|
+
for (const instance of this.instances.values()) {
|
|
7637
|
+
system_storage_1.default.store("InstanceConfig", instance.instanceUuid, instance.config);
|
|
7638
|
+
instance.process?.snapshot?.({
|
|
7639
|
+
pid: Number(instance.process.pid),
|
|
7640
|
+
startTimestamp: instance.startTimestamp,
|
|
7641
|
+
startCount: instance.startCount,
|
|
7642
|
+
autoRestartCount: instance.autoRestartCount,
|
|
7643
|
+
userRequestedStop: instance.getUserRequestedStop()
|
|
7644
|
+
});
|
|
7645
|
+
}
|
|
7646
|
+
}
|
|
7549
7647
|
/** Transfer the existing owners, including ordinary child/PTY/Docker handles. */
|
|
7550
7648
|
adoptInstances(instances) {
|
|
7551
7649
|
this.startupCancelled = true;
|
|
@@ -8131,6 +8229,46 @@ async function takeoverContainer(isActive = () => true) {
|
|
|
8131
8229
|
}
|
|
8132
8230
|
|
|
8133
8231
|
|
|
8232
|
+
/***/ },
|
|
8233
|
+
|
|
8234
|
+
/***/ "../../plugins/instance/daemon/src/backend/service/takeover_processes.ts"
|
|
8235
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
8236
|
+
|
|
8237
|
+
"use strict";
|
|
8238
|
+
|
|
8239
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8240
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8241
|
+
};
|
|
8242
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
8243
|
+
exports["default"] = takeoverProcesses;
|
|
8244
|
+
const process_adapter_1 = __webpack_require__("../../plugins/instance/daemon/src/backend/entity/commands/base/process_adapter.ts");
|
|
8245
|
+
const pty_start_1 = __webpack_require__("../../plugins/instance/daemon/src/backend/entity/commands/pty/pty_start.ts");
|
|
8246
|
+
const system_instance_1 = __importDefault(__webpack_require__("../../plugins/instance/daemon/src/backend/service/system_instance.ts"));
|
|
8247
|
+
/** Reattach the launcher's live pipes; do not execute the instance start command. */
|
|
8248
|
+
async function takeoverProcesses(isActive = () => true) {
|
|
8249
|
+
const host = (0, process_adapter_1.instanceProcessHost)();
|
|
8250
|
+
if (!host)
|
|
8251
|
+
return;
|
|
8252
|
+
for (const snapshot of await host.list()) {
|
|
8253
|
+
if (!isActive())
|
|
8254
|
+
return;
|
|
8255
|
+
const instance = system_instance_1.default.getInstance(snapshot.id);
|
|
8256
|
+
const child = host.connect(snapshot);
|
|
8257
|
+
const { pipeName, pid } = snapshot.metadata;
|
|
8258
|
+
const adapter = pipeName
|
|
8259
|
+
? new pty_start_1.GoPtyProcessAdapter(child, pid, pipeName)
|
|
8260
|
+
: new process_adapter_1.ChildProcessAdapter(child);
|
|
8261
|
+
if (!instance || instance.process) {
|
|
8262
|
+
await adapter.destroy();
|
|
8263
|
+
continue;
|
|
8264
|
+
}
|
|
8265
|
+
instance.started(adapter, snapshot.metadata);
|
|
8266
|
+
if (pipeName)
|
|
8267
|
+
adapter.attachOutput();
|
|
8268
|
+
}
|
|
8269
|
+
}
|
|
8270
|
+
|
|
8271
|
+
|
|
8134
8272
|
/***/ },
|
|
8135
8273
|
|
|
8136
8274
|
/***/ "../../plugins/instance/daemon/src/backend/service/version_adapter.ts"
|
|
@@ -8634,6 +8772,7 @@ Object.defineProperty(exports, "arrayUnique", ({ enumerable: true, get: function
|
|
|
8634
8772
|
__exportStar(__webpack_require__("../common/src/plugin_contract.ts"), exports);
|
|
8635
8773
|
__exportStar(__webpack_require__("../common/src/plugin_overrides.ts"), exports);
|
|
8636
8774
|
__exportStar(__webpack_require__("../common/src/plugin_lifecycle.ts"), exports);
|
|
8775
|
+
__exportStar(__webpack_require__("../common/src/process_restart.ts"), exports);
|
|
8637
8776
|
__exportStar(__webpack_require__("../common/src/plugin_revision.ts"), exports);
|
|
8638
8777
|
__exportStar(__webpack_require__("../common/src/plugin_modules.ts"), exports);
|
|
8639
8778
|
__exportStar(__webpack_require__("../common/src/plugin_watch.ts"), exports);
|
|
@@ -10267,6 +10406,50 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
10267
10406
|
}
|
|
10268
10407
|
|
|
10269
10408
|
|
|
10409
|
+
/***/ },
|
|
10410
|
+
|
|
10411
|
+
/***/ "../common/src/process_restart.ts"
|
|
10412
|
+
(__unused_webpack_module, exports) {
|
|
10413
|
+
|
|
10414
|
+
"use strict";
|
|
10415
|
+
|
|
10416
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10417
|
+
exports.isProcessRestartPending = isProcessRestartPending;
|
|
10418
|
+
exports.requestProcessRestart = requestProcessRestart;
|
|
10419
|
+
const RESTART = Symbol.for("elementspanel.process.restart");
|
|
10420
|
+
function isProcessRestartPending(ctx) {
|
|
10421
|
+
return ctx.root[RESTART]?.pending === true;
|
|
10422
|
+
}
|
|
10423
|
+
/** The CLI retains instance processes and starts a fresh worker after this one exits. */
|
|
10424
|
+
function requestProcessRestart(ctx, settle, ready = async () => { }) {
|
|
10425
|
+
if (isProcessRestartPending(ctx))
|
|
10426
|
+
return true;
|
|
10427
|
+
if (process.env.EPANEL_SUPERVISED !== "1" || !process.connected || !process.send)
|
|
10428
|
+
return false;
|
|
10429
|
+
const state = { pending: true };
|
|
10430
|
+
ctx.root[RESTART] = state;
|
|
10431
|
+
const retainProcesses = () => new Promise((resolve, reject) => process.send({ type: "elementspanel:prepare-restart" }, (error) => error ? reject(error) : resolve()));
|
|
10432
|
+
setImmediate(() => {
|
|
10433
|
+
void (async () => {
|
|
10434
|
+
await ready();
|
|
10435
|
+
// Detach output consumers before cleanup so output and exits during the
|
|
10436
|
+
// restart are retained for the next daemon generation.
|
|
10437
|
+
await retainProcesses();
|
|
10438
|
+
await ctx.parallel("process/restarting");
|
|
10439
|
+
// A pending start can finish while restart hooks are awaiting it.
|
|
10440
|
+
await retainProcesses();
|
|
10441
|
+
await ctx.stop();
|
|
10442
|
+
await settle();
|
|
10443
|
+
process.send({ type: "elementspanel:restart" }, (error) => process.exit(error ? 1 : 0));
|
|
10444
|
+
})().catch((error) => {
|
|
10445
|
+
ctx.logger.error("Failed to restart the process:", error);
|
|
10446
|
+
process.exit(1);
|
|
10447
|
+
});
|
|
10448
|
+
});
|
|
10449
|
+
return true;
|
|
10450
|
+
}
|
|
10451
|
+
|
|
10452
|
+
|
|
10270
10453
|
/***/ },
|
|
10271
10454
|
|
|
10272
10455
|
/***/ "../common/src/process_tools.ts"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementspanel/epanel-plugin-instance",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Application instance and Java runtime management.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Csituka_D <694428809@qq.com> (https://github.com/JessDaodao)",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@elementspanel/panel": "^1.0.
|
|
54
|
-
"@elementspanel/daemon": "^1.0.
|
|
53
|
+
"@elementspanel/panel": "^1.0.3",
|
|
54
|
+
"@elementspanel/daemon": "^1.0.3"
|
|
55
55
|
},
|
|
56
56
|
"peerDependenciesMeta": {
|
|
57
57
|
"@elementspanel/panel": {
|
package/panel/backend/index.cjs
CHANGED
|
@@ -9468,6 +9468,7 @@ Object.defineProperty(exports, "arrayUnique", ({ enumerable: true, get: function
|
|
|
9468
9468
|
__exportStar(__webpack_require__("../common/src/plugin_contract.ts"), exports);
|
|
9469
9469
|
__exportStar(__webpack_require__("../common/src/plugin_overrides.ts"), exports);
|
|
9470
9470
|
__exportStar(__webpack_require__("../common/src/plugin_lifecycle.ts"), exports);
|
|
9471
|
+
__exportStar(__webpack_require__("../common/src/process_restart.ts"), exports);
|
|
9471
9472
|
__exportStar(__webpack_require__("../common/src/plugin_revision.ts"), exports);
|
|
9472
9473
|
__exportStar(__webpack_require__("../common/src/plugin_modules.ts"), exports);
|
|
9473
9474
|
__exportStar(__webpack_require__("../common/src/plugin_watch.ts"), exports);
|
|
@@ -11134,6 +11135,51 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
11134
11135
|
}
|
|
11135
11136
|
|
|
11136
11137
|
|
|
11138
|
+
/***/ },
|
|
11139
|
+
|
|
11140
|
+
/***/ "../common/src/process_restart.ts"
|
|
11141
|
+
(__unused_webpack_module, exports) {
|
|
11142
|
+
|
|
11143
|
+
"use strict";
|
|
11144
|
+
|
|
11145
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
11146
|
+
exports.isProcessRestartPending = isProcessRestartPending;
|
|
11147
|
+
exports.requestProcessRestart = requestProcessRestart;
|
|
11148
|
+
const RESTART = Symbol.for("elementspanel.process.restart");
|
|
11149
|
+
function isProcessRestartPending(ctx) {
|
|
11150
|
+
var _a;
|
|
11151
|
+
return ((_a = ctx.root[RESTART]) === null || _a === void 0 ? void 0 : _a.pending) === true;
|
|
11152
|
+
}
|
|
11153
|
+
/** The CLI retains instance processes and starts a fresh worker after this one exits. */
|
|
11154
|
+
function requestProcessRestart(ctx, settle, ready = async () => { }) {
|
|
11155
|
+
if (isProcessRestartPending(ctx))
|
|
11156
|
+
return true;
|
|
11157
|
+
if (process.env.EPANEL_SUPERVISED !== "1" || !process.connected || !process.send)
|
|
11158
|
+
return false;
|
|
11159
|
+
const state = { pending: true };
|
|
11160
|
+
ctx.root[RESTART] = state;
|
|
11161
|
+
const retainProcesses = () => new Promise((resolve, reject) => process.send({ type: "elementspanel:prepare-restart" }, (error) => error ? reject(error) : resolve()));
|
|
11162
|
+
setImmediate(() => {
|
|
11163
|
+
void (async () => {
|
|
11164
|
+
await ready();
|
|
11165
|
+
// Detach output consumers before cleanup so output and exits during the
|
|
11166
|
+
// restart are retained for the next daemon generation.
|
|
11167
|
+
await retainProcesses();
|
|
11168
|
+
await ctx.parallel("process/restarting");
|
|
11169
|
+
// A pending start can finish while restart hooks are awaiting it.
|
|
11170
|
+
await retainProcesses();
|
|
11171
|
+
await ctx.stop();
|
|
11172
|
+
await settle();
|
|
11173
|
+
process.send({ type: "elementspanel:restart" }, (error) => process.exit(error ? 1 : 0));
|
|
11174
|
+
})().catch((error) => {
|
|
11175
|
+
ctx.logger.error("Failed to restart the process:", error);
|
|
11176
|
+
process.exit(1);
|
|
11177
|
+
});
|
|
11178
|
+
});
|
|
11179
|
+
return true;
|
|
11180
|
+
}
|
|
11181
|
+
|
|
11182
|
+
|
|
11137
11183
|
/***/ },
|
|
11138
11184
|
|
|
11139
11185
|
/***/ "../common/src/process_tools.ts"
|