channel-worker 2.1.4 → 2.1.6
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 +13 -12
- package/lib/nst-manager.js +12 -2
- package/package.json +1 -1
package/lib/command-poller.js
CHANGED
|
@@ -1177,21 +1177,21 @@ class CommandPoller {
|
|
|
1177
1177
|
} catch {}
|
|
1178
1178
|
}
|
|
1179
1179
|
|
|
1180
|
-
// 3b. Running profiles with stale heartbeat + commands → extension
|
|
1181
|
-
|
|
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;
|
|
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
|
-
await this.nst.stopProfile(r.nst_profile_id).catch(() => {});
|
|
1193
1193
|
await this.api.resetRendererCommands(r.nst_profile_id);
|
|
1194
|
-
await this._launchRendererProfile(r);
|
|
1194
|
+
await this._launchRendererProfile(r, { forceRelaunch: true });
|
|
1195
1195
|
console.log(`[scene-dispatch] ${r.name} restarted`);
|
|
1196
1196
|
} catch (err) {
|
|
1197
1197
|
console.error(`[scene-dispatch] Failed to restart ${r.name}: ${err.message}`);
|
|
@@ -1203,13 +1203,14 @@ class CommandPoller {
|
|
|
1203
1203
|
const queueCount = await this.api.getSceneQueueCount();
|
|
1204
1204
|
if (!queueCount) { this._dispatching = false; return; }
|
|
1205
1205
|
|
|
1206
|
-
// 5. Launch new profiles up to parallel limit
|
|
1206
|
+
// 5. Launch new profiles up to parallel limit (recompute offline after recovery)
|
|
1207
1207
|
const parallelLimit = parseInt(await this.api.getSetting('veo3_parallel_limit')) || 1;
|
|
1208
|
-
|
|
1208
|
+
const stillOffline = renderers.filter(r => !runningRenderers.includes(r));
|
|
1209
|
+
console.log(`[scene-dispatch] running=${runningRenderers.length}/${parallelLimit} offline=${stillOffline.length} queue=${queueCount} names=[${runningRenderers.map(r=>r.name)}]`);
|
|
1209
1210
|
|
|
1210
|
-
const neededLaunches = Math.min(parallelLimit - runningRenderers.length,
|
|
1211
|
+
const neededLaunches = Math.min(parallelLimit - runningRenderers.length, stillOffline.length, queueCount);
|
|
1211
1212
|
for (let li = 0; li < neededLaunches; li++) {
|
|
1212
|
-
const toLaunch =
|
|
1213
|
+
const toLaunch = stillOffline[li];
|
|
1213
1214
|
console.log(`[scene-dispatch] Launching ${toLaunch.name} (running: ${runningRenderers.length + li}/${parallelLimit})`);
|
|
1214
1215
|
try {
|
|
1215
1216
|
await this._launchRendererProfile(toLaunch);
|
|
@@ -1243,7 +1244,7 @@ class CommandPoller {
|
|
|
1243
1244
|
this._dispatching = false;
|
|
1244
1245
|
}
|
|
1245
1246
|
|
|
1246
|
-
async _launchRendererProfile(renderer) {
|
|
1247
|
+
async _launchRendererProfile(renderer, options = {}) {
|
|
1247
1248
|
await this.nst.ensureProfile(renderer.nst_profile_id, { os: renderer.os || 'windows', proxy: renderer.proxy || null });
|
|
1248
1249
|
|
|
1249
1250
|
const path = require('path');
|
|
@@ -1278,7 +1279,7 @@ class CommandPoller {
|
|
|
1278
1279
|
console.warn(`[scene-dispatch] Ext dir failed: ${e.message}, using base`);
|
|
1279
1280
|
}
|
|
1280
1281
|
|
|
1281
|
-
await this.nst.launchProfile(renderer.nst_profile_id, { proxy: renderer.proxy || null, extensionPath });
|
|
1282
|
+
await this.nst.launchProfile(renderer.nst_profile_id, { proxy: renderer.proxy || null, extensionPath, forceRelaunch: options.forceRelaunch });
|
|
1282
1283
|
}
|
|
1283
1284
|
|
|
1284
1285
|
// ─── Profile Timeout ───────────────────────────────────────────────────────
|
package/lib/nst-manager.js
CHANGED
|
@@ -153,8 +153,18 @@ class NstManager {
|
|
|
153
153
|
console.log(`[nst] Running browsers: ${running.map(b => b.name || b.profileId).join(', ') || 'none'}`);
|
|
154
154
|
const isRunning = running.some(b => b.profileId === profileId);
|
|
155
155
|
if (isRunning) {
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
if (options.forceRelaunch) {
|
|
157
|
+
console.log(`[nst] Profile ${profileId} already running — force stopping for relaunch`);
|
|
158
|
+
try {
|
|
159
|
+
await this.stopProfile(profileId);
|
|
160
|
+
await new Promise(r => setTimeout(r, 3000));
|
|
161
|
+
} catch (e) {
|
|
162
|
+
console.warn(`[nst] Stop failed: ${e.message}`);
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
console.log(`[nst] Profile ${profileId} already running — skipping launch`);
|
|
166
|
+
return { profileId, alreadyRunning: true };
|
|
167
|
+
}
|
|
158
168
|
}
|
|
159
169
|
|
|
160
170
|
// Update profile language to en-US (Custom) before launch
|