channel-worker 2.5.0 → 2.5.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/api-client.js CHANGED
@@ -84,6 +84,13 @@ class ApiClient {
84
84
  return this.request('POST', `/extension/commands/${commandId}/result`, { status, result: result || {}, error: error || null });
85
85
  }
86
86
 
87
+ // Return the calling daemon's own Worker doc — primarily for reading
88
+ // parallel_limit (the per-daemon scene-generation concurrency cap that
89
+ // replaced the legacy global flowkit_max_concurrent setting).
90
+ async getMyWorker() {
91
+ return this.request('GET', '/workers/me');
92
+ }
93
+
87
94
  // Scene dispatch
88
95
  async getRenderers() {
89
96
  return this.request('GET', '/workers/renderers');
@@ -1313,16 +1313,29 @@ class CommandPoller {
1313
1313
  const domQ = typeof queueInfo === 'number' ? queueCount : (queueInfo?.dom_count || 0);
1314
1314
  if (!queueCount) { this._dispatching = false; return; }
1315
1315
 
1316
- // 5. Pick the right parallel limit based on queue composition
1317
- // - queue toàn flowkit → dùng flowkit_max_concurrent
1318
- // - queue toàn DOM → dùng veo3_parallel_limit
1319
- // - mixed (hiếm) → dùng max của 2 để không bottleneck nhánh nào
1320
- const flowkitLimit = parseInt(await this.api.getSetting('flowkit_max_concurrent')) || 5;
1321
- const veo3Limit = parseInt(await this.api.getSetting('veo3_parallel_limit')) || 1;
1322
- let parallelLimit;
1323
- if (flowkitQ > 0 && domQ === 0) parallelLimit = flowkitLimit;
1324
- else if (domQ > 0 && flowkitQ === 0) parallelLimit = veo3Limit;
1325
- else parallelLimit = Math.max(flowkitLimit, veo3Limit);
1316
+ // 5. Parallel limit sourced from THIS daemon's Worker.parallel_limit
1317
+ // via /workers/me. Replaces the legacy global Settings
1318
+ // (flowkit_max_concurrent / veo3_parallel_limit) which throttled
1319
+ // across all daemons of a user making multi-machine setup
1320
+ // impossible to scale (set global=1 only one machine runs at a
1321
+ // time). Server-side enforcement in /scene-dispatch +
1322
+ // /flowkit/claim-command uses the same field, so a daemon trying
1323
+ // to over-launch profiles will simply get yielded responses on
1324
+ // overflow. We still cap launches here to avoid keeping idle
1325
+ // profiles open (each NST profile holds RAM + a Chromium tab).
1326
+ let parallelLimit = 2; // sane default if /workers/me fails or is
1327
+ // unavailable on an older API; effective limit
1328
+ // is still bounded by server-side enforcement.
1329
+ try {
1330
+ if (this.api.getMyWorker) {
1331
+ const me = await this.api.getMyWorker();
1332
+ if (me && typeof me.parallel_limit === 'number') {
1333
+ parallelLimit = Math.max(0, me.parallel_limit);
1334
+ }
1335
+ }
1336
+ } catch (e) {
1337
+ if (this.config.verbose) console.warn('[scene-dispatch] getMyWorker failed, using default:', e.message);
1338
+ }
1326
1339
  const stillOffline = renderers.filter(r => !runningRenderers.includes(r));
1327
1340
  console.log(`[scene-dispatch] running=${runningRenderers.length}/${parallelLimit} (flowkit=${flowkitQ} dom=${domQ}) offline=${stillOffline.length} queue=${queueCount} names=[${runningRenderers.map(r=>r.name)}]`);
1328
1341
 
@@ -1425,17 +1438,24 @@ class CommandPoller {
1425
1438
  // two daemons would happily double-launch and corrupt cookies / kill
1426
1439
  // sessions for the underlying Google/FB accounts.
1427
1440
  if (renderer.nst_profile_id && this.api.leaseRenderer) {
1441
+ // api.leaseRenderer returns json.data on success (a {nst_profile_id,
1442
+ // leased_at, lessee} envelope) and THROWS on success=false. So:
1443
+ // - throw → another daemon holds the lease OR API rejected → skip
1444
+ // - return → lease acquired → proceed with NST launch
1445
+ // Previous bug: checked `leaseRes.success !== true` but `.success` is
1446
+ // already stripped from json.data → always falsy → every launch was
1447
+ // wrongfully denied with reason="unknown".
1428
1448
  try {
1429
1449
  const leaseRes = await this.api.leaseRenderer(renderer.nst_profile_id);
1430
- if (!leaseRes || leaseRes.success !== true) {
1431
- const reason = leaseRes && leaseRes.message ? leaseRes.message : 'unknown';
1432
- console.warn(`[scene-dispatch] LEASE DENIED for ${renderer.name || renderer.nst_profile_id}: ${reason} — skipping launch`);
1450
+ if (!leaseRes || !leaseRes.nst_profile_id) {
1451
+ console.warn(`[scene-dispatch] lease returned no data for ${renderer.name || renderer.nst_profile_id} skipping launch (API may be older)`);
1433
1452
  return;
1434
1453
  }
1435
1454
  } catch (e) {
1436
- // Treat lease failure as a soft block the API might be down OR
1437
- // running an older version. Better to skip than risk double-launch.
1438
- console.warn(`[scene-dispatch] lease request failed for ${renderer.name || renderer.nst_profile_id}: ${e.message} — skipping launch`);
1455
+ // Either API said success=false (lease held by peer / unowned /
1456
+ // stale rules failed) OR network failure. Either way, do NOT
1457
+ // launch better idle than collision.
1458
+ console.warn(`[scene-dispatch] LEASE DENIED for ${renderer.name || renderer.nst_profile_id}: ${e.message} — skipping launch`);
1439
1459
  return;
1440
1460
  }
1441
1461
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "2.5.0",
3
+ "version": "2.5.2",
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": {