@lensmcp/cluster 1.16.18 → 1.16.19
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/executors/gateway/runtime/lens-children.d.ts +3 -2
- package/executors/gateway/runtime/lens-children.d.ts.map +1 -1
- package/executors/gateway/runtime/lens-children.js +19 -2
- package/executors/gateway/runtime/server.d.ts.map +1 -1
- package/executors/gateway/runtime/server.js +4 -3
- package/package.json +3 -3
|
@@ -15,8 +15,9 @@ export interface LensChildren {
|
|
|
15
15
|
* everything"): spawn each app's vite (+ capture) in the workspace's OWN root + event bus, on a
|
|
16
16
|
* collision-safe port, and point its route target at that port. Returns a reaper for unregister. */
|
|
17
17
|
hostWorkspaceApps(fragment: WorkspaceFragment): () => void;
|
|
18
|
-
/** Reap all managed children (called from `stop()`)
|
|
19
|
-
|
|
18
|
+
/** Reap all managed children (called from `stop()`): SIGTERM, a grace window, then SIGKILL any survivor
|
|
19
|
+
* (vite ignores SIGTERM → would orphan when the daemon exits). Async so `stop()` awaits the escalation. */
|
|
20
|
+
reapAll(): Promise<void>;
|
|
20
21
|
}
|
|
21
22
|
export declare function createLensChildren(rt: GatewayRuntime, obs: Observability, options: GatewayRuntimeOptions): LensChildren;
|
|
22
23
|
//# sourceMappingURL=lens-children.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lens-children.d.ts","sourceRoot":"","sources":["../../../../../../libs/cluster/src/executors/gateway/runtime/lens-children.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,kCAAkC,CAAC;AAG1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAuB,MAAM,SAAS,CAAC;AAQ1F,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAM7E,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,UAAU,CAAC;IAC9B;iFAC6E;IAC7E,qBAAqB,IAAI,IAAI,CAAC;IAC9B;;6GAEyG;IACzG,sBAAsB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAC9E;;yGAEqG;IACrG,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAAC;IAC3D
|
|
1
|
+
{"version":3,"file":"lens-children.d.ts","sourceRoot":"","sources":["../../../../../../libs/cluster/src/executors/gateway/runtime/lens-children.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,kCAAkC,CAAC;AAG1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAuB,MAAM,SAAS,CAAC;AAQ1F,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAM7E,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,UAAU,CAAC;IAC9B;iFAC6E;IAC7E,qBAAqB,IAAI,IAAI,CAAC;IAC9B;;6GAEyG;IACzG,sBAAsB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAC9E;;yGAEqG;IACrG,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAAC;IAC3D;gHAC4G;IAC5G,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,qBAAqB,GAAG,YAAY,CAmTvH"}
|
|
@@ -315,17 +315,34 @@ function createLensChildren(rt, obs, options) {
|
|
|
315
315
|
usedAppPorts.delete(p);
|
|
316
316
|
};
|
|
317
317
|
};
|
|
318
|
-
const reapAll = () => {
|
|
318
|
+
const reapAll = async (graceMs = 2500) => {
|
|
319
319
|
if (lensSweeper) {
|
|
320
320
|
clearInterval(lensSweeper);
|
|
321
321
|
lensSweeper = undefined;
|
|
322
322
|
}
|
|
323
|
-
|
|
323
|
+
const kids = [...lensChildren];
|
|
324
|
+
for (const c of kids) {
|
|
324
325
|
try {
|
|
325
326
|
c.kill('SIGTERM');
|
|
326
327
|
}
|
|
327
328
|
catch { /* already gone */ }
|
|
328
329
|
}
|
|
330
|
+
// Grace, then SIGKILL any survivor — vite ignores SIGTERM, so without this it ORPHANS (reparents to
|
|
331
|
+
// ppid 1) when the daemon exits, keeping its port held (5173/4200/…). Poll so we escalate only for the
|
|
332
|
+
// stragglers and wait no longer than needed.
|
|
333
|
+
const alive = (c) => c.exitCode === null && c.signalCode === null;
|
|
334
|
+
const deadline = Date.now() + graceMs;
|
|
335
|
+
while (Date.now() < deadline && kids.some(alive)) {
|
|
336
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
337
|
+
}
|
|
338
|
+
for (const c of kids) {
|
|
339
|
+
if (alive(c)) {
|
|
340
|
+
try {
|
|
341
|
+
c.kill('SIGKILL');
|
|
342
|
+
}
|
|
343
|
+
catch { /* already gone */ }
|
|
344
|
+
}
|
|
345
|
+
}
|
|
329
346
|
};
|
|
330
347
|
return { spawnManagedChild, bootSingletonsAndApps, hostWorkspaceDashboard, hostWorkspaceApps, reapAll };
|
|
331
348
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../../../libs/cluster/src/executors/gateway/runtime/server.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAkB,qBAAqB,EAAsB,MAAM,SAAS,CAAC;AAkDxH,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../../../libs/cluster/src/executors/gateway/runtime/server.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAkB,qBAAqB,EAAsB,MAAM,SAAS,CAAC;AAkDxH,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAmPxB"}
|
|
@@ -305,9 +305,10 @@ async function startGateway(options, context) {
|
|
|
305
305
|
(0, workspace_registry_1.unregisterWorkspace)(wsKey); // drop this workspace from the global chooser registry (graceful stop)
|
|
306
306
|
for (const svc of services)
|
|
307
307
|
svcLayer.killSpawned(svc, 'gateway shutdown');
|
|
308
|
-
// Reap the lens-mode managed children (dashboard + MCP singletons + each
|
|
309
|
-
//
|
|
310
|
-
|
|
308
|
+
// Reap the lens-mode managed children (dashboard + MCP singletons + each `lens:true` app's Vite/capture)
|
|
309
|
+
// — SIGTERM → grace → SIGKILL, awaited, so a SIGTERM-ignoring vite is gone BEFORE the daemon exits
|
|
310
|
+
// (otherwise it orphans + keeps its port). Same teardown as the pod services.
|
|
311
|
+
await lens.reapAll();
|
|
311
312
|
await Promise.all(servers.map((s) => new Promise((r) => s.close(() => r()))));
|
|
312
313
|
proxyLayer.closeProxy();
|
|
313
314
|
proxyLayer.destroyAgents(); // release pooled upstream sockets
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/cluster",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.19",
|
|
4
4
|
"description": "Run your Nx workspace as a local production cluster: pods on unix sockets with true HMR, one https gateway with per-project domains, scale-from-zero, autoscale, idle-kill, local-CA TLS — observed by the LensMCP lens.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@lensmcp/node-instrumentation": "1.16.
|
|
69
|
-
"@lensmcp/nx-plugin": "1.16.
|
|
68
|
+
"@lensmcp/node-instrumentation": "1.16.19",
|
|
69
|
+
"@lensmcp/nx-plugin": "1.16.19",
|
|
70
70
|
"fork-ts-checker-webpack-plugin": "^9.0.0",
|
|
71
71
|
"glob": "^11.0.0",
|
|
72
72
|
"http-proxy": "^1.18.0",
|