channel-worker 2.2.0 → 2.2.2
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/lib/command-poller.js +14 -5
- package/package.json +1 -1
package/lib/command-poller.js
CHANGED
|
@@ -1169,6 +1169,7 @@ class CommandPoller {
|
|
|
1169
1169
|
await this.api.resetRendererCommands(r.nst_profile_id);
|
|
1170
1170
|
await this._launchRendererProfile(r);
|
|
1171
1171
|
runningRenderers.push(r);
|
|
1172
|
+
this._profileLastActivity[r.nst_profile_id] = Date.now();
|
|
1172
1173
|
console.log(`[scene-dispatch] ${r.name} recovered (${cmdCount} commands reset)`);
|
|
1173
1174
|
} catch (err) {
|
|
1174
1175
|
console.error(`[scene-dispatch] Failed to recover ${r.name}: ${err.message}`);
|
|
@@ -1179,19 +1180,24 @@ class CommandPoller {
|
|
|
1179
1180
|
|
|
1180
1181
|
// 3b. Running profiles with stale heartbeat + PENDING commands → extension never started
|
|
1181
1182
|
// Only restart if commands are still "pending" (not "running" = extension picked up but busy)
|
|
1182
|
-
const HEARTBEAT_STALE =
|
|
1183
|
+
const HEARTBEAT_STALE = 60 * 1000; // 60s — extension heartbeats every 15s
|
|
1184
|
+
const LAUNCH_GRACE = 60 * 1000; // 60s grace period after launch for extension to init
|
|
1183
1185
|
const now = Date.now();
|
|
1184
1186
|
for (const r of [...runningRenderers]) {
|
|
1185
1187
|
try {
|
|
1186
|
-
// Only check profiles that have pending commands (not running = actively processing)
|
|
1187
1188
|
const cmdCount = await this.api.rendererHasCommands(r.nst_profile_id);
|
|
1188
1189
|
if (cmdCount === 0) continue;
|
|
1190
|
+
// Skip if recently launched (grace period for extension to init + first heartbeat)
|
|
1191
|
+
const lastLaunch = this._profileLastActivity[r.nst_profile_id] || 0;
|
|
1192
|
+
if (lastLaunch && (now - lastLaunch) < LAUNCH_GRACE) continue;
|
|
1189
1193
|
const hb = r.last_heartbeat ? new Date(r.last_heartbeat).getTime() : 0;
|
|
1190
|
-
if (hb && (now - hb) < HEARTBEAT_STALE) continue;
|
|
1194
|
+
if (hb && (now - hb) < HEARTBEAT_STALE) continue; // heartbeat fresh
|
|
1195
|
+
if (!hb && lastLaunch) continue; // never heartbeated but recently tracked — still in grace
|
|
1191
1196
|
console.log(`[scene-dispatch] Stuck: ${r.name} running but heartbeat stale (${hb ? Math.round((now - hb) / 1000) + 's' : 'never'}) — restarting`);
|
|
1192
1197
|
try {
|
|
1193
1198
|
await this.api.resetRendererCommands(r.nst_profile_id);
|
|
1194
1199
|
await this._launchRendererProfile(r, { forceRelaunch: true });
|
|
1200
|
+
this._profileLastActivity[r.nst_profile_id] = Date.now();
|
|
1195
1201
|
console.log(`[scene-dispatch] ${r.name} restarted`);
|
|
1196
1202
|
} catch (err) {
|
|
1197
1203
|
console.error(`[scene-dispatch] Failed to restart ${r.name}: ${err.message}`);
|
|
@@ -1208,13 +1214,16 @@ class CommandPoller {
|
|
|
1208
1214
|
const stillOffline = renderers.filter(r => !runningRenderers.includes(r));
|
|
1209
1215
|
console.log(`[scene-dispatch] running=${runningRenderers.length}/${parallelLimit} offline=${stillOffline.length} queue=${queueCount} names=[${runningRenderers.map(r=>r.name)}]`);
|
|
1210
1216
|
|
|
1211
|
-
|
|
1217
|
+
// Only launch if queue has more work than running profiles can handle
|
|
1218
|
+
const freeSlots = Math.max(0, queueCount - runningRenderers.length);
|
|
1219
|
+
const neededLaunches = Math.min(parallelLimit - runningRenderers.length, stillOffline.length, freeSlots);
|
|
1212
1220
|
for (let li = 0; li < neededLaunches; li++) {
|
|
1213
1221
|
const toLaunch = stillOffline[li];
|
|
1214
1222
|
console.log(`[scene-dispatch] Launching ${toLaunch.name} (running: ${runningRenderers.length + li}/${parallelLimit})`);
|
|
1215
1223
|
try {
|
|
1216
1224
|
await this._launchRendererProfile(toLaunch);
|
|
1217
|
-
runningRenderers.push(toLaunch);
|
|
1225
|
+
runningRenderers.push(toLaunch);
|
|
1226
|
+
this._profileLastActivity[toLaunch.nst_profile_id] = Date.now();
|
|
1218
1227
|
console.log(`[scene-dispatch] ${toLaunch.name} launched`);
|
|
1219
1228
|
} catch (err) {
|
|
1220
1229
|
console.error(`[scene-dispatch] Failed to launch ${toLaunch.name}: ${err.message}`);
|