channel-worker 2.0.2 → 2.1.0
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 +71 -48
- package/package.json +1 -1
package/lib/command-poller.js
CHANGED
|
@@ -334,6 +334,19 @@ class CommandPoller {
|
|
|
334
334
|
else if (fs.statSync(src).isDirectory()) fs.cpSync(src, dest, { recursive: true });
|
|
335
335
|
}
|
|
336
336
|
console.log(`[commands] CC extension downloaded to ${extPath}`);
|
|
337
|
+
|
|
338
|
+
// Close running profiles so they reload with new extension on next launch
|
|
339
|
+
if (this.nst) {
|
|
340
|
+
try {
|
|
341
|
+
const running = await this.nst.getRunningBrowsers();
|
|
342
|
+
if (running.length > 0) {
|
|
343
|
+
console.log(`[commands] Closing ${running.length} running profiles to reload extension...`);
|
|
344
|
+
for (const b of running) {
|
|
345
|
+
try { await this.nst.stopProfile(b.profileId); } catch {}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
} catch {}
|
|
349
|
+
}
|
|
337
350
|
} finally {
|
|
338
351
|
try { fs.unlinkSync(tmpArchive); } catch {}
|
|
339
352
|
try { fs.rmSync(tmpExtract, { recursive: true, force: true }); } catch {}
|
|
@@ -1153,66 +1166,38 @@ class CommandPoller {
|
|
|
1153
1166
|
});
|
|
1154
1167
|
const offlineRenderers = renderers.filter(r => !runningRenderers.includes(r));
|
|
1155
1168
|
|
|
1156
|
-
// 6.
|
|
1157
|
-
let target = null;
|
|
1169
|
+
// 6. Launch profiles up to parallel limit
|
|
1158
1170
|
console.log(`[scene-dispatch] running=${runningRenderers.length}/${parallelLimit} offline=${offlineRenderers.length} queue=${queueCount} names=[${runningRenderers.map(r=>r.name)}]`);
|
|
1159
1171
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
console.log(`[scene-dispatch] Launching ${
|
|
1172
|
+
const neededLaunches = Math.min(parallelLimit - runningRenderers.length, offlineRenderers.length, queueCount);
|
|
1173
|
+
for (let li = 0; li < neededLaunches; li++) {
|
|
1174
|
+
const toLaunch = offlineRenderers[li];
|
|
1175
|
+
console.log(`[scene-dispatch] Launching ${toLaunch.name} (running: ${runningRenderers.length + li}/${parallelLimit})`);
|
|
1164
1176
|
try {
|
|
1165
|
-
await this.
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
const os_mod = require('os');
|
|
1169
|
-
const defaultCCExtPath = path.join(os_mod.homedir(), 'content-creator-ext');
|
|
1170
|
-
const baseExtPath = this.config.content_creator_ext_path || defaultCCExtPath;
|
|
1171
|
-
await this._ensureContentCreatorExt(baseExtPath);
|
|
1172
|
-
|
|
1173
|
-
// Create unique ext dir per profile
|
|
1174
|
-
let extensionPath = baseExtPath;
|
|
1175
|
-
const fs = require('fs');
|
|
1176
|
-
const uniqueExtPath = baseExtPath + '-' + target.nst_profile_id;
|
|
1177
|
-
try {
|
|
1178
|
-
if (fs.existsSync(uniqueExtPath)) fs.rmSync(uniqueExtPath, { recursive: true });
|
|
1179
|
-
fs.mkdirSync(uniqueExtPath, { recursive: true });
|
|
1180
|
-
fs.cpSync(baseExtPath, uniqueExtPath, { recursive: true });
|
|
1181
|
-
fs.writeFileSync(path.join(uniqueExtPath, 'config.json'), JSON.stringify({
|
|
1182
|
-
channelManagerApi: this.api.baseUrl,
|
|
1183
|
-
profileId: target.nst_profile_id,
|
|
1184
|
-
workerToken: this.config.worker_token || '',
|
|
1185
|
-
workerType: 'veo3',
|
|
1186
|
-
}));
|
|
1187
|
-
extensionPath = uniqueExtPath;
|
|
1188
|
-
} catch (e) {
|
|
1189
|
-
console.warn(`[scene-dispatch] Ext dir failed: ${e.message}, using base`);
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
await this.nst.launchProfile(target.nst_profile_id, { proxy: target.proxy || null, extensionPath });
|
|
1193
|
-
console.log(`[scene-dispatch] ${target.name} launched`);
|
|
1177
|
+
await this._launchRendererProfile(toLaunch);
|
|
1178
|
+
runningRenderers.push(toLaunch); // now considered running
|
|
1179
|
+
console.log(`[scene-dispatch] ${toLaunch.name} launched`);
|
|
1194
1180
|
} catch (err) {
|
|
1195
|
-
console.error(`[scene-dispatch] Failed to launch ${
|
|
1196
|
-
target = runningRenderers[0] || null; // fallback to running
|
|
1181
|
+
console.error(`[scene-dispatch] Failed to launch ${toLaunch.name}: ${err.message}`);
|
|
1197
1182
|
}
|
|
1198
1183
|
}
|
|
1199
1184
|
|
|
1200
|
-
|
|
1201
|
-
if (!target && runningRenderers.length > 0) {
|
|
1202
|
-
target = runningRenderers[0]; // extension processes commands sequentially per profile
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
if (!target) {
|
|
1206
|
-
// No renderers available at all — wait for next cycle
|
|
1185
|
+
if (runningRenderers.length === 0) {
|
|
1207
1186
|
this._dispatching = false;
|
|
1208
1187
|
return;
|
|
1209
1188
|
}
|
|
1210
1189
|
|
|
1211
|
-
// 7.
|
|
1212
|
-
|
|
1213
|
-
|
|
1190
|
+
// 7. Assign queued commands round-robin across running renderers
|
|
1191
|
+
let assigned = 0;
|
|
1192
|
+
for (let qi = 0; qi < queueCount; qi++) {
|
|
1193
|
+
const target = runningRenderers[qi % runningRenderers.length];
|
|
1194
|
+
const cmd = await this.api.sceneDispatch(target.nst_profile_id);
|
|
1195
|
+
if (!cmd) break; // queue empty
|
|
1214
1196
|
this._profileLastActivity[target.nst_profile_id] = Date.now();
|
|
1215
|
-
|
|
1197
|
+
assigned++;
|
|
1198
|
+
}
|
|
1199
|
+
if (assigned > 0) {
|
|
1200
|
+
console.log(`[scene-dispatch] Assigned ${assigned} commands across ${runningRenderers.length} renderers`);
|
|
1216
1201
|
}
|
|
1217
1202
|
} catch (err) {
|
|
1218
1203
|
console.error(`[scene-dispatch] Error: ${err.message}`);
|
|
@@ -1220,6 +1205,44 @@ class CommandPoller {
|
|
|
1220
1205
|
this._dispatching = false;
|
|
1221
1206
|
}
|
|
1222
1207
|
|
|
1208
|
+
async _launchRendererProfile(renderer) {
|
|
1209
|
+
await this.nst.ensureProfile(renderer.nst_profile_id, { os: renderer.os || 'windows', proxy: renderer.proxy || null });
|
|
1210
|
+
|
|
1211
|
+
const path = require('path');
|
|
1212
|
+
const os_mod = require('os');
|
|
1213
|
+
const fs = require('fs');
|
|
1214
|
+
const defaultCCExtPath = path.join(os_mod.homedir(), 'content-creator-ext');
|
|
1215
|
+
const baseExtPath = this.config.content_creator_ext_path || defaultCCExtPath;
|
|
1216
|
+
await this._ensureContentCreatorExt(baseExtPath);
|
|
1217
|
+
|
|
1218
|
+
let extensionPath = baseExtPath;
|
|
1219
|
+
const extVersion = (() => { try { return JSON.parse(fs.readFileSync(path.join(baseExtPath, 'manifest.json'), 'utf8')).version; } catch { return '0'; } })();
|
|
1220
|
+
const uniqueExtPath = baseExtPath + '-' + renderer.nst_profile_id + '-v' + extVersion;
|
|
1221
|
+
try {
|
|
1222
|
+
const parent = path.dirname(baseExtPath);
|
|
1223
|
+
const prefix = path.basename(baseExtPath) + '-' + renderer.nst_profile_id;
|
|
1224
|
+
try {
|
|
1225
|
+
fs.readdirSync(parent)
|
|
1226
|
+
.filter(d => d.startsWith(prefix) && d !== path.basename(uniqueExtPath))
|
|
1227
|
+
.forEach(d => { try { fs.rmSync(path.join(parent, d), { recursive: true }); } catch {} });
|
|
1228
|
+
} catch {}
|
|
1229
|
+
if (fs.existsSync(uniqueExtPath)) fs.rmSync(uniqueExtPath, { recursive: true });
|
|
1230
|
+
fs.mkdirSync(uniqueExtPath, { recursive: true });
|
|
1231
|
+
fs.cpSync(baseExtPath, uniqueExtPath, { recursive: true });
|
|
1232
|
+
fs.writeFileSync(path.join(uniqueExtPath, 'config.json'), JSON.stringify({
|
|
1233
|
+
channelManagerApi: this.api.baseUrl,
|
|
1234
|
+
profileId: renderer.nst_profile_id,
|
|
1235
|
+
workerToken: this.config.worker_token || '',
|
|
1236
|
+
workerType: 'veo3',
|
|
1237
|
+
}));
|
|
1238
|
+
extensionPath = uniqueExtPath;
|
|
1239
|
+
} catch (e) {
|
|
1240
|
+
console.warn(`[scene-dispatch] Ext dir failed: ${e.message}, using base`);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
await this.nst.launchProfile(renderer.nst_profile_id, { proxy: renderer.proxy || null, extensionPath });
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1223
1246
|
// ─── Profile Timeout ───────────────────────────────────────────────────────
|
|
1224
1247
|
// Close profiles that have been idle (no commands assigned) for too long.
|
|
1225
1248
|
|