orchestrating 0.1.36 → 0.1.37
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/bin/orch +20 -0
- package/package.json +1 -1
package/bin/orch
CHANGED
|
@@ -448,10 +448,12 @@ async function handleDaemon(projectsDir) {
|
|
|
448
448
|
|
|
449
449
|
const PING_INTERVAL_MS = 30_000;
|
|
450
450
|
const PONG_TIMEOUT_MS = 10_000;
|
|
451
|
+
const HEARTBEAT_TIMEOUT_MS = 65_000; // expect server heartbeat every 30s, allow 2 missed + margin
|
|
451
452
|
let ws = null;
|
|
452
453
|
let pingTimer = null;
|
|
453
454
|
let pongTimer = null;
|
|
454
455
|
let reconnectTimer = null;
|
|
456
|
+
let heartbeatTimer = null;
|
|
455
457
|
|
|
456
458
|
// Scan project directories
|
|
457
459
|
const homeDir = os.homedir();
|
|
@@ -478,6 +480,14 @@ async function handleDaemon(projectsDir) {
|
|
|
478
480
|
const recentRequests = new Set();
|
|
479
481
|
const recentSpawns = new Map(); // "command:cwd" -> timestamp
|
|
480
482
|
|
|
483
|
+
function resetHeartbeatTimer(sock) {
|
|
484
|
+
if (heartbeatTimer) clearTimeout(heartbeatTimer);
|
|
485
|
+
heartbeatTimer = setTimeout(() => {
|
|
486
|
+
process.stderr.write(`${RED}${PREFIX} No server heartbeat — reconnecting${RESET}\n`);
|
|
487
|
+
if (sock && sock.readyState !== WebSocket.CLOSED) sock.terminate();
|
|
488
|
+
}, HEARTBEAT_TIMEOUT_MS);
|
|
489
|
+
}
|
|
490
|
+
|
|
481
491
|
function scheduleReconnect(delaySec) {
|
|
482
492
|
if (reconnecting) return;
|
|
483
493
|
reconnecting = true;
|
|
@@ -530,6 +540,9 @@ async function handleDaemon(projectsDir) {
|
|
|
530
540
|
}, PONG_TIMEOUT_MS);
|
|
531
541
|
}
|
|
532
542
|
}, PING_INTERVAL_MS);
|
|
543
|
+
|
|
544
|
+
// Start expecting server heartbeats (more reliable than WS pings through proxies)
|
|
545
|
+
resetHeartbeatTimer(sock);
|
|
533
546
|
});
|
|
534
547
|
|
|
535
548
|
sock.on("pong", () => {
|
|
@@ -540,6 +553,11 @@ async function handleDaemon(projectsDir) {
|
|
|
540
553
|
let msg;
|
|
541
554
|
try { msg = JSON.parse(raw.toString()); } catch { return; }
|
|
542
555
|
|
|
556
|
+
if (msg.type === "heartbeat") {
|
|
557
|
+
resetHeartbeatTimer(sock);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
|
|
543
561
|
if (msg.type === "error") {
|
|
544
562
|
process.stderr.write(`${RED}${PREFIX} Server: ${msg.error}${RESET}\n`);
|
|
545
563
|
if (/unauthorized|auth|token/i.test(msg.error || "")) {
|
|
@@ -647,6 +665,7 @@ async function handleDaemon(projectsDir) {
|
|
|
647
665
|
if (ws === sock) ws = null;
|
|
648
666
|
if (pingTimer) { clearInterval(pingTimer); pingTimer = null; }
|
|
649
667
|
if (pongTimer) { clearTimeout(pongTimer); pongTimer = null; }
|
|
668
|
+
if (heartbeatTimer) { clearTimeout(heartbeatTimer); heartbeatTimer = null; }
|
|
650
669
|
process.stderr.write(`${DIM}${PREFIX} Disconnected — reconnecting in 2s${RESET}\n`);
|
|
651
670
|
scheduleReconnect(2);
|
|
652
671
|
});
|
|
@@ -663,6 +682,7 @@ async function handleDaemon(projectsDir) {
|
|
|
663
682
|
process.stderr.write(`\n${DIM}${PREFIX} Shutting down${RESET}\n`);
|
|
664
683
|
if (pingTimer) clearInterval(pingTimer);
|
|
665
684
|
if (pongTimer) clearTimeout(pongTimer);
|
|
685
|
+
if (heartbeatTimer) clearTimeout(heartbeatTimer);
|
|
666
686
|
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
667
687
|
if (ws) ws.close();
|
|
668
688
|
process.exit(0);
|