@camstack/system 1.2.310 → 1.2.312
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/dist/addon-runner.js +6 -8
- package/dist/addon-runner.mjs +6 -8
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +1 -1
- package/dist/builtins/composer/composer.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +10 -102
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +4 -92
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{child-cap-dispatch-BCJjUtXV.mjs → child-cap-dispatch-CHTiHbsv.mjs} +294 -10
- package/dist/{child-cap-dispatch-Be8e2cBP.js → child-cap-dispatch-Dyn_7ezH.js} +347 -9
- package/dist/{dist-B78pkrps.mjs → dist-Cj7pJmXq.mjs} +35 -4
- package/dist/{dist-Cy6DFFjs.js → dist-CkRwnhbo.js} +35 -4
- package/dist/index.js +88 -18
- package/dist/index.mjs +89 -20
- package/dist/kernel/index.d.ts +1 -0
- package/dist/kernel/moleculer/process-service.d.ts +9 -0
- package/dist/kernel/moleculer/runner-process-group.d.ts +92 -0
- package/dist/proc-stat-CbC55Kqi.mjs +92 -0
- package/dist/proc-stat-DL-WUOhl.js +127 -0
- package/dist/{resource-monitor-Vp0bPV3U.mjs → resource-monitor-B1v6E07R.mjs} +1 -1
- package/dist/{resource-monitor-LVE1BoLs.js → resource-monitor-DzNn_IZK.js} +5 -5
- package/dist/{retired-settings-keys-B4_hiWsm.mjs → retired-settings-keys-C1duPikd.mjs} +1 -1
- package/dist/{retired-settings-keys-D9sgD6Yg.js → retired-settings-keys-CGSuXhP8.js} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("./dist-
|
|
3
|
+
const require_dist = require("./dist-CkRwnhbo.js");
|
|
4
4
|
const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
|
|
5
5
|
require("./builtins/alerts/index.js");
|
|
6
6
|
const require_builtins_composer_composer_addon = require("./builtins/composer/composer.addon.js");
|
|
@@ -29,8 +29,8 @@ require("./builtins/system-config/index.js");
|
|
|
29
29
|
const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
|
|
30
30
|
const require_event_loop_stall_monitor = require("./event-loop-stall-monitor-ey4mbofz.js");
|
|
31
31
|
const require_tls$1 = require("./tls-D_wUeOTD.js");
|
|
32
|
-
const require_child_cap_dispatch = require("./child-cap-dispatch-
|
|
33
|
-
const require_resource_monitor = require("./resource-monitor-
|
|
32
|
+
const require_child_cap_dispatch = require("./child-cap-dispatch-Dyn_7ezH.js");
|
|
33
|
+
const require_resource_monitor = require("./resource-monitor-DzNn_IZK.js");
|
|
34
34
|
const require_custom_action_registry = require("./custom-action-registry-acBY3mHA.js");
|
|
35
35
|
let zod = require("zod");
|
|
36
36
|
let node_crypto = require("node:crypto");
|
|
@@ -95015,7 +95015,10 @@ var CRASH_WINDOW_MS = 6e4;
|
|
|
95015
95015
|
var MAX_CRASHES_IN_WINDOW = 5;
|
|
95016
95016
|
function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parentUdsPath) {
|
|
95017
95017
|
const spawnFn = deps?.spawnFn ?? node_child_process.spawn;
|
|
95018
|
+
const groupOps = deps?.processGroups ?? require_child_cap_dispatch.defaultProcessGroupOps;
|
|
95019
|
+
const runnersOwnGroups = require_child_cap_dispatch.runnerOwnsProcessGroup(deps?.platform ?? process.platform);
|
|
95018
95020
|
const processes = /* @__PURE__ */ new Map();
|
|
95021
|
+
const pendingGroupReaps = /* @__PURE__ */ new Map();
|
|
95019
95022
|
const runnerLocks = /* @__PURE__ */ new Map();
|
|
95020
95023
|
function withRunnerLock(runnerId, fn) {
|
|
95021
95024
|
const result = (runnerLocks.get(runnerId) ?? Promise.resolve()).then(fn, fn);
|
|
@@ -95055,6 +95058,49 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95055
95058
|
}, data));
|
|
95056
95059
|
}
|
|
95057
95060
|
/**
|
|
95061
|
+
* One line per reap that found something, or that failed. An empty group is the
|
|
95062
|
+
* normal case after a clean stop and stays quiet at debug. The kernel cannot say
|
|
95063
|
+
* which device a child served — the runner id is the finest attribution it has.
|
|
95064
|
+
*/
|
|
95065
|
+
function logGroupReap(runnerId, result) {
|
|
95066
|
+
const found = result.membersAtExit;
|
|
95067
|
+
const killed = result.killed ?? [];
|
|
95068
|
+
const line = `[${runnerId}] runner group reaped {pgid=${result.pgid}, members=${found === null ? "unreadable" : found.length}${found !== null && found.length > 0 ? ` (${require_child_cap_dispatch.summarizeMembers(found)})` : ""}, sigkilled=${killed.length}${killed.length > 0 ? ` (${require_child_cap_dispatch.summarizeMembers(killed)})` : ""}${result.error !== null ? `, error=${result.error}` : ""}}`;
|
|
95069
|
+
const logger = capturedBroker?.logger;
|
|
95070
|
+
if (result.error !== null || killed.length > 0) if (logger) logger.warn(line);
|
|
95071
|
+
else console.error(line);
|
|
95072
|
+
else if ((found?.length ?? 0) > 0 || found === null) logger?.info(line);
|
|
95073
|
+
else logger?.debug(line);
|
|
95074
|
+
}
|
|
95075
|
+
/**
|
|
95076
|
+
* Reap a runner's process group (D668): SIGTERM, a bounded grace, SIGKILL for what
|
|
95077
|
+
* remains. Memoized on the entry so the `exit` handler and a stop/restart that timed
|
|
95078
|
+
* out waiting for that exit share one reap, and registered in `pendingGroupReaps` so
|
|
95079
|
+
* the next spawn under the same id waits for it. Never rejects.
|
|
95080
|
+
*/
|
|
95081
|
+
function reapRunnerGroup(entry) {
|
|
95082
|
+
if (entry.groupReap !== null) return entry.groupReap;
|
|
95083
|
+
if (!entry.ownsGroup) {
|
|
95084
|
+
entry.groupReap = Promise.resolve();
|
|
95085
|
+
return entry.groupReap;
|
|
95086
|
+
}
|
|
95087
|
+
const reap = require_child_cap_dispatch.reapProcessGroup(entry.pid, groupOps).then((result) => logGroupReap(entry.name, result)).catch((err) => {
|
|
95088
|
+
capturedBroker?.logger.error(`[${entry.name}] runner group reap threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
95089
|
+
}).finally(() => {
|
|
95090
|
+
require_child_cap_dispatch.releaseRunnerGroup(entry.pid);
|
|
95091
|
+
if (pendingGroupReaps.get(entry.name) === tracked) pendingGroupReaps.delete(entry.name);
|
|
95092
|
+
});
|
|
95093
|
+
const previous = pendingGroupReaps.get(entry.name);
|
|
95094
|
+
const tracked = previous ? Promise.all([previous, reap]).then(() => void 0) : reap;
|
|
95095
|
+
pendingGroupReaps.set(entry.name, tracked);
|
|
95096
|
+
entry.groupReap = reap;
|
|
95097
|
+
return reap;
|
|
95098
|
+
}
|
|
95099
|
+
/** Resolves once every reap started for `runnerId` has finished. */
|
|
95100
|
+
async function awaitPredecessorReap(runnerId) {
|
|
95101
|
+
await pendingGroupReaps.get(runnerId);
|
|
95102
|
+
}
|
|
95103
|
+
/**
|
|
95058
95104
|
* Spawn ONE runner subprocess (`addon-runner.js`) that hosts the
|
|
95059
95105
|
* `addons` set sharing a single Moleculer broker. The normal case is
|
|
95060
95106
|
* a size-1 `addons` array — one addon, one process; the media group
|
|
@@ -95103,8 +95149,9 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95103
95149
|
"pipe",
|
|
95104
95150
|
"pipe"
|
|
95105
95151
|
],
|
|
95106
|
-
detached:
|
|
95152
|
+
detached: runnersOwnGroups
|
|
95107
95153
|
});
|
|
95154
|
+
const ownsGroup = runnersOwnGroups && typeof child.pid === "number" && child.pid > 1;
|
|
95108
95155
|
const entry = {
|
|
95109
95156
|
pid: child.pid,
|
|
95110
95157
|
nodeId,
|
|
@@ -95115,16 +95162,23 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95115
95162
|
startedAt: Date.now(),
|
|
95116
95163
|
restartCount: 0,
|
|
95117
95164
|
state: "starting",
|
|
95118
|
-
child
|
|
95165
|
+
child,
|
|
95166
|
+
ownsGroup,
|
|
95167
|
+
groupReap: null
|
|
95119
95168
|
};
|
|
95169
|
+
if (ownsGroup) require_child_cap_dispatch.registerRunnerGroup(entry.pid, {
|
|
95170
|
+
runnerId,
|
|
95171
|
+
kill: groupOps.kill
|
|
95172
|
+
});
|
|
95120
95173
|
child.stdout?.on("data", (data) => {
|
|
95121
|
-
if (data.toString().includes(`READY:${nodeId}`)) entry.state = "running";
|
|
95174
|
+
if (data.toString().includes(`READY:${nodeId}`) && entry.state === "starting") entry.state = "running";
|
|
95122
95175
|
});
|
|
95123
95176
|
child.stderr?.on("data", (data) => {
|
|
95124
95177
|
process.stderr.write(`[${runnerId}] ${data.toString()}`);
|
|
95125
95178
|
});
|
|
95126
95179
|
child.on("exit", (code, signal) => {
|
|
95127
95180
|
console.error(`[process-service EXIT] runner=${runnerId} code=${String(code)} signal=${String(signal)} state=${entry.state}`);
|
|
95181
|
+
const groupReap = reapRunnerGroup(entry);
|
|
95128
95182
|
if (entry.state === "stopped") return;
|
|
95129
95183
|
entry.state = "crashed";
|
|
95130
95184
|
capturedBroker?.logger.error(`[${runnerId}] Process exited (code=${code}, signal=${signal})`);
|
|
@@ -95163,6 +95217,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95163
95217
|
if (capturedBroker) forceMoleculerDisconnect(capturedBroker, entry.nodeId);
|
|
95164
95218
|
setTimeout(() => {
|
|
95165
95219
|
withRunnerLock(runnerId, async () => {
|
|
95220
|
+
await groupReap;
|
|
95166
95221
|
if (processes.has(runnerId)) return;
|
|
95167
95222
|
const restarted = spawnRunner(runnerId, addons, env);
|
|
95168
95223
|
restarted.restartCount = entry.restartCount + 1;
|
|
@@ -95175,10 +95230,12 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95175
95230
|
return {
|
|
95176
95231
|
name: "$process",
|
|
95177
95232
|
actions: {
|
|
95178
|
-
spawnRunner: { handler(ctx) {
|
|
95233
|
+
spawnRunner: { async handler(ctx) {
|
|
95179
95234
|
const { runnerId, addons, env } = ctx.params;
|
|
95180
95235
|
if (processes.has(runnerId)) throw new Error(`Runner "${runnerId}" already running`);
|
|
95181
95236
|
if (!Array.isArray(addons) || addons.length === 0) throw new Error(`spawnRunner requires non-empty addons array`);
|
|
95237
|
+
await awaitPredecessorReap(runnerId);
|
|
95238
|
+
if (processes.has(runnerId)) throw new Error(`Runner "${runnerId}" already running`);
|
|
95182
95239
|
invalidateHeapProfiles(addons);
|
|
95183
95240
|
const entry = spawnRunner(runnerId, addons, env);
|
|
95184
95241
|
return {
|
|
@@ -95215,6 +95272,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95215
95272
|
});
|
|
95216
95273
|
});
|
|
95217
95274
|
}
|
|
95275
|
+
await reapRunnerGroup(target);
|
|
95218
95276
|
processes.delete(name);
|
|
95219
95277
|
crashSupervisor.reset(name);
|
|
95220
95278
|
forceMoleculerDisconnect(ctx.broker, deadNodeId);
|
|
@@ -95251,6 +95309,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95251
95309
|
});
|
|
95252
95310
|
});
|
|
95253
95311
|
}
|
|
95312
|
+
await reapRunnerGroup(target);
|
|
95254
95313
|
processes.delete(name);
|
|
95255
95314
|
crashSupervisor.reset(name);
|
|
95256
95315
|
forceMoleculerDisconnect(ctx.broker, deadNodeId);
|
|
@@ -95310,6 +95369,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95310
95369
|
});
|
|
95311
95370
|
});
|
|
95312
95371
|
}
|
|
95372
|
+
await reapRunnerGroup(entry);
|
|
95313
95373
|
processes.delete(name);
|
|
95314
95374
|
crashSupervisor.reset(name);
|
|
95315
95375
|
invalidateHeapProfiles(runnerAddons);
|
|
@@ -95360,19 +95420,28 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95360
95420
|
started() {
|
|
95361
95421
|
capturedBroker = this.broker;
|
|
95362
95422
|
},
|
|
95363
|
-
stopped() {
|
|
95364
|
-
const
|
|
95365
|
-
|
|
95423
|
+
async stopped() {
|
|
95424
|
+
const entries = [...processes.values()];
|
|
95425
|
+
await Promise.all(entries.map(async (entry) => {
|
|
95366
95426
|
entry.state = "stopped";
|
|
95367
|
-
entry.child.
|
|
95368
|
-
|
|
95369
|
-
|
|
95370
|
-
|
|
95371
|
-
|
|
95372
|
-
|
|
95373
|
-
|
|
95427
|
+
if (!(entry.child.exitCode !== null || entry.child.signalCode !== null)) {
|
|
95428
|
+
entry.child.kill("SIGTERM");
|
|
95429
|
+
await new Promise((resolve) => {
|
|
95430
|
+
const timer = setTimeout(() => {
|
|
95431
|
+
if (entry.child.exitCode === null && entry.child.signalCode === null) {
|
|
95432
|
+
capturedBroker?.logger.warn(`[${entry.name}] Did not exit on SIGTERM — sending SIGKILL`);
|
|
95433
|
+
entry.child.kill("SIGKILL");
|
|
95434
|
+
}
|
|
95435
|
+
resolve();
|
|
95436
|
+
}, 3e3);
|
|
95437
|
+
entry.child.once("exit", () => {
|
|
95438
|
+
clearTimeout(timer);
|
|
95439
|
+
resolve();
|
|
95440
|
+
});
|
|
95441
|
+
});
|
|
95374
95442
|
}
|
|
95375
|
-
|
|
95443
|
+
await reapRunnerGroup(entry);
|
|
95444
|
+
}));
|
|
95376
95445
|
processes.clear();
|
|
95377
95446
|
capturedBroker = null;
|
|
95378
95447
|
}
|
|
@@ -96259,6 +96328,7 @@ exports.setHubConnected = require_child_cap_dispatch.setHubConnected;
|
|
|
96259
96328
|
exports.setNodeEventInterest = require_child_cap_dispatch.setNodeEventInterest;
|
|
96260
96329
|
exports.setWrapperActive = require_builtins_device_manager_device_manager_addon.setWrapperActive;
|
|
96261
96330
|
exports.shouldReclaim = require_child_cap_dispatch.shouldReclaim;
|
|
96331
|
+
exports.signalAllRunnerGroups = require_child_cap_dispatch.signalAllRunnerGroups;
|
|
96262
96332
|
exports.socketDirectionBytes = require_child_cap_dispatch.socketDirectionBytes;
|
|
96263
96333
|
exports.socketDirectionMessages = require_child_cap_dispatch.socketDirectionMessages;
|
|
96264
96334
|
exports.startEventLoopStallMonitor = require_event_loop_stall_monitor.startEventLoopStallMonitor;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { $n as parseJsonUnknown, $t as objectInputDeclaresRequiredDeviceId, At as isArrayOutputSchema, Bt as lifecycleJobSchema, D as RUNTIME_DEFAULTS, Gn as emitDownForOwnedCaps, Gt as looseSchema, Hn as asNumber, It as isVoidInput, Lt as kebabToCamel, Mn as DATAPLANE_SECRET_HEADER$1, Nn as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Nt as isObjectInput, Pn as DEVICE_STATUS_METHOD, Qn as parseJsonObject, Qt as objectInputDeclaresAddonId, Rn as ReadinessRegistry, S as METHOD_ACCESS_MAP, Tt as extractNestedAddonId, Un as asString$1, Vn as asJsonObject$1, Wn as createEvent, Wt as logLevelAtMost, cn as resolveMethodAuth, dn as scopesAllowDeviceCap, er as readinessKey, ir as EventCategory$1, jt as isCollectionArrayMethod, kn as errMsg$1, nr as scopeKey, qn as expandCapMethods, rn as procedureAuthKey, t as ALL_CAPABILITY_DEFINITIONS, tr as resolveCapMount, un as scopesAllowAddon, y as LOG_LEVEL_RANK, z as addonSettingsCapability, zn as ReadinessTimeoutError } from "./dist-
|
|
2
|
+
import { $n as parseJsonUnknown, $t as objectInputDeclaresRequiredDeviceId, At as isArrayOutputSchema, Bt as lifecycleJobSchema, D as RUNTIME_DEFAULTS, Gn as emitDownForOwnedCaps, Gt as looseSchema, Hn as asNumber, It as isVoidInput, Lt as kebabToCamel, Mn as DATAPLANE_SECRET_HEADER$1, Nn as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Nt as isObjectInput, Pn as DEVICE_STATUS_METHOD, Qn as parseJsonObject, Qt as objectInputDeclaresAddonId, Rn as ReadinessRegistry, S as METHOD_ACCESS_MAP, Tt as extractNestedAddonId, Un as asString$1, Vn as asJsonObject$1, Wn as createEvent, Wt as logLevelAtMost, cn as resolveMethodAuth, dn as scopesAllowDeviceCap, er as readinessKey, ir as EventCategory$1, jt as isCollectionArrayMethod, kn as errMsg$1, nr as scopeKey, qn as expandCapMethods, rn as procedureAuthKey, t as ALL_CAPABILITY_DEFINITIONS, tr as resolveCapMount, un as scopesAllowAddon, y as LOG_LEVEL_RANK, z as addonSettingsCapability, zn as ReadinessTimeoutError } from "./dist-Cj7pJmXq.mjs";
|
|
3
3
|
import { AlertCenterAddon } from "./builtins/alerts/alerts.addon.mjs";
|
|
4
4
|
import "./builtins/alerts/index.mjs";
|
|
5
5
|
import { ComposerAddon } from "./builtins/composer/composer.addon.mjs";
|
|
@@ -16,7 +16,7 @@ import "./builtins/liveness-monitor/index.mjs";
|
|
|
16
16
|
import { LocalAuthAddon, a as require_safe_buffer, i as require_ms, n as ScopedTokenManager, o as ApiKeyManager, r as AuthManager, t as UserManager } from "./builtins/local-auth/local-auth.addon.mjs";
|
|
17
17
|
import "./builtins/local-auth/index.mjs";
|
|
18
18
|
import { LokiDestination, LokiLoggingAddon } from "./builtins/loki-logging/index.mjs";
|
|
19
|
-
import NativeMetricsAddon, {
|
|
19
|
+
import NativeMetricsAddon, { t as NativeMetricsProvider } from "./builtins/native-metrics/native-metrics.addon.mjs";
|
|
20
20
|
import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
|
|
21
21
|
import { SqliteSettingsAddon, o as SqliteSettingsBackend, s as prefixRange } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
|
|
22
22
|
import { ConfigStore, DeviceStore } from "./builtins/sqlite-storage/index.mjs";
|
|
@@ -28,8 +28,8 @@ import "./builtins/system-config/index.mjs";
|
|
|
28
28
|
import { WinstonDestination, WinstonLoggingAddon } from "./builtins/winston-logging/index.mjs";
|
|
29
29
|
import { _ as ensureModel, a as createFileDataPlaneHandler, c as parseRangeHeader, d as ModelDownloadService, g as downloadModel, h as downloadFile, i as startEventLoopStallMonitor, l as parseTokenizedUrl, m as deleteModelFromDisk, n as STALL_TICK_MS, o as contentTypeFor, p as collectModelFiles, r as attributeStall, s as createAuthenticatedFileServer, t as STALL_REPORT_MS, u as resolveFilePath, v as fetchJson, x as isModelDownloaded, y as getModelFilePath } from "./event-loop-stall-monitor-EXjzIxDz.mjs";
|
|
30
30
|
import { C as registerLanHttpHandler, S as readLanHttpState, _ as DEFAULT_LAN_HTTP_PORT, a as writeTlsMode, b as bindPendingLanHttp, c as loadTlsCert, d as collectCertIdentity, f as CA_VALIDITY_DAYS, g as evaluateExistingCert, h as SERVER_AUTH_OID, i as writeExtraSans, l as reissueTlsLeaf, m as MAX_LEAF_VALIDITY_DAYS, n as readTlsAccessStatus, o as validateUploadedTls, p as LEAF_RENEWAL_WINDOW_DAYS, r as readTlsMode, s as ensureTlsCert, t as readExtraSans, u as CA_COMMON_NAME, v as allFamiliesListenHost, x as closeLanHttp, y as applyLanHttp } from "./tls-IM-v7JV4.mjs";
|
|
31
|
-
import { $ as
|
|
32
|
-
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-
|
|
31
|
+
import { $ as CapUsageRegistry, $n as capActionLabel, $t as buildHeapSample, A as resolveHwAccel, An as createOutboundQueueGate, At as CapabilityUnavailableError, B as udsChildLogToWorkerEntry, Bn as diffSocketPlane, Bt as HEAP_RECLAIM_MIN_INTERVAL_MS, C as getBrokerEventBus, Cn as formatHeapSpaces, Ct as capBareAction, D as subscribePassthrough, Dn as OUTBOUND_QUEUE_COOLDOWN_MS, Dt as serializeTypedArrays, E as setNodeEventInterest, En as selectReportedSpaces, Et as deserializeTypedArrays, F as ipcParentLink, Fn as EMPTY_SOCKET_PLANE_BASELINE, Ft as resolveNpmInvocation, G as CapRouteResolver, Gn as recordSocketFrame, Gt as HUB_MAIN_HEAP_WATCH_LABEL, H as createUdsLoggerWithControl, Hn as readSocketQueues, Ht as HEAP_RECLAIM_TRIGGER_MB, I as localProviderLink, In as SOCKET_PLANE_TOP_N, It as runNpm, J as classifyCapRoute, Jn as socketDirectionMessages, Jt as RSS_BUDGET_REANNOUNCE_MIN_MS, K as callWithServiceDiscovery, Kn as sampleSocketDirection, Kt as HUB_MAIN_RSS_BUDGET_MB, L as createParentUnownedCallHandler, Ln as SOCKET_QUEUE_TOP_N, Lt as createAddonPeerBytesFacility, M as brokerTransportLink, Mn as MESH_QUEUE_TOP_N, Mt as installManifestNativeDeps, N as buildLinkChain, Nn as createMeshQueueReader, Nt as resolveAddonClass, O as AddonDepsManager, On as OUTBOUND_QUEUE_SUSTAIN_MS, Ot as DeviceRegistry, P as deviceCapResolverLink, Pn as formatMeshQueue, Pt as buildNpmChildEnv, Q as readMoleculerFanoutMode, Qn as MAX_CAP_ACTIONS_PER_PEER, Qt as ZERO_LOOP_DELAY, R as createUdsEventBridge, Rn as createSocketPlaneMeter, Rt as hostNodeIdOf, S as clusterEventTopic, Sn as emitHeapDiagnosticReport, St as capActionSuffix, T as registerEventBusService, Tn as readHeapSpaces, Tt as parseCapAction, U as AGENT_CAP_FWD_ACTION, Un as EMPTY_SOCKET_DIRECTION, Ut as HEAP_WATCH_INTERVAL_MS, V as createUdsLogger, Vn as formatSocketPlane, Vt as HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, W as AGENT_CAP_FWD_SERVICE, Wn as createSocketDirectionCounters, Wt as HEAP_WATCH_WARN_RATIO, X as LocalChildRegistry, Xn as CAP_ACTION_UNLABELLED, Xt as RUNNER_HEAP_WATCH_INTERVAL_MS, Y as LocalChildClient, Yn as CAP_ACTION_OVERFLOW_LABEL, Yt as RSS_BUDGET_RELEASE_RATIO, Z as UDS_NO_ROUTE_PREFIX, Zn as EMPTY_CAP_ACTION_READING, Zt as RUNNER_RSS_BUDGET_ENV, _ as getWorkerDeviceRegistry, _n as createInspectorArrayBufferCensus, a as reapProcessGroup, an as nextRssBudgetState, ar as diffEventPlane, at as UdsLocalTransportServer, b as setHubConnected, bn as DECISIVE_HEAP_SPACES, bt as NATIVE_PROVIDER_SERVICE_INFIX, c as runnerOwnsProcessGroup, cn as shouldReclaim, ct as localEndpointPath, d as summarizeMembers, dn as strandedMb, dt as buildNativeCapProxy, en as createDeferredHeapWatchSink, er as createCapActionCensus, et as PARENT_ROUTED_PROVIDER_ADDON_ID, f as installManifestSystemDeps, fn as ARRAY_BUFFER_CENSUS_COOLDOWN_MS, ft as buildUdsNativeCapProxy, g as createUdsAddonContext, gn as createArrayBufferCensusGate, gt as mountNativeCapService, h as createAddonContext, hn as ARRAY_BUFFER_RELEASE_MIN_DROP_RATIO, in as hubMainRssBudget, ir as createEventPlaneReader, it as UdsLocalTransportClient, j as brokerCallForCap, jn as formatOutboundQueueVerdict, jt as copyBundledNativeModules, k as createKernelHwAccel, kn as OUTBOUND_QUEUE_THRESHOLD_BYTES, kt as CapabilityHandle, l as signalAllRunnerGroups, ln as startHeapWatch, lt as FrameDecoder, m as adaptBrokerToCluster, mn as ARRAY_BUFFER_CENSUS_THRESHOLD_MB, nn as createV8Reclaimer, nr as EVENT_PLANE_TOP_N, nt as getCapUsageRegistry, o as registerRunnerGroup, on as parseRssBudgetMb, or as formatEventPlane, ot as SocketChannel, p as installManifestPythonDeps, pn as ARRAY_BUFFER_CENSUS_SUSTAIN_MS, pt as createBrokerDeviceManagerApi, q as CapRouteError, qn as socketDirectionBytes, qt as HUB_RSS_BUDGET_ENV, r as defaultProcessGroupOps, rn as describeRss, rr as createEventPlaneMeter, rt as createLocalTransport, s as releaseRunnerGroup, sn as reclaimIntervalMs, st as PeerAnsweredError, t as CAP_METHOD_NOT_IMPLEMENTED, tn as createLoopDelayMeter, tr as diffCapActionCensus, tt as __resetCapUsageRegistryForTests, un as startRunnerHeapWatch, ut as encodeFrame, v as getOrInitReadinessRegistry, vn as formatArrayBufferCensus, vt as createAddonService, w as getMoleculerEventStats, wn as heapSpaceField, wt as capServiceName, x as EVENT_TOPIC_PREFIX, xn as HEAP_SPACE_REPORT_MIN_MB, xt as capActionName, y as getOrInitReadinessRegistryForClient, yn as isArrayBufferCensusReport, yt as validateProviderRegistrations, z as createUdsEventBus, zn as createSocketPlaneReader, zt as createAddonDataPlaneFacility } from "./child-cap-dispatch-CHTiHbsv.mjs";
|
|
32
|
+
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-B1v6E07R.mjs";
|
|
33
33
|
import { t as CustomActionRegistry } from "./custom-action-registry-B4Cf4O_X.mjs";
|
|
34
34
|
import { z } from "zod";
|
|
35
35
|
import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
@@ -95008,7 +95008,10 @@ var CRASH_WINDOW_MS = 6e4;
|
|
|
95008
95008
|
var MAX_CRASHES_IN_WINDOW = 5;
|
|
95009
95009
|
function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parentUdsPath) {
|
|
95010
95010
|
const spawnFn = deps?.spawnFn ?? spawn;
|
|
95011
|
+
const groupOps = deps?.processGroups ?? defaultProcessGroupOps;
|
|
95012
|
+
const runnersOwnGroups = runnerOwnsProcessGroup(deps?.platform ?? process.platform);
|
|
95011
95013
|
const processes = /* @__PURE__ */ new Map();
|
|
95014
|
+
const pendingGroupReaps = /* @__PURE__ */ new Map();
|
|
95012
95015
|
const runnerLocks = /* @__PURE__ */ new Map();
|
|
95013
95016
|
function withRunnerLock(runnerId, fn) {
|
|
95014
95017
|
const result = (runnerLocks.get(runnerId) ?? Promise.resolve()).then(fn, fn);
|
|
@@ -95048,6 +95051,49 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95048
95051
|
}, data));
|
|
95049
95052
|
}
|
|
95050
95053
|
/**
|
|
95054
|
+
* One line per reap that found something, or that failed. An empty group is the
|
|
95055
|
+
* normal case after a clean stop and stays quiet at debug. The kernel cannot say
|
|
95056
|
+
* which device a child served — the runner id is the finest attribution it has.
|
|
95057
|
+
*/
|
|
95058
|
+
function logGroupReap(runnerId, result) {
|
|
95059
|
+
const found = result.membersAtExit;
|
|
95060
|
+
const killed = result.killed ?? [];
|
|
95061
|
+
const line = `[${runnerId}] runner group reaped {pgid=${result.pgid}, members=${found === null ? "unreadable" : found.length}${found !== null && found.length > 0 ? ` (${summarizeMembers(found)})` : ""}, sigkilled=${killed.length}${killed.length > 0 ? ` (${summarizeMembers(killed)})` : ""}${result.error !== null ? `, error=${result.error}` : ""}}`;
|
|
95062
|
+
const logger = capturedBroker?.logger;
|
|
95063
|
+
if (result.error !== null || killed.length > 0) if (logger) logger.warn(line);
|
|
95064
|
+
else console.error(line);
|
|
95065
|
+
else if ((found?.length ?? 0) > 0 || found === null) logger?.info(line);
|
|
95066
|
+
else logger?.debug(line);
|
|
95067
|
+
}
|
|
95068
|
+
/**
|
|
95069
|
+
* Reap a runner's process group (D668): SIGTERM, a bounded grace, SIGKILL for what
|
|
95070
|
+
* remains. Memoized on the entry so the `exit` handler and a stop/restart that timed
|
|
95071
|
+
* out waiting for that exit share one reap, and registered in `pendingGroupReaps` so
|
|
95072
|
+
* the next spawn under the same id waits for it. Never rejects.
|
|
95073
|
+
*/
|
|
95074
|
+
function reapRunnerGroup(entry) {
|
|
95075
|
+
if (entry.groupReap !== null) return entry.groupReap;
|
|
95076
|
+
if (!entry.ownsGroup) {
|
|
95077
|
+
entry.groupReap = Promise.resolve();
|
|
95078
|
+
return entry.groupReap;
|
|
95079
|
+
}
|
|
95080
|
+
const reap = reapProcessGroup(entry.pid, groupOps).then((result) => logGroupReap(entry.name, result)).catch((err) => {
|
|
95081
|
+
capturedBroker?.logger.error(`[${entry.name}] runner group reap threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
95082
|
+
}).finally(() => {
|
|
95083
|
+
releaseRunnerGroup(entry.pid);
|
|
95084
|
+
if (pendingGroupReaps.get(entry.name) === tracked) pendingGroupReaps.delete(entry.name);
|
|
95085
|
+
});
|
|
95086
|
+
const previous = pendingGroupReaps.get(entry.name);
|
|
95087
|
+
const tracked = previous ? Promise.all([previous, reap]).then(() => void 0) : reap;
|
|
95088
|
+
pendingGroupReaps.set(entry.name, tracked);
|
|
95089
|
+
entry.groupReap = reap;
|
|
95090
|
+
return reap;
|
|
95091
|
+
}
|
|
95092
|
+
/** Resolves once every reap started for `runnerId` has finished. */
|
|
95093
|
+
async function awaitPredecessorReap(runnerId) {
|
|
95094
|
+
await pendingGroupReaps.get(runnerId);
|
|
95095
|
+
}
|
|
95096
|
+
/**
|
|
95051
95097
|
* Spawn ONE runner subprocess (`addon-runner.js`) that hosts the
|
|
95052
95098
|
* `addons` set sharing a single Moleculer broker. The normal case is
|
|
95053
95099
|
* a size-1 `addons` array — one addon, one process; the media group
|
|
@@ -95096,8 +95142,9 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95096
95142
|
"pipe",
|
|
95097
95143
|
"pipe"
|
|
95098
95144
|
],
|
|
95099
|
-
detached:
|
|
95145
|
+
detached: runnersOwnGroups
|
|
95100
95146
|
});
|
|
95147
|
+
const ownsGroup = runnersOwnGroups && typeof child.pid === "number" && child.pid > 1;
|
|
95101
95148
|
const entry = {
|
|
95102
95149
|
pid: child.pid,
|
|
95103
95150
|
nodeId,
|
|
@@ -95108,16 +95155,23 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95108
95155
|
startedAt: Date.now(),
|
|
95109
95156
|
restartCount: 0,
|
|
95110
95157
|
state: "starting",
|
|
95111
|
-
child
|
|
95158
|
+
child,
|
|
95159
|
+
ownsGroup,
|
|
95160
|
+
groupReap: null
|
|
95112
95161
|
};
|
|
95162
|
+
if (ownsGroup) registerRunnerGroup(entry.pid, {
|
|
95163
|
+
runnerId,
|
|
95164
|
+
kill: groupOps.kill
|
|
95165
|
+
});
|
|
95113
95166
|
child.stdout?.on("data", (data) => {
|
|
95114
|
-
if (data.toString().includes(`READY:${nodeId}`)) entry.state = "running";
|
|
95167
|
+
if (data.toString().includes(`READY:${nodeId}`) && entry.state === "starting") entry.state = "running";
|
|
95115
95168
|
});
|
|
95116
95169
|
child.stderr?.on("data", (data) => {
|
|
95117
95170
|
process.stderr.write(`[${runnerId}] ${data.toString()}`);
|
|
95118
95171
|
});
|
|
95119
95172
|
child.on("exit", (code, signal) => {
|
|
95120
95173
|
console.error(`[process-service EXIT] runner=${runnerId} code=${String(code)} signal=${String(signal)} state=${entry.state}`);
|
|
95174
|
+
const groupReap = reapRunnerGroup(entry);
|
|
95121
95175
|
if (entry.state === "stopped") return;
|
|
95122
95176
|
entry.state = "crashed";
|
|
95123
95177
|
capturedBroker?.logger.error(`[${runnerId}] Process exited (code=${code}, signal=${signal})`);
|
|
@@ -95156,6 +95210,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95156
95210
|
if (capturedBroker) forceMoleculerDisconnect(capturedBroker, entry.nodeId);
|
|
95157
95211
|
setTimeout(() => {
|
|
95158
95212
|
withRunnerLock(runnerId, async () => {
|
|
95213
|
+
await groupReap;
|
|
95159
95214
|
if (processes.has(runnerId)) return;
|
|
95160
95215
|
const restarted = spawnRunner(runnerId, addons, env);
|
|
95161
95216
|
restarted.restartCount = entry.restartCount + 1;
|
|
@@ -95168,10 +95223,12 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95168
95223
|
return {
|
|
95169
95224
|
name: "$process",
|
|
95170
95225
|
actions: {
|
|
95171
|
-
spawnRunner: { handler(ctx) {
|
|
95226
|
+
spawnRunner: { async handler(ctx) {
|
|
95172
95227
|
const { runnerId, addons, env } = ctx.params;
|
|
95173
95228
|
if (processes.has(runnerId)) throw new Error(`Runner "${runnerId}" already running`);
|
|
95174
95229
|
if (!Array.isArray(addons) || addons.length === 0) throw new Error(`spawnRunner requires non-empty addons array`);
|
|
95230
|
+
await awaitPredecessorReap(runnerId);
|
|
95231
|
+
if (processes.has(runnerId)) throw new Error(`Runner "${runnerId}" already running`);
|
|
95175
95232
|
invalidateHeapProfiles(addons);
|
|
95176
95233
|
const entry = spawnRunner(runnerId, addons, env);
|
|
95177
95234
|
return {
|
|
@@ -95208,6 +95265,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95208
95265
|
});
|
|
95209
95266
|
});
|
|
95210
95267
|
}
|
|
95268
|
+
await reapRunnerGroup(target);
|
|
95211
95269
|
processes.delete(name);
|
|
95212
95270
|
crashSupervisor.reset(name);
|
|
95213
95271
|
forceMoleculerDisconnect(ctx.broker, deadNodeId);
|
|
@@ -95244,6 +95302,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95244
95302
|
});
|
|
95245
95303
|
});
|
|
95246
95304
|
}
|
|
95305
|
+
await reapRunnerGroup(target);
|
|
95247
95306
|
processes.delete(name);
|
|
95248
95307
|
crashSupervisor.reset(name);
|
|
95249
95308
|
forceMoleculerDisconnect(ctx.broker, deadNodeId);
|
|
@@ -95303,6 +95362,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95303
95362
|
});
|
|
95304
95363
|
});
|
|
95305
95364
|
}
|
|
95365
|
+
await reapRunnerGroup(entry);
|
|
95306
95366
|
processes.delete(name);
|
|
95307
95367
|
crashSupervisor.reset(name);
|
|
95308
95368
|
invalidateHeapProfiles(runnerAddons);
|
|
@@ -95353,19 +95413,28 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
95353
95413
|
started() {
|
|
95354
95414
|
capturedBroker = this.broker;
|
|
95355
95415
|
},
|
|
95356
|
-
stopped() {
|
|
95357
|
-
const
|
|
95358
|
-
|
|
95416
|
+
async stopped() {
|
|
95417
|
+
const entries = [...processes.values()];
|
|
95418
|
+
await Promise.all(entries.map(async (entry) => {
|
|
95359
95419
|
entry.state = "stopped";
|
|
95360
|
-
entry.child.
|
|
95361
|
-
|
|
95362
|
-
|
|
95363
|
-
|
|
95364
|
-
|
|
95365
|
-
|
|
95366
|
-
|
|
95420
|
+
if (!(entry.child.exitCode !== null || entry.child.signalCode !== null)) {
|
|
95421
|
+
entry.child.kill("SIGTERM");
|
|
95422
|
+
await new Promise((resolve) => {
|
|
95423
|
+
const timer = setTimeout(() => {
|
|
95424
|
+
if (entry.child.exitCode === null && entry.child.signalCode === null) {
|
|
95425
|
+
capturedBroker?.logger.warn(`[${entry.name}] Did not exit on SIGTERM — sending SIGKILL`);
|
|
95426
|
+
entry.child.kill("SIGKILL");
|
|
95427
|
+
}
|
|
95428
|
+
resolve();
|
|
95429
|
+
}, 3e3);
|
|
95430
|
+
entry.child.once("exit", () => {
|
|
95431
|
+
clearTimeout(timer);
|
|
95432
|
+
resolve();
|
|
95433
|
+
});
|
|
95434
|
+
});
|
|
95367
95435
|
}
|
|
95368
|
-
|
|
95436
|
+
await reapRunnerGroup(entry);
|
|
95437
|
+
}));
|
|
95369
95438
|
processes.clear();
|
|
95370
95439
|
capturedBroker = null;
|
|
95371
95440
|
}
|
|
@@ -95849,4 +95918,4 @@ var LifecycleJobEngine = class {
|
|
|
95849
95918
|
}
|
|
95850
95919
|
};
|
|
95851
95920
|
//#endregion
|
|
95852
|
-
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, ARRAY_BUFFER_CENSUS_COOLDOWN_MS, ARRAY_BUFFER_CENSUS_SUSTAIN_MS, ARRAY_BUFFER_CENSUS_THRESHOLD_MB, ARRAY_BUFFER_RELEASE_MIN_DROP_RATIO, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CAP_ACTION_OVERFLOW_LABEL, CAP_ACTION_UNLABELLED, CAP_METHOD_NOT_IMPLEMENTED, CA_COMMON_NAME, CA_VALIDITY_DAYS, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ComposerAddon, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CoreBlocksAddon, CustomActionRegistry, DECISIVE_HEAP_SPACES, DEFAULT_DATA_PATH, DEFAULT_LAN_HTTP_PORT, DEFAULT_LOG_LEVEL, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EMPTY_CAP_ACTION_READING, EMPTY_SOCKET_DIRECTION, EMPTY_SOCKET_PLANE_BASELINE, EVENT_PLANE_TOP_N, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HEAP_RECLAIM_MIN_INTERVAL_MS, HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, HEAP_RECLAIM_TRIGGER_MB, HEAP_SPACE_REPORT_MIN_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HUB_MAIN_HEAP_WATCH_LABEL, HUB_MAIN_RSS_BUDGET_MB, HUB_RSS_BUDGET_ENV, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LoggingGate, LokiDestination, LokiLoggingAddon, MAX_CAP_ACTIONS_PER_PEER, MAX_LEAF_VALIDITY_DAYS, MESH_QUEUE_TOP_N, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, OUTBOUND_QUEUE_COOLDOWN_MS, OUTBOUND_QUEUE_SUSTAIN_MS, OUTBOUND_QUEUE_THRESHOLD_BYTES, PARENT_ROUTED_PROVIDER_ADDON_ID, PYTHON_VERSION, PeerAnsweredError, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, RESTART_MARKER_FILE, RSS_BUDGET_REANNOUNCE_MIN_MS, RSS_BUDGET_RELEASE_RATIO, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNNER_RSS_BUDGET_ENV, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, SOCKET_PLANE_TOP_N, SOCKET_QUEUE_TOP_N, STALL_REPORT_MS, STALL_TICK_MS, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, ZERO_LOOP_DELAY, __resetCapUsageRegistryForTests, __resetLoggingGateForTests, adaptBrokerToCluster, addonSettingsCapability, allFamiliesListenHost, applyLanHttp, attributeStall, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildNpmChildEnv, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionLabel, capActionName, capActionSuffix, capBareAction, capServiceName, classifyAddonDir, classifyCapRoute, clearPendingRestart, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonPeerBytesFacility, createAddonService, createArrayBufferCensusGate, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCapActionCensus, createCoreCapService, createDeferredHeapWatchSink, createDoorSettingsView, createEventPlaneMeter, createEventPlaneReader, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createInspectorArrayBufferCensus, createKernelHwAccel, createLocalTransport, createLoopDelayMeter, createMeshQueueReader, createOutboundQueueGate, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createSocketDirectionCounters, createSocketPlaneMeter, createSocketPlaneReader, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, describeRss, detectWorkspacePackagesDir, deviceCapResolverLink, diffCapActionCensus, diffEventPlane, diffSocketPlane, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, emitHeapDiagnosticReport, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, fetchJson, findInPath, formatArrayBufferCensus, formatEventPlane, formatHeapSpaces, formatLogLine, formatMeshQueue, formatOutboundQueueVerdict, formatSocketPlane, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getLoggingGate, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, heapSpaceField, hostNodeIdOf, hubMainRssBudget, installManifestNativeDeps, installManifestPythonDeps, installManifestSystemDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isArrayBufferCensusReport, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, isolatedBuiltinPhase, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, nextRssBudgetState, parseCapAction, parseRangeHeader, parseRssBudgetMb, parseTokenizedUrl, partitionIsolatedBuiltinIds, proxyToUpstream, quarantineAddonResidue, readExtraSans, readHeapSpaces, readLanHttpState, readMoleculerFanoutMode, readPendingRestart, readSocketQueues, readTlsAccessStatus, readTlsMode, readinessKey, reclaimIntervalMs, recordSocketFrame, registerEventBusService, registerLanHttpHandler, reissueTlsLeaf, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runHubAddonBoot, runNpm, sampleSocketDirection, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, selectReportedSpaces, serializeTypedArrays, setHubConnected, setNodeEventInterest, setWrapperActive, shouldReclaim, socketDirectionBytes, socketDirectionMessages, startEventLoopStallMonitor, startHeapWatch, startRunnerHeapWatch, strandedMb, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
|
95921
|
+
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, ARRAY_BUFFER_CENSUS_COOLDOWN_MS, ARRAY_BUFFER_CENSUS_SUSTAIN_MS, ARRAY_BUFFER_CENSUS_THRESHOLD_MB, ARRAY_BUFFER_RELEASE_MIN_DROP_RATIO, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CAP_ACTION_OVERFLOW_LABEL, CAP_ACTION_UNLABELLED, CAP_METHOD_NOT_IMPLEMENTED, CA_COMMON_NAME, CA_VALIDITY_DAYS, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ComposerAddon, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CoreBlocksAddon, CustomActionRegistry, DECISIVE_HEAP_SPACES, DEFAULT_DATA_PATH, DEFAULT_LAN_HTTP_PORT, DEFAULT_LOG_LEVEL, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EMPTY_CAP_ACTION_READING, EMPTY_SOCKET_DIRECTION, EMPTY_SOCKET_PLANE_BASELINE, EVENT_PLANE_TOP_N, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HEAP_RECLAIM_MIN_INTERVAL_MS, HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, HEAP_RECLAIM_TRIGGER_MB, HEAP_SPACE_REPORT_MIN_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HUB_MAIN_HEAP_WATCH_LABEL, HUB_MAIN_RSS_BUDGET_MB, HUB_RSS_BUDGET_ENV, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LoggingGate, LokiDestination, LokiLoggingAddon, MAX_CAP_ACTIONS_PER_PEER, MAX_LEAF_VALIDITY_DAYS, MESH_QUEUE_TOP_N, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, OUTBOUND_QUEUE_COOLDOWN_MS, OUTBOUND_QUEUE_SUSTAIN_MS, OUTBOUND_QUEUE_THRESHOLD_BYTES, PARENT_ROUTED_PROVIDER_ADDON_ID, PYTHON_VERSION, PeerAnsweredError, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, RESTART_MARKER_FILE, RSS_BUDGET_REANNOUNCE_MIN_MS, RSS_BUDGET_RELEASE_RATIO, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNNER_RSS_BUDGET_ENV, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, SOCKET_PLANE_TOP_N, SOCKET_QUEUE_TOP_N, STALL_REPORT_MS, STALL_TICK_MS, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, ZERO_LOOP_DELAY, __resetCapUsageRegistryForTests, __resetLoggingGateForTests, adaptBrokerToCluster, addonSettingsCapability, allFamiliesListenHost, applyLanHttp, attributeStall, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildNpmChildEnv, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionLabel, capActionName, capActionSuffix, capBareAction, capServiceName, classifyAddonDir, classifyCapRoute, clearPendingRestart, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonPeerBytesFacility, createAddonService, createArrayBufferCensusGate, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCapActionCensus, createCoreCapService, createDeferredHeapWatchSink, createDoorSettingsView, createEventPlaneMeter, createEventPlaneReader, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createInspectorArrayBufferCensus, createKernelHwAccel, createLocalTransport, createLoopDelayMeter, createMeshQueueReader, createOutboundQueueGate, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createSocketDirectionCounters, createSocketPlaneMeter, createSocketPlaneReader, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, describeRss, detectWorkspacePackagesDir, deviceCapResolverLink, diffCapActionCensus, diffEventPlane, diffSocketPlane, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, emitHeapDiagnosticReport, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, fetchJson, findInPath, formatArrayBufferCensus, formatEventPlane, formatHeapSpaces, formatLogLine, formatMeshQueue, formatOutboundQueueVerdict, formatSocketPlane, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getLoggingGate, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, heapSpaceField, hostNodeIdOf, hubMainRssBudget, installManifestNativeDeps, installManifestPythonDeps, installManifestSystemDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isArrayBufferCensusReport, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, isolatedBuiltinPhase, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, nextRssBudgetState, parseCapAction, parseRangeHeader, parseRssBudgetMb, parseTokenizedUrl, partitionIsolatedBuiltinIds, proxyToUpstream, quarantineAddonResidue, readExtraSans, readHeapSpaces, readLanHttpState, readMoleculerFanoutMode, readPendingRestart, readSocketQueues, readTlsAccessStatus, readTlsMode, readinessKey, reclaimIntervalMs, recordSocketFrame, registerEventBusService, registerLanHttpHandler, reissueTlsLeaf, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runHubAddonBoot, runNpm, sampleSocketDirection, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, selectReportedSpaces, serializeTypedArrays, setHubConnected, setNodeEventInterest, setWrapperActive, shouldReclaim, signalAllRunnerGroups, socketDirectionBytes, socketDirectionMessages, startEventLoopStallMonitor, startHeapWatch, startRunnerHeapWatch, strandedMb, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ export { localProviderLink, brokerTransportLink, deviceCapResolverLink, ipcParen
|
|
|
73
73
|
export type { LocalProviderResolver, BrokerCapCallOpts } from './moleculer/trpc-links.js';
|
|
74
74
|
export { createProcessService } from './moleculer/process-service.js';
|
|
75
75
|
export type { ProcessInfo } from './moleculer/process-service.js';
|
|
76
|
+
export { signalAllRunnerGroups } from './moleculer/runner-process-group.js';
|
|
76
77
|
export { CapUsageRegistry, getCapUsageRegistry, PARENT_ROUTED_PROVIDER_ADDON_ID, __resetCapUsageRegistryForTests, } from './moleculer/cap-usage-registry.js';
|
|
77
78
|
export type { CapUsageCallRecord, CapUsageEdge, CapUsageRegistryOptions, CapUsageStats, } from './moleculer/cap-usage-registry.js';
|
|
78
79
|
export { createScopedProcessManager } from './moleculer/process-context.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ChildProcess, SpawnOptions } from 'node:child_process';
|
|
2
2
|
import { ServiceSchema } from 'moleculer';
|
|
3
|
+
import { ProcessGroupOps } from './runner-process-group.js';
|
|
3
4
|
/** One addon hosted inside a runner subprocess. */
|
|
4
5
|
interface RunnerAddonSpec {
|
|
5
6
|
readonly addonId: string;
|
|
@@ -137,6 +138,10 @@ interface SpawnedProcess {
|
|
|
137
138
|
*/
|
|
138
139
|
state: 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed' | 'failed';
|
|
139
140
|
child: ChildProcess;
|
|
141
|
+
/** The runner leads its own process group (POSIX, D668); its pgid is its `pid`. */
|
|
142
|
+
readonly ownsGroup: boolean;
|
|
143
|
+
/** The reap of this runner's group, once started. Memoized: every exit path shares it. */
|
|
144
|
+
groupReap: Promise<void> | null;
|
|
140
145
|
}
|
|
141
146
|
interface ProcessInfo {
|
|
142
147
|
readonly pid: number;
|
|
@@ -174,6 +179,10 @@ interface ProcessInfo {
|
|
|
174
179
|
type SpawnFn = (command: string, args: readonly string[], opts: SpawnOptions) => ChildProcess;
|
|
175
180
|
interface ProcessServiceDeps {
|
|
176
181
|
readonly spawnFn?: SpawnFn;
|
|
182
|
+
/** Group signalling + member listing. Tests inject a fake: a fake pid must never be signalled. */
|
|
183
|
+
readonly processGroups?: ProcessGroupOps;
|
|
184
|
+
/** Platform deciding whether a runner leads a process group. Defaults to `process.platform`. */
|
|
185
|
+
readonly platform?: NodeJS.Platform;
|
|
177
186
|
}
|
|
178
187
|
declare function createProcessService(parentNodeId: string, dataDir: string, deps?: ProcessServiceDeps, parentTcpPort?: number, parentUdsPath?: string): ServiceSchema;
|
|
179
188
|
export type { ProcessInfo, SpawnedProcess };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** SIGTERM → SIGKILL grace for a runner's group, in ms. ffmpeg finalises a segment well inside it. */
|
|
2
|
+
export declare const RUNNER_GROUP_REAP_GRACE_MS = 2000;
|
|
3
|
+
/** Whether a runner is spawned as a process-group leader on this platform. */
|
|
4
|
+
export declare function runnerOwnsProcessGroup(platform?: NodeJS.Platform): boolean;
|
|
5
|
+
/** One live (non-zombie) member of a process group. */
|
|
6
|
+
export interface GroupMember {
|
|
7
|
+
readonly pid: number;
|
|
8
|
+
/** Executable name (`ffmpeg`, `llama-server`, …). */
|
|
9
|
+
readonly command: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The OS surface a group reap needs. Injectable so a unit test never signals a real pid:
|
|
13
|
+
* the fake-spawn suites hand out pids like 70001, and a `kill(-70001)` on a developer's
|
|
14
|
+
* machine is not a test.
|
|
15
|
+
*/
|
|
16
|
+
export interface ProcessGroupOps {
|
|
17
|
+
/** `process.kill`. A negative pid addresses a group; signal 0 probes. Throws ESRCH when empty. */
|
|
18
|
+
readonly kill: (pid: number, signal: NodeJS.Signals | 0) => void;
|
|
19
|
+
/** Live members of `pgid`, or `null` when the table could not be read. */
|
|
20
|
+
readonly listMembers: (pgid: number) => Promise<readonly GroupMember[] | null>;
|
|
21
|
+
readonly sleep: (ms: number) => Promise<void>;
|
|
22
|
+
readonly graceMs: number;
|
|
23
|
+
}
|
|
24
|
+
/** What one reap did. `membersAtExit === null` means the table was unreadable, not empty. */
|
|
25
|
+
export interface GroupReapResult {
|
|
26
|
+
readonly pgid: number;
|
|
27
|
+
readonly membersAtExit: readonly GroupMember[] | null;
|
|
28
|
+
/** Members still present after the grace, which were sent SIGKILL. */
|
|
29
|
+
readonly killed: readonly GroupMember[] | null;
|
|
30
|
+
/** The group was already empty when the reap began — the normal case after a clean stop. */
|
|
31
|
+
readonly alreadyEmpty: boolean;
|
|
32
|
+
/** A signal the OS refused for a reason other than ESRCH (EPERM). */
|
|
33
|
+
readonly error: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* SIGTERM the whole group, wait up to `graceMs` for it to empty, SIGKILL what is left.
|
|
37
|
+
*
|
|
38
|
+
* pid reuse: POSIX never hands out a pid while a process group with that id exists, so
|
|
39
|
+
* the SIGTERM always lands on our group. The SIGKILL is sent only when the group is
|
|
40
|
+
* still populated at the end of the grace, which is the same group; the residual window
|
|
41
|
+
* (group empties, the pid wraps around AND is reused as a new group leader, all inside
|
|
42
|
+
* the grace) is not reachable in practice.
|
|
43
|
+
*/
|
|
44
|
+
export declare function reapProcessGroup(pgid: number, ops: ProcessGroupOps): Promise<GroupReapResult>;
|
|
45
|
+
/** `ffmpeg×28 llama-server×1` — what a reap line says it removed. */
|
|
46
|
+
export declare function summarizeMembers(members: readonly GroupMember[]): string;
|
|
47
|
+
/** Parse `ps -A -o pid=,pgid=,stat=,comm=` for one group, zombies excluded. */
|
|
48
|
+
export declare function parsePsGroupMembers(stdout: string, pgid: number): readonly GroupMember[];
|
|
49
|
+
/** Live members of `pgid`: `/proc` on Linux, `ps` elsewhere; `null` when neither answers. */
|
|
50
|
+
export declare function listProcessGroupMembers(pgid: number, platform?: NodeJS.Platform): Promise<readonly GroupMember[] | null>;
|
|
51
|
+
export declare const defaultProcessGroupOps: ProcessGroupOps;
|
|
52
|
+
interface OwnedGroup {
|
|
53
|
+
readonly runnerId: string;
|
|
54
|
+
readonly kill: ProcessGroupOps['kill'];
|
|
55
|
+
}
|
|
56
|
+
export declare function registerRunnerGroup(pgid: number, group: OwnedGroup): void;
|
|
57
|
+
export declare function releaseRunnerGroup(pgid: number): void;
|
|
58
|
+
/**
|
|
59
|
+
* Signal every runner group this process owns, synchronously. Hub-main's SIGTERM/SIGINT
|
|
60
|
+
* handler calls it: before D668 the runners were in hub-main's own group and its
|
|
61
|
+
* `kill -- -<pid>` reached them and their children; now each is its own group.
|
|
62
|
+
* Returns how many groups were signalled.
|
|
63
|
+
*/
|
|
64
|
+
export declare function signalAllRunnerGroups(signal: NodeJS.Signals): number;
|
|
65
|
+
/** Test seam: the groups currently owned, by pgid. */
|
|
66
|
+
export declare function ownedRunnerGroupIds(): readonly number[];
|
|
67
|
+
export interface RunnerParentDeathWatchdogOptions {
|
|
68
|
+
readonly initialPpid?: number;
|
|
69
|
+
readonly readPpid?: () => number;
|
|
70
|
+
readonly intervalMs?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Arm the runner's parent-death watchdog before addon code starts loading.
|
|
74
|
+
*
|
|
75
|
+
* A parent can die while an addon module or `initialize()` is still pending, so
|
|
76
|
+
* installing this only after READY leaves exactly the boot window where a detached
|
|
77
|
+
* runner can become an orphan. Any PPID change means the direct parent died and the
|
|
78
|
+
* kernel reparented us; checking for a change also covers a non-PID-1 subreaper.
|
|
79
|
+
*/
|
|
80
|
+
export declare function startRunnerParentDeathWatchdog(onParentDeath: () => void, options?: RunnerParentDeathWatchdogOptions): NodeJS.Timeout | null;
|
|
81
|
+
/**
|
|
82
|
+
* Last resort for a detached runner whose direct parent disappeared without an
|
|
83
|
+
* `exit` hook (SIGKILL, native crash). The runner's own pid is also its pgid, so
|
|
84
|
+
* one SIGKILL removes the runner and every descendant in that group atomically.
|
|
85
|
+
*
|
|
86
|
+
* Calling `kill(-process.pid, ...)` from an ordinary, non-group-leading process
|
|
87
|
+
* returns ESRCH: while this pid exists, no unrelated process group can have the
|
|
88
|
+
* same id. That makes the failed call a safe compatibility fallback for an older
|
|
89
|
+
* parent that did not spawn the runner detached.
|
|
90
|
+
*/
|
|
91
|
+
export declare function killOwnRunnerGroupAfterParentLoss(platform?: NodeJS.Platform, kill?: ProcessGroupOps['kill']): boolean;
|
|
92
|
+
export {};
|