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 +7 -0
- package/lib/command-poller.js +36 -16
- package/package.json +1 -1
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');
|
package/lib/command-poller.js
CHANGED
|
@@ -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.
|
|
1317
|
-
//
|
|
1318
|
-
//
|
|
1319
|
-
//
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
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.
|
|
1431
|
-
|
|
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
|
-
//
|
|
1437
|
-
//
|
|
1438
|
-
|
|
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
|
}
|