@camstack/addon-pipeline 1.2.186 → 1.2.187
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/dist/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/detection-pipeline/index.js +5 -5
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-yaetDPpW.mjs → dist-HWdaHLLK.mjs} +21 -0
- package/dist/{dist-CiVhPNTB.js → dist-e2OKAUGI.js} +21 -0
- package/dist/{lazy-sharp-D1PX1Psd.js → lazy-sharp-AJ7newgl.js} +1 -1
- package/dist/{local-frame-registry-CANBpRSg.mjs → local-frame-registry-Bki81rM0.mjs} +1 -1
- package/dist/{local-frame-registry-D5d1W1Vf.js → local-frame-registry-Cl1VUpx_.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-CCRb0fqW.mjs → node-CwSBH-3M.mjs} +1 -1
- package/dist/{node-DGzZLg-c.js → node-Dw6FrDFS.js} +1 -1
- package/dist/pipeline-runner/index.js +166 -10
- package/dist/pipeline-runner/index.mjs +165 -9
- package/dist/{process-memory-BIy4e_mZ.mjs → process-memory-CnTmyk9s.mjs} +1 -1
- package/dist/{process-memory-C7f66zUT.js → process-memory-einpgBTr.js} +1 -1
- package/dist/recorder/index.js +2 -2
- package/dist/recorder/index.mjs +2 -2
- package/dist/{segment-demux-js-CViDx3UC.mjs → segment-demux-js-CuNHMubE.mjs} +1 -1
- package/dist/{segment-demux-js-CnqYsNPt.js → segment-demux-js-CyCdXcFZ.js} +1 -1
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CR6bzoE5.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CWa6ONcK.mjs} +3 -3
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BC-nahrU.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-D5XwN-xi.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-DgDPe3HR.mjs → hostInit-DUqxWCSo.mjs} +3 -3
- package/dist/stream-broker/index.js +70 -48
- package/dist/stream-broker/index.mjs +70 -48
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-Db6BWHr-.js → worker-protocol-Bva8nEZO.js} +1 -1
- package/dist/{worker-protocol-BcKW7xgG.mjs → worker-protocol-DN1y2Vyk.mjs} +1 -1
- package/package.json +1 -1
|
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_process_memory = require("../process-memory-
|
|
5
|
+
const require_dist = require("../dist-e2OKAUGI.js");
|
|
6
|
+
const require_process_memory = require("../process-memory-einpgBTr.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_dist.__toESM(node_fs);
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-
|
|
3
|
-
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-
|
|
2
|
+
import { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-HWdaHLLK.mjs";
|
|
3
|
+
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-CnTmyk9s.mjs";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as path$1 from "node:path";
|
|
6
6
|
import { downloadFile } from "@camstack/system/addon-utils";
|
|
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_node = require("../node-
|
|
7
|
-
const require_local_frame_registry = require("../local-frame-registry-
|
|
8
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
5
|
+
const require_dist = require("../dist-e2OKAUGI.js");
|
|
6
|
+
const require_node = require("../node-Dw6FrDFS.js");
|
|
7
|
+
const require_local_frame_registry = require("../local-frame-registry-Cl1VUpx_.js");
|
|
8
|
+
const require_lazy_sharp = require("../lazy-sharp-AJ7newgl.js");
|
|
9
9
|
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
|
|
10
|
-
const require_process_memory = require("../process-memory-
|
|
10
|
+
const require_process_memory = require("../process-memory-einpgBTr.js");
|
|
11
11
|
let node_fs = require("node:fs");
|
|
12
12
|
node_fs = require_dist.__toESM(node_fs);
|
|
13
13
|
let node_path = require("node:path");
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-
|
|
3
|
-
import { a as readProcessCost } from "../node-
|
|
4
|
-
import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-
|
|
2
|
+
import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-HWdaHLLK.mjs";
|
|
3
|
+
import { a as readProcessCost } from "../node-CwSBH-3M.mjs";
|
|
4
|
+
import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-Bki81rM0.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
6
6
|
import { n as startEventLoopStallMonitor } from "../event-loop-stall-monitor-DXLNBMkY.mjs";
|
|
7
|
-
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-
|
|
7
|
+
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-CnTmyk9s.mjs";
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import * as path$1 from "node:path";
|
|
10
10
|
import { dirname, join } from "node:path";
|
|
@@ -22996,6 +22996,14 @@ var AgentPipelineSettingsSchema = object({
|
|
|
22996
22996
|
/** Node is eligible to be the ingest / source-owner (serve the restream). */
|
|
22997
22997
|
ingest: boolean().optional(),
|
|
22998
22998
|
/**
|
|
22999
|
+
* This node's decode RAM budget, MB. Wins over the cluster
|
|
23000
|
+
* `nodeDecodeBudgetMb`; absent, the runner derives a share of the node's
|
|
23001
|
+
* own RAM unless the operator moved the cluster value (D365).
|
|
23002
|
+
*/
|
|
23003
|
+
decodeBudgetMb: number().int().min(1024).max(65536).optional(),
|
|
23004
|
+
/** This node's live decode-worker cap. Wins over the cluster `maxLiveDecodeWorkers`. */
|
|
23005
|
+
maxLiveDecodeWorkers: number().int().min(1).max(32).optional(),
|
|
23006
|
+
/**
|
|
22999
23007
|
* Operator override for the LAN host a cross-node decoder dials to reach
|
|
23000
23008
|
* THIS node's restream (Cluster UI). Absent → auto-detect: a remote runner
|
|
23001
23009
|
* falls back to its `CAMSTACK_HUB_URL`-derived host (the Moleculer address
|
|
@@ -23457,6 +23465,13 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
23457
23465
|
}), object({ success: literal(true) }), {
|
|
23458
23466
|
kind: "mutation",
|
|
23459
23467
|
auth: "admin"
|
|
23468
|
+
}), method(object({
|
|
23469
|
+
agentNodeId: string(),
|
|
23470
|
+
decodeBudgetMb: number().int().min(1024).max(65536).nullable().optional(),
|
|
23471
|
+
maxLiveDecodeWorkers: number().int().min(1).max(32).nullable().optional()
|
|
23472
|
+
}), object({ success: literal(true) }), {
|
|
23473
|
+
kind: "mutation",
|
|
23474
|
+
auth: "admin"
|
|
23460
23475
|
}), method(object({
|
|
23461
23476
|
agentNodeId: string(),
|
|
23462
23477
|
reachableHost: string().nullable()
|
|
@@ -36190,6 +36205,12 @@ Object.freeze({
|
|
|
36190
36205
|
addonId: null,
|
|
36191
36206
|
access: "create"
|
|
36192
36207
|
},
|
|
36208
|
+
"pipelineOrchestrator.setAgentDecodeLimits": {
|
|
36209
|
+
capName: "pipeline-orchestrator",
|
|
36210
|
+
capScope: "system",
|
|
36211
|
+
addonId: null,
|
|
36212
|
+
access: "create"
|
|
36213
|
+
},
|
|
36193
36214
|
"pipelineOrchestrator.setAgentDetectWeight": {
|
|
36194
36215
|
capName: "pipeline-orchestrator",
|
|
36195
36216
|
capScope: "system",
|
|
@@ -23019,6 +23019,14 @@ var AgentPipelineSettingsSchema = object({
|
|
|
23019
23019
|
/** Node is eligible to be the ingest / source-owner (serve the restream). */
|
|
23020
23020
|
ingest: boolean().optional(),
|
|
23021
23021
|
/**
|
|
23022
|
+
* This node's decode RAM budget, MB. Wins over the cluster
|
|
23023
|
+
* `nodeDecodeBudgetMb`; absent, the runner derives a share of the node's
|
|
23024
|
+
* own RAM unless the operator moved the cluster value (D365).
|
|
23025
|
+
*/
|
|
23026
|
+
decodeBudgetMb: number().int().min(1024).max(65536).optional(),
|
|
23027
|
+
/** This node's live decode-worker cap. Wins over the cluster `maxLiveDecodeWorkers`. */
|
|
23028
|
+
maxLiveDecodeWorkers: number().int().min(1).max(32).optional(),
|
|
23029
|
+
/**
|
|
23022
23030
|
* Operator override for the LAN host a cross-node decoder dials to reach
|
|
23023
23031
|
* THIS node's restream (Cluster UI). Absent → auto-detect: a remote runner
|
|
23024
23032
|
* falls back to its `CAMSTACK_HUB_URL`-derived host (the Moleculer address
|
|
@@ -23480,6 +23488,13 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
|
|
|
23480
23488
|
}), object({ success: literal(true) }), {
|
|
23481
23489
|
kind: "mutation",
|
|
23482
23490
|
auth: "admin"
|
|
23491
|
+
}), method(object({
|
|
23492
|
+
agentNodeId: string(),
|
|
23493
|
+
decodeBudgetMb: number().int().min(1024).max(65536).nullable().optional(),
|
|
23494
|
+
maxLiveDecodeWorkers: number().int().min(1).max(32).nullable().optional()
|
|
23495
|
+
}), object({ success: literal(true) }), {
|
|
23496
|
+
kind: "mutation",
|
|
23497
|
+
auth: "admin"
|
|
23483
23498
|
}), method(object({
|
|
23484
23499
|
agentNodeId: string(),
|
|
23485
23500
|
reachableHost: string().nullable()
|
|
@@ -36213,6 +36228,12 @@ Object.freeze({
|
|
|
36213
36228
|
addonId: null,
|
|
36214
36229
|
access: "create"
|
|
36215
36230
|
},
|
|
36231
|
+
"pipelineOrchestrator.setAgentDecodeLimits": {
|
|
36232
|
+
capName: "pipeline-orchestrator",
|
|
36233
|
+
capScope: "system",
|
|
36234
|
+
addonId: null,
|
|
36235
|
+
access: "create"
|
|
36236
|
+
},
|
|
36216
36237
|
"pipelineOrchestrator.setAgentDetectWeight": {
|
|
36217
36238
|
capName: "pipeline-orchestrator",
|
|
36218
36239
|
capScope: "system",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-
|
|
1
|
+
import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-HWdaHLLK.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
4
4
|
var HF_REPO = "camstack/camstack-models";
|
|
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
5
|
+
const require_dist = require("../dist-e2OKAUGI.js");
|
|
6
|
+
const require_lazy_sharp = require("../lazy-sharp-AJ7newgl.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_path = require("node:path");
|
|
9
9
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-
|
|
1
|
+
import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-HWdaHLLK.mjs";
|
|
2
2
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-
|
|
1
|
+
import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-HWdaHLLK.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import "node:fs";
|
|
4
4
|
import "node:path";
|
|
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_node = require("../node-
|
|
7
|
-
const require_local_frame_registry = require("../local-frame-registry-
|
|
8
|
-
const require_worker_protocol = require("../worker-protocol-
|
|
5
|
+
const require_dist = require("../dist-e2OKAUGI.js");
|
|
6
|
+
const require_node = require("../node-Dw6FrDFS.js");
|
|
7
|
+
const require_local_frame_registry = require("../local-frame-registry-Cl1VUpx_.js");
|
|
8
|
+
const require_worker_protocol = require("../worker-protocol-Bva8nEZO.js");
|
|
9
9
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
10
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
10
|
+
const require_lazy_sharp = require("../lazy-sharp-AJ7newgl.js");
|
|
11
11
|
const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
|
|
12
12
|
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
|
|
13
13
|
const require_remote_restream = require("../remote-restream-CO36Sr30.js");
|
|
@@ -3381,6 +3381,115 @@ var NativeLeaseSettingsSource = class {
|
|
|
3381
3381
|
}
|
|
3382
3382
|
}
|
|
3383
3383
|
};
|
|
3384
|
+
function pickLimits(settings) {
|
|
3385
|
+
if (settings === null) return {};
|
|
3386
|
+
const budget = settings.decodeBudgetMb;
|
|
3387
|
+
const workers = settings.maxLiveDecodeWorkers;
|
|
3388
|
+
return {
|
|
3389
|
+
...typeof budget === "number" && Number.isFinite(budget) ? { decodeBudgetMb: budget } : {},
|
|
3390
|
+
...typeof workers === "number" && Number.isFinite(workers) ? { maxLiveDecodeWorkers: workers } : {}
|
|
3391
|
+
};
|
|
3392
|
+
}
|
|
3393
|
+
function sameLimits(a, b) {
|
|
3394
|
+
return a.decodeBudgetMb === b.decodeBudgetMb && a.maxLiveDecodeWorkers === b.maxLiveDecodeWorkers;
|
|
3395
|
+
}
|
|
3396
|
+
var NodeDecodeLimitsSource = class {
|
|
3397
|
+
limits = {};
|
|
3398
|
+
lastReadAtMs = Number.NEGATIVE_INFINITY;
|
|
3399
|
+
inFlight = null;
|
|
3400
|
+
logger;
|
|
3401
|
+
nodeId;
|
|
3402
|
+
now;
|
|
3403
|
+
ttlMs;
|
|
3404
|
+
constructor(options) {
|
|
3405
|
+
this.logger = options.logger;
|
|
3406
|
+
this.nodeId = options.nodeId;
|
|
3407
|
+
this.now = options.now ?? (() => Date.now());
|
|
3408
|
+
this.ttlMs = options.ttlMs ?? 3e4;
|
|
3409
|
+
}
|
|
3410
|
+
current() {
|
|
3411
|
+
return this.limits;
|
|
3412
|
+
}
|
|
3413
|
+
async refresh(api) {
|
|
3414
|
+
if (api === void 0) return this.limits;
|
|
3415
|
+
if (this.now() - this.lastReadAtMs < this.ttlMs) return this.limits;
|
|
3416
|
+
this.inFlight ??= this.read(api).finally(() => {
|
|
3417
|
+
this.inFlight = null;
|
|
3418
|
+
});
|
|
3419
|
+
await this.inFlight;
|
|
3420
|
+
return this.limits;
|
|
3421
|
+
}
|
|
3422
|
+
async read(api) {
|
|
3423
|
+
try {
|
|
3424
|
+
const next = pickLimits(await api.pipelineOrchestrator.getAgentSettings.query({ agentNodeId: this.nodeId }));
|
|
3425
|
+
this.lastReadAtMs = this.now();
|
|
3426
|
+
if (sameLimits(next, this.limits)) return;
|
|
3427
|
+
this.logger.info("node decode limits changed — the admission resizes on the next dial", { meta: {
|
|
3428
|
+
nodeId: this.nodeId,
|
|
3429
|
+
from: { ...this.limits },
|
|
3430
|
+
to: { ...next }
|
|
3431
|
+
} });
|
|
3432
|
+
this.limits = next;
|
|
3433
|
+
} catch (err) {
|
|
3434
|
+
this.logger.warn("node decode limits read failed — keeping the last known value", { meta: {
|
|
3435
|
+
nodeId: this.nodeId,
|
|
3436
|
+
inUse: { ...this.limits },
|
|
3437
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3438
|
+
} });
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
};
|
|
3442
|
+
//#endregion
|
|
3443
|
+
//#region src/session-decode/node-decode-budget.ts
|
|
3444
|
+
/**
|
|
3445
|
+
* The decode RAM budget and worker cap THIS node runs under.
|
|
3446
|
+
*
|
|
3447
|
+
* `nodeDecodeBudgetMb` and `maxLiveDecodeWorkers` are cluster settings — one
|
|
3448
|
+
* number for a 64 GB hub and a 16 GB Mac alike. Until 2026-09-05 the shipped
|
|
3449
|
+
* 8192 MB was the hub's number applied everywhere; with the footprint fixed
|
|
3450
|
+
* (D361) that admits 8 workers on the Mac, whose workers measure RSS p90
|
|
3451
|
+
* 952 MB on a machine already at 80% — 7.6 GB of decode on 16 GB is a swap
|
|
3452
|
+
* away from a stall — while the hub leaves 56 GB idle.
|
|
3453
|
+
*
|
|
3454
|
+
* Three sources, in order, and the winner is NAMED so a log line can say why:
|
|
3455
|
+
* 1. the node's own agent setting (`decodeBudgetMb` / `maxLiveDecodeWorkers`
|
|
3456
|
+
* in `AgentPipelineSettings`) — the operator sized this node;
|
|
3457
|
+
* 2. the cluster setting when the operator MOVED it off the shipped default
|
|
3458
|
+
* (a value equal to the default reads as "nobody chose", the same rule the
|
|
3459
|
+
* native-lease knobs use, `readKnob`);
|
|
3460
|
+
* 3. otherwise a share of the node's RAM, clamped — the shipped default
|
|
3461
|
+
* becomes a per-node derivation instead of the hub's number.
|
|
3462
|
+
*/
|
|
3463
|
+
var DECODE_BUDGET_RAM_SHARE = .5;
|
|
3464
|
+
var DECODE_BUDGET_MIN_MB = 2048;
|
|
3465
|
+
var DECODE_BUDGET_MAX_MB = 16384;
|
|
3466
|
+
function derivedDecodeBudgetMb(totalMemMb) {
|
|
3467
|
+
const share = Math.round(totalMemMb * DECODE_BUDGET_RAM_SHARE);
|
|
3468
|
+
return Math.max(DECODE_BUDGET_MIN_MB, Math.min(DECODE_BUDGET_MAX_MB, share));
|
|
3469
|
+
}
|
|
3470
|
+
function resolveNodeDecodeLimits(input) {
|
|
3471
|
+
const budget = input.node.decodeBudgetMb !== void 0 ? {
|
|
3472
|
+
budgetMb: input.node.decodeBudgetMb,
|
|
3473
|
+
budgetSource: "node"
|
|
3474
|
+
} : input.clusterBudgetMb !== input.defaultBudgetMb ? {
|
|
3475
|
+
budgetMb: input.clusterBudgetMb,
|
|
3476
|
+
budgetSource: "cluster"
|
|
3477
|
+
} : {
|
|
3478
|
+
budgetMb: derivedDecodeBudgetMb(input.totalMemMb),
|
|
3479
|
+
budgetSource: "derived"
|
|
3480
|
+
};
|
|
3481
|
+
const workers = input.node.maxLiveDecodeWorkers !== void 0 ? {
|
|
3482
|
+
maxWorkers: input.node.maxLiveDecodeWorkers,
|
|
3483
|
+
maxWorkersSource: "node"
|
|
3484
|
+
} : {
|
|
3485
|
+
maxWorkers: input.clusterMaxWorkers,
|
|
3486
|
+
maxWorkersSource: "cluster"
|
|
3487
|
+
};
|
|
3488
|
+
return {
|
|
3489
|
+
...budget,
|
|
3490
|
+
...workers
|
|
3491
|
+
};
|
|
3492
|
+
}
|
|
3384
3493
|
//#endregion
|
|
3385
3494
|
//#region src/session-decode/on-demand-jpeg-fallback.ts
|
|
3386
3495
|
/** Single content-sized JPEG requested after a detection, never a continuous raw. */
|
|
@@ -5652,6 +5761,13 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
5652
5761
|
async onInitialize() {
|
|
5653
5762
|
const raw = this.ctx.kernel.localNodeId ?? this.ctx.id;
|
|
5654
5763
|
this.nodeId = raw.includes("/") ? raw.split("/")[0] : raw;
|
|
5764
|
+
this.nodeLimits = new NodeDecodeLimitsSource({
|
|
5765
|
+
logger: {
|
|
5766
|
+
info: (message, extras) => this.ctxIfReady?.logger.info(message, extras),
|
|
5767
|
+
warn: (message, extras) => this.ctxIfReady?.logger.warn(message, extras)
|
|
5768
|
+
},
|
|
5769
|
+
nodeId: this.nodeId
|
|
5770
|
+
});
|
|
5655
5771
|
this.retainedFrames = new RetainedFrameStore({
|
|
5656
5772
|
nodeId: this.nodeId,
|
|
5657
5773
|
logger: this.ctx.logger.child("retained-frames"),
|
|
@@ -5682,10 +5798,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
5682
5798
|
noteInferenceOutcome: (deviceId, reason) => this.failureReport.noteInference(deviceId, reason)
|
|
5683
5799
|
});
|
|
5684
5800
|
this.spawnGate = new Semaphore(Math.max(1, this.config.maxConcurrentDecodeSpawns));
|
|
5801
|
+
const decodeLimits = this.resolvedNodeDecodeLimits();
|
|
5802
|
+
this.lastAppliedDecodeLimits = decodeLimits;
|
|
5685
5803
|
this.liveWorkers = new LiveDecodeWorkerAdmission({
|
|
5686
|
-
limit:
|
|
5804
|
+
limit: decodeLimits.maxWorkers,
|
|
5687
5805
|
logger: this.ctx.logger,
|
|
5688
|
-
nodeBudgetMb:
|
|
5806
|
+
nodeBudgetMb: decodeLimits.budgetMb,
|
|
5689
5807
|
workerFootprintMb: decodeWorkerFootprintMb(this.nativeLease.current())
|
|
5690
5808
|
});
|
|
5691
5809
|
this.runner.timingSampler.setLogger(this.ctx.logger.child("timing"));
|
|
@@ -6907,6 +7025,45 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
6907
7025
|
async refreshNativeLeaseSettings() {
|
|
6908
7026
|
await this.nativeLease.refresh(this.ctxIfReady?.api);
|
|
6909
7027
|
this.liveWorkers?.resizeFootprint(decodeWorkerFootprintMb(this.nativeLease.current()));
|
|
7028
|
+
await this.nodeLimits?.refresh(this.ctxIfReady?.api);
|
|
7029
|
+
this.applyNodeDecodeLimits("lease-refresh");
|
|
7030
|
+
}
|
|
7031
|
+
nodeLimits = null;
|
|
7032
|
+
lastAppliedDecodeLimits = null;
|
|
7033
|
+
/**
|
|
7034
|
+
* The budget and worker cap THIS node runs under (D365): its own agent
|
|
7035
|
+
* setting, else the cluster value the operator moved, else a share of its
|
|
7036
|
+
* RAM. One resolver for construction, the lease refresh and a settings
|
|
7037
|
+
* change — computing it in two places is how the count and the budget
|
|
7038
|
+
* drifted apart before.
|
|
7039
|
+
*/
|
|
7040
|
+
resolvedNodeDecodeLimits() {
|
|
7041
|
+
return resolveNodeDecodeLimits({
|
|
7042
|
+
clusterBudgetMb: this.config.nodeDecodeBudgetMb,
|
|
7043
|
+
clusterMaxWorkers: this.config.maxLiveDecodeWorkers,
|
|
7044
|
+
defaultBudgetMb: DEFAULT_CONFIG.nodeDecodeBudgetMb,
|
|
7045
|
+
defaultMaxWorkers: DEFAULT_CONFIG.maxLiveDecodeWorkers,
|
|
7046
|
+
node: this.nodeLimits?.current() ?? {},
|
|
7047
|
+
totalMemMb: Math.round(node_os.totalmem() / 1048576)
|
|
7048
|
+
});
|
|
7049
|
+
}
|
|
7050
|
+
/** Resize the admission to the resolved limits; one info line per change. */
|
|
7051
|
+
applyNodeDecodeLimits(reason) {
|
|
7052
|
+
const limits = this.resolvedNodeDecodeLimits();
|
|
7053
|
+
const last = this.lastAppliedDecodeLimits;
|
|
7054
|
+
this.liveWorkers?.resize(limits.maxWorkers);
|
|
7055
|
+
this.liveWorkers?.resizeBudget(limits.budgetMb);
|
|
7056
|
+
if (last !== null && last.budgetMb === limits.budgetMb && last.maxWorkers === limits.maxWorkers && last.budgetSource === limits.budgetSource) return;
|
|
7057
|
+
this.lastAppliedDecodeLimits = limits;
|
|
7058
|
+
this.ctxIfReady?.logger.info("node decode limits in force", { meta: {
|
|
7059
|
+
reason,
|
|
7060
|
+
budgetMb: limits.budgetMb,
|
|
7061
|
+
budgetSource: limits.budgetSource,
|
|
7062
|
+
maxWorkers: limits.maxWorkers,
|
|
7063
|
+
maxWorkersSource: limits.maxWorkersSource,
|
|
7064
|
+
totalMemMb: Math.round(node_os.totalmem() / 1048576),
|
|
7065
|
+
decodeCeilingInForce: this.liveWorkers?.ceiling
|
|
7066
|
+
} });
|
|
6910
7067
|
}
|
|
6911
7068
|
/** A warn sink that survives a not-yet-ready ctx (boot-order dispatches). */
|
|
6912
7069
|
detailSubtreeLogger() {
|
|
@@ -8456,7 +8613,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
8456
8613
|
type: "slider",
|
|
8457
8614
|
key: "nodeDecodeBudgetMb",
|
|
8458
8615
|
label: "Decode worker RAM budget (MB)",
|
|
8459
|
-
description: "RAM
|
|
8616
|
+
description: "Cluster-wide fallback for the RAM a node lets live decode workers commit. Each node resolves its own number: its agent setting (decodeBudgetMb) wins; otherwise this value when moved off the default; otherwise half the node's RAM (2-16 GB). The number of workers admitted is derived from it: budget divided by one worker's worst case — what the lease store can hold (the smaller of the lease budget and held frames × 25 MB, one 4K frame), plus the tile and scene budgets, plus ~350 MB of baseline, ~660 MB at the shipped knobs. Raising held frames or the lease budget per worker therefore LOWERS how many run at once, instead of silently authorising more memory.",
|
|
8460
8617
|
min: 1024,
|
|
8461
8618
|
max: 32768,
|
|
8462
8619
|
step: 512,
|
|
@@ -8469,8 +8626,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends require_dist.BaseAdd
|
|
|
8469
8626
|
async onConfigChanged() {
|
|
8470
8627
|
this.runner?.updateLimits(this.config);
|
|
8471
8628
|
this.spawnGate?.resize(Math.max(1, this.config.maxConcurrentDecodeSpawns));
|
|
8472
|
-
this.
|
|
8473
|
-
this.liveWorkers?.resizeBudget(this.config.nodeDecodeBudgetMb);
|
|
8629
|
+
this.applyNodeDecodeLimits("settings");
|
|
8474
8630
|
this.ctx.logger.info("pipeline-runner tuning updated", { meta: {
|
|
8475
8631
|
maxQueueDepth: this.config.maxQueueDepth,
|
|
8476
8632
|
maxConcurrentInferences: this.config.maxConcurrentInferences,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-
|
|
2
|
-
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-
|
|
3
|
-
import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-
|
|
4
|
-
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-
|
|
1
|
+
import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-HWdaHLLK.mjs";
|
|
2
|
+
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-CwSBH-3M.mjs";
|
|
3
|
+
import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-Bki81rM0.mjs";
|
|
4
|
+
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-DN1y2Vyk.mjs";
|
|
5
5
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
6
6
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
7
7
|
import { n as withDetectionIntent } from "../restream-intent-B4BXZra7.mjs";
|
|
@@ -3374,6 +3374,115 @@ var NativeLeaseSettingsSource = class {
|
|
|
3374
3374
|
}
|
|
3375
3375
|
}
|
|
3376
3376
|
};
|
|
3377
|
+
function pickLimits(settings) {
|
|
3378
|
+
if (settings === null) return {};
|
|
3379
|
+
const budget = settings.decodeBudgetMb;
|
|
3380
|
+
const workers = settings.maxLiveDecodeWorkers;
|
|
3381
|
+
return {
|
|
3382
|
+
...typeof budget === "number" && Number.isFinite(budget) ? { decodeBudgetMb: budget } : {},
|
|
3383
|
+
...typeof workers === "number" && Number.isFinite(workers) ? { maxLiveDecodeWorkers: workers } : {}
|
|
3384
|
+
};
|
|
3385
|
+
}
|
|
3386
|
+
function sameLimits(a, b) {
|
|
3387
|
+
return a.decodeBudgetMb === b.decodeBudgetMb && a.maxLiveDecodeWorkers === b.maxLiveDecodeWorkers;
|
|
3388
|
+
}
|
|
3389
|
+
var NodeDecodeLimitsSource = class {
|
|
3390
|
+
limits = {};
|
|
3391
|
+
lastReadAtMs = Number.NEGATIVE_INFINITY;
|
|
3392
|
+
inFlight = null;
|
|
3393
|
+
logger;
|
|
3394
|
+
nodeId;
|
|
3395
|
+
now;
|
|
3396
|
+
ttlMs;
|
|
3397
|
+
constructor(options) {
|
|
3398
|
+
this.logger = options.logger;
|
|
3399
|
+
this.nodeId = options.nodeId;
|
|
3400
|
+
this.now = options.now ?? (() => Date.now());
|
|
3401
|
+
this.ttlMs = options.ttlMs ?? 3e4;
|
|
3402
|
+
}
|
|
3403
|
+
current() {
|
|
3404
|
+
return this.limits;
|
|
3405
|
+
}
|
|
3406
|
+
async refresh(api) {
|
|
3407
|
+
if (api === void 0) return this.limits;
|
|
3408
|
+
if (this.now() - this.lastReadAtMs < this.ttlMs) return this.limits;
|
|
3409
|
+
this.inFlight ??= this.read(api).finally(() => {
|
|
3410
|
+
this.inFlight = null;
|
|
3411
|
+
});
|
|
3412
|
+
await this.inFlight;
|
|
3413
|
+
return this.limits;
|
|
3414
|
+
}
|
|
3415
|
+
async read(api) {
|
|
3416
|
+
try {
|
|
3417
|
+
const next = pickLimits(await api.pipelineOrchestrator.getAgentSettings.query({ agentNodeId: this.nodeId }));
|
|
3418
|
+
this.lastReadAtMs = this.now();
|
|
3419
|
+
if (sameLimits(next, this.limits)) return;
|
|
3420
|
+
this.logger.info("node decode limits changed — the admission resizes on the next dial", { meta: {
|
|
3421
|
+
nodeId: this.nodeId,
|
|
3422
|
+
from: { ...this.limits },
|
|
3423
|
+
to: { ...next }
|
|
3424
|
+
} });
|
|
3425
|
+
this.limits = next;
|
|
3426
|
+
} catch (err) {
|
|
3427
|
+
this.logger.warn("node decode limits read failed — keeping the last known value", { meta: {
|
|
3428
|
+
nodeId: this.nodeId,
|
|
3429
|
+
inUse: { ...this.limits },
|
|
3430
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3431
|
+
} });
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
};
|
|
3435
|
+
//#endregion
|
|
3436
|
+
//#region src/session-decode/node-decode-budget.ts
|
|
3437
|
+
/**
|
|
3438
|
+
* The decode RAM budget and worker cap THIS node runs under.
|
|
3439
|
+
*
|
|
3440
|
+
* `nodeDecodeBudgetMb` and `maxLiveDecodeWorkers` are cluster settings — one
|
|
3441
|
+
* number for a 64 GB hub and a 16 GB Mac alike. Until 2026-09-05 the shipped
|
|
3442
|
+
* 8192 MB was the hub's number applied everywhere; with the footprint fixed
|
|
3443
|
+
* (D361) that admits 8 workers on the Mac, whose workers measure RSS p90
|
|
3444
|
+
* 952 MB on a machine already at 80% — 7.6 GB of decode on 16 GB is a swap
|
|
3445
|
+
* away from a stall — while the hub leaves 56 GB idle.
|
|
3446
|
+
*
|
|
3447
|
+
* Three sources, in order, and the winner is NAMED so a log line can say why:
|
|
3448
|
+
* 1. the node's own agent setting (`decodeBudgetMb` / `maxLiveDecodeWorkers`
|
|
3449
|
+
* in `AgentPipelineSettings`) — the operator sized this node;
|
|
3450
|
+
* 2. the cluster setting when the operator MOVED it off the shipped default
|
|
3451
|
+
* (a value equal to the default reads as "nobody chose", the same rule the
|
|
3452
|
+
* native-lease knobs use, `readKnob`);
|
|
3453
|
+
* 3. otherwise a share of the node's RAM, clamped — the shipped default
|
|
3454
|
+
* becomes a per-node derivation instead of the hub's number.
|
|
3455
|
+
*/
|
|
3456
|
+
var DECODE_BUDGET_RAM_SHARE = .5;
|
|
3457
|
+
var DECODE_BUDGET_MIN_MB = 2048;
|
|
3458
|
+
var DECODE_BUDGET_MAX_MB = 16384;
|
|
3459
|
+
function derivedDecodeBudgetMb(totalMemMb) {
|
|
3460
|
+
const share = Math.round(totalMemMb * DECODE_BUDGET_RAM_SHARE);
|
|
3461
|
+
return Math.max(DECODE_BUDGET_MIN_MB, Math.min(DECODE_BUDGET_MAX_MB, share));
|
|
3462
|
+
}
|
|
3463
|
+
function resolveNodeDecodeLimits(input) {
|
|
3464
|
+
const budget = input.node.decodeBudgetMb !== void 0 ? {
|
|
3465
|
+
budgetMb: input.node.decodeBudgetMb,
|
|
3466
|
+
budgetSource: "node"
|
|
3467
|
+
} : input.clusterBudgetMb !== input.defaultBudgetMb ? {
|
|
3468
|
+
budgetMb: input.clusterBudgetMb,
|
|
3469
|
+
budgetSource: "cluster"
|
|
3470
|
+
} : {
|
|
3471
|
+
budgetMb: derivedDecodeBudgetMb(input.totalMemMb),
|
|
3472
|
+
budgetSource: "derived"
|
|
3473
|
+
};
|
|
3474
|
+
const workers = input.node.maxLiveDecodeWorkers !== void 0 ? {
|
|
3475
|
+
maxWorkers: input.node.maxLiveDecodeWorkers,
|
|
3476
|
+
maxWorkersSource: "node"
|
|
3477
|
+
} : {
|
|
3478
|
+
maxWorkers: input.clusterMaxWorkers,
|
|
3479
|
+
maxWorkersSource: "cluster"
|
|
3480
|
+
};
|
|
3481
|
+
return {
|
|
3482
|
+
...budget,
|
|
3483
|
+
...workers
|
|
3484
|
+
};
|
|
3485
|
+
}
|
|
3377
3486
|
//#endregion
|
|
3378
3487
|
//#region src/session-decode/on-demand-jpeg-fallback.ts
|
|
3379
3488
|
/** Single content-sized JPEG requested after a detection, never a continuous raw. */
|
|
@@ -5645,6 +5754,13 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
5645
5754
|
async onInitialize() {
|
|
5646
5755
|
const raw = this.ctx.kernel.localNodeId ?? this.ctx.id;
|
|
5647
5756
|
this.nodeId = raw.includes("/") ? raw.split("/")[0] : raw;
|
|
5757
|
+
this.nodeLimits = new NodeDecodeLimitsSource({
|
|
5758
|
+
logger: {
|
|
5759
|
+
info: (message, extras) => this.ctxIfReady?.logger.info(message, extras),
|
|
5760
|
+
warn: (message, extras) => this.ctxIfReady?.logger.warn(message, extras)
|
|
5761
|
+
},
|
|
5762
|
+
nodeId: this.nodeId
|
|
5763
|
+
});
|
|
5648
5764
|
this.retainedFrames = new RetainedFrameStore({
|
|
5649
5765
|
nodeId: this.nodeId,
|
|
5650
5766
|
logger: this.ctx.logger.child("retained-frames"),
|
|
@@ -5675,10 +5791,12 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
5675
5791
|
noteInferenceOutcome: (deviceId, reason) => this.failureReport.noteInference(deviceId, reason)
|
|
5676
5792
|
});
|
|
5677
5793
|
this.spawnGate = new Semaphore(Math.max(1, this.config.maxConcurrentDecodeSpawns));
|
|
5794
|
+
const decodeLimits = this.resolvedNodeDecodeLimits();
|
|
5795
|
+
this.lastAppliedDecodeLimits = decodeLimits;
|
|
5678
5796
|
this.liveWorkers = new LiveDecodeWorkerAdmission({
|
|
5679
|
-
limit:
|
|
5797
|
+
limit: decodeLimits.maxWorkers,
|
|
5680
5798
|
logger: this.ctx.logger,
|
|
5681
|
-
nodeBudgetMb:
|
|
5799
|
+
nodeBudgetMb: decodeLimits.budgetMb,
|
|
5682
5800
|
workerFootprintMb: decodeWorkerFootprintMb(this.nativeLease.current())
|
|
5683
5801
|
});
|
|
5684
5802
|
this.runner.timingSampler.setLogger(this.ctx.logger.child("timing"));
|
|
@@ -6900,6 +7018,45 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
6900
7018
|
async refreshNativeLeaseSettings() {
|
|
6901
7019
|
await this.nativeLease.refresh(this.ctxIfReady?.api);
|
|
6902
7020
|
this.liveWorkers?.resizeFootprint(decodeWorkerFootprintMb(this.nativeLease.current()));
|
|
7021
|
+
await this.nodeLimits?.refresh(this.ctxIfReady?.api);
|
|
7022
|
+
this.applyNodeDecodeLimits("lease-refresh");
|
|
7023
|
+
}
|
|
7024
|
+
nodeLimits = null;
|
|
7025
|
+
lastAppliedDecodeLimits = null;
|
|
7026
|
+
/**
|
|
7027
|
+
* The budget and worker cap THIS node runs under (D365): its own agent
|
|
7028
|
+
* setting, else the cluster value the operator moved, else a share of its
|
|
7029
|
+
* RAM. One resolver for construction, the lease refresh and a settings
|
|
7030
|
+
* change — computing it in two places is how the count and the budget
|
|
7031
|
+
* drifted apart before.
|
|
7032
|
+
*/
|
|
7033
|
+
resolvedNodeDecodeLimits() {
|
|
7034
|
+
return resolveNodeDecodeLimits({
|
|
7035
|
+
clusterBudgetMb: this.config.nodeDecodeBudgetMb,
|
|
7036
|
+
clusterMaxWorkers: this.config.maxLiveDecodeWorkers,
|
|
7037
|
+
defaultBudgetMb: DEFAULT_CONFIG.nodeDecodeBudgetMb,
|
|
7038
|
+
defaultMaxWorkers: DEFAULT_CONFIG.maxLiveDecodeWorkers,
|
|
7039
|
+
node: this.nodeLimits?.current() ?? {},
|
|
7040
|
+
totalMemMb: Math.round(os.totalmem() / 1048576)
|
|
7041
|
+
});
|
|
7042
|
+
}
|
|
7043
|
+
/** Resize the admission to the resolved limits; one info line per change. */
|
|
7044
|
+
applyNodeDecodeLimits(reason) {
|
|
7045
|
+
const limits = this.resolvedNodeDecodeLimits();
|
|
7046
|
+
const last = this.lastAppliedDecodeLimits;
|
|
7047
|
+
this.liveWorkers?.resize(limits.maxWorkers);
|
|
7048
|
+
this.liveWorkers?.resizeBudget(limits.budgetMb);
|
|
7049
|
+
if (last !== null && last.budgetMb === limits.budgetMb && last.maxWorkers === limits.maxWorkers && last.budgetSource === limits.budgetSource) return;
|
|
7050
|
+
this.lastAppliedDecodeLimits = limits;
|
|
7051
|
+
this.ctxIfReady?.logger.info("node decode limits in force", { meta: {
|
|
7052
|
+
reason,
|
|
7053
|
+
budgetMb: limits.budgetMb,
|
|
7054
|
+
budgetSource: limits.budgetSource,
|
|
7055
|
+
maxWorkers: limits.maxWorkers,
|
|
7056
|
+
maxWorkersSource: limits.maxWorkersSource,
|
|
7057
|
+
totalMemMb: Math.round(os.totalmem() / 1048576),
|
|
7058
|
+
decodeCeilingInForce: this.liveWorkers?.ceiling
|
|
7059
|
+
} });
|
|
6903
7060
|
}
|
|
6904
7061
|
/** A warn sink that survives a not-yet-ready ctx (boot-order dispatches). */
|
|
6905
7062
|
detailSubtreeLogger() {
|
|
@@ -8449,7 +8606,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
8449
8606
|
type: "slider",
|
|
8450
8607
|
key: "nodeDecodeBudgetMb",
|
|
8451
8608
|
label: "Decode worker RAM budget (MB)",
|
|
8452
|
-
description: "RAM
|
|
8609
|
+
description: "Cluster-wide fallback for the RAM a node lets live decode workers commit. Each node resolves its own number: its agent setting (decodeBudgetMb) wins; otherwise this value when moved off the default; otherwise half the node's RAM (2-16 GB). The number of workers admitted is derived from it: budget divided by one worker's worst case — what the lease store can hold (the smaller of the lease budget and held frames × 25 MB, one 4K frame), plus the tile and scene budgets, plus ~350 MB of baseline, ~660 MB at the shipped knobs. Raising held frames or the lease budget per worker therefore LOWERS how many run at once, instead of silently authorising more memory.",
|
|
8453
8610
|
min: 1024,
|
|
8454
8611
|
max: 32768,
|
|
8455
8612
|
step: 512,
|
|
@@ -8462,8 +8619,7 @@ var PipelineRunnerAddon = class PipelineRunnerAddon extends BaseAddon {
|
|
|
8462
8619
|
async onConfigChanged() {
|
|
8463
8620
|
this.runner?.updateLimits(this.config);
|
|
8464
8621
|
this.spawnGate?.resize(Math.max(1, this.config.maxConcurrentDecodeSpawns));
|
|
8465
|
-
this.
|
|
8466
|
-
this.liveWorkers?.resizeBudget(this.config.nodeDecodeBudgetMb);
|
|
8622
|
+
this.applyNodeDecodeLimits("settings");
|
|
8467
8623
|
this.ctx.logger.info("pipeline-runner tuning updated", { meta: {
|
|
8468
8624
|
maxQueueDepth: this.config.maxQueueDepth,
|
|
8469
8625
|
maxConcurrentInferences: this.config.maxConcurrentInferences,
|