channel-worker 2.1.4 → 2.1.5

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.
@@ -1177,16 +1177,17 @@ class CommandPoller {
1177
1177
  } catch {}
1178
1178
  }
1179
1179
 
1180
- // 3b. Running profiles with stale heartbeat + commands → extension stuck, close + reset + relaunch
1181
- const HEARTBEAT_STALE = 90 * 1000; // 90s
1180
+ // 3b. Running profiles with stale heartbeat + PENDING commands → extension never started
1181
+ // Only restart if commands are still "pending" (not "running" = extension picked up but busy)
1182
+ const HEARTBEAT_STALE = 3 * 60 * 1000; // 3 minutes (extension can be busy rendering for 5+ min)
1182
1183
  const now = Date.now();
1183
1184
  for (const r of [...runningRenderers]) {
1184
1185
  try {
1186
+ // Only check profiles that have pending commands (not running = actively processing)
1185
1187
  const cmdCount = await this.api.rendererHasCommands(r.nst_profile_id);
1186
1188
  if (cmdCount === 0) continue;
1187
1189
  const hb = r.last_heartbeat ? new Date(r.last_heartbeat).getTime() : 0;
1188
- if (hb && (now - hb) < HEARTBEAT_STALE) continue; // heartbeat fresh, extension alive
1189
- // Stale heartbeat + has commands → extension stuck
1190
+ if (hb && (now - hb) < HEARTBEAT_STALE) continue;
1190
1191
  console.log(`[scene-dispatch] Stuck: ${r.name} running but heartbeat stale (${hb ? Math.round((now - hb) / 1000) + 's' : 'never'}) — restarting`);
1191
1192
  try {
1192
1193
  await this.nst.stopProfile(r.nst_profile_id).catch(() => {});
@@ -1203,13 +1204,14 @@ class CommandPoller {
1203
1204
  const queueCount = await this.api.getSceneQueueCount();
1204
1205
  if (!queueCount) { this._dispatching = false; return; }
1205
1206
 
1206
- // 5. Launch new profiles up to parallel limit
1207
+ // 5. Launch new profiles up to parallel limit (recompute offline after recovery)
1207
1208
  const parallelLimit = parseInt(await this.api.getSetting('veo3_parallel_limit')) || 1;
1208
- console.log(`[scene-dispatch] running=${runningRenderers.length}/${parallelLimit} offline=${offlineRenderers.length} queue=${queueCount} names=[${runningRenderers.map(r=>r.name)}]`);
1209
+ const stillOffline = renderers.filter(r => !runningRenderers.includes(r));
1210
+ console.log(`[scene-dispatch] running=${runningRenderers.length}/${parallelLimit} offline=${stillOffline.length} queue=${queueCount} names=[${runningRenderers.map(r=>r.name)}]`);
1209
1211
 
1210
- const neededLaunches = Math.min(parallelLimit - runningRenderers.length, offlineRenderers.length, queueCount);
1212
+ const neededLaunches = Math.min(parallelLimit - runningRenderers.length, stillOffline.length, queueCount);
1211
1213
  for (let li = 0; li < neededLaunches; li++) {
1212
- const toLaunch = offlineRenderers[li];
1214
+ const toLaunch = stillOffline[li];
1213
1215
  console.log(`[scene-dispatch] Launching ${toLaunch.name} (running: ${runningRenderers.length + li}/${parallelLimit})`);
1214
1216
  try {
1215
1217
  await this._launchRendererProfile(toLaunch);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "Channel Manager worker daemon — runs on remote machines to execute video pipeline jobs",
5
5
  "main": "lib/daemon.js",
6
6
  "bin": {