camstack 1.2.137 → 1.2.138
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.
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-B17W9ngu.js
|
|
23637
|
+
var require_dist_B17W9ngu = __commonJS({
|
|
23638
|
+
"../system/dist/dist-B17W9ngu.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -44623,8 +44623,8 @@ var require_dist_BOlMCOeT = __commonJS({
|
|
|
44623
44623
|
*
|
|
44624
44624
|
* An **empty array reads NOTHING** — `[]` is an empty page, never
|
|
44625
44625
|
* "every camera". A request for no devices is a request, not an
|
|
44626
|
-
* omission; same contract as `deviceManager.
|
|
44627
|
-
* `pipelineAnalytics.listRecentTracks`.
|
|
44626
|
+
* omission; same contract as `deviceManager.listAll`'s `deviceIds`
|
|
44627
|
+
* and `pipelineAnalytics.listRecentTracks`.
|
|
44628
44628
|
*
|
|
44629
44629
|
* Absent (`undefined`) is the omission, and keeps the cluster-wide view.
|
|
44630
44630
|
*/
|
|
@@ -61586,7 +61586,7 @@ var require_alerts_addon = __commonJS({
|
|
|
61586
61586
|
[Symbol.toStringTag]: { value: "Module" }
|
|
61587
61587
|
});
|
|
61588
61588
|
require_chunk_Cek0wNdY();
|
|
61589
|
-
var require_dist10 =
|
|
61589
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
61590
61590
|
function selectExpired(alerts, cutoffMs) {
|
|
61591
61591
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
61592
61592
|
}
|
|
@@ -62405,7 +62405,7 @@ var require_console_logging = __commonJS({
|
|
|
62405
62405
|
[Symbol.toStringTag]: { value: "Module" }
|
|
62406
62406
|
});
|
|
62407
62407
|
require_chunk_Cek0wNdY();
|
|
62408
|
-
var require_dist10 =
|
|
62408
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
62409
62409
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
62410
62410
|
var LEVEL_RANK = {
|
|
62411
62411
|
debug: 0,
|
|
@@ -62499,7 +62499,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
62499
62499
|
"use strict";
|
|
62500
62500
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
62501
62501
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
62502
|
-
var require_dist10 =
|
|
62502
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
62503
62503
|
var node_crypto = __require("crypto");
|
|
62504
62504
|
var node_fs_promises = __require("fs/promises");
|
|
62505
62505
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -63396,11 +63396,11 @@ var require_core_blocks = __commonJS({
|
|
|
63396
63396
|
}
|
|
63397
63397
|
});
|
|
63398
63398
|
|
|
63399
|
-
// ../system/dist/retired-settings-keys-
|
|
63400
|
-
var
|
|
63401
|
-
"../system/dist/retired-settings-keys-
|
|
63399
|
+
// ../system/dist/retired-settings-keys-CjvB7Etx.js
|
|
63400
|
+
var require_retired_settings_keys_CjvB7Etx = __commonJS({
|
|
63401
|
+
"../system/dist/retired-settings-keys-CjvB7Etx.js"(exports) {
|
|
63402
63402
|
"use strict";
|
|
63403
|
-
var require_dist10 =
|
|
63403
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
63404
63404
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
63405
63405
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
63406
63406
|
return raw === "" || raw === "hub";
|
|
@@ -65635,8 +65635,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
65635
65635
|
[Symbol.toStringTag]: { value: "Module" }
|
|
65636
65636
|
});
|
|
65637
65637
|
require_chunk_Cek0wNdY();
|
|
65638
|
-
var require_dist10 =
|
|
65639
|
-
var require_retired_settings_keys =
|
|
65638
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
65639
|
+
var require_retired_settings_keys = require_retired_settings_keys_CjvB7Etx();
|
|
65640
65640
|
var node_crypto = __require("crypto");
|
|
65641
65641
|
var _camstack_types_node = require_node();
|
|
65642
65642
|
var JOB_HISTORY = 20;
|
|
@@ -71261,7 +71261,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
71261
71261
|
[Symbol.toStringTag]: { value: "Module" }
|
|
71262
71262
|
});
|
|
71263
71263
|
require_chunk_Cek0wNdY();
|
|
71264
|
-
var require_dist10 =
|
|
71264
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
71265
71265
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
71266
71266
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
71267
71267
|
var HubForwarderDestination = class {
|
|
@@ -71398,7 +71398,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
71398
71398
|
"use strict";
|
|
71399
71399
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
71400
71400
|
require_chunk_Cek0wNdY();
|
|
71401
|
-
var require_dist10 =
|
|
71401
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
71402
71402
|
var NO_DEVICES = "liveness:no-devices";
|
|
71403
71403
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
71404
71404
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -71594,7 +71594,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
71594
71594
|
[Symbol.toStringTag]: { value: "Module" }
|
|
71595
71595
|
});
|
|
71596
71596
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
71597
|
-
var require_dist10 =
|
|
71597
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
71598
71598
|
var node_crypto = __require("crypto");
|
|
71599
71599
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
71600
71600
|
var crypto$1 = __require("crypto");
|
|
@@ -79407,7 +79407,7 @@ var require_loki_logging = __commonJS({
|
|
|
79407
79407
|
[Symbol.toStringTag]: { value: "Module" }
|
|
79408
79408
|
});
|
|
79409
79409
|
require_chunk_Cek0wNdY();
|
|
79410
|
-
var require_dist10 =
|
|
79410
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
79411
79411
|
function sanitizeLabelName(raw) {
|
|
79412
79412
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
79413
79413
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -79873,31 +79873,18 @@ var require_loki_logging = __commonJS({
|
|
|
79873
79873
|
}
|
|
79874
79874
|
});
|
|
79875
79875
|
|
|
79876
|
-
// ../system/dist/resource-monitor-
|
|
79877
|
-
var
|
|
79878
|
-
"../system/dist/resource-monitor-
|
|
79876
|
+
// ../system/dist/resource-monitor-LVE1BoLs.js
|
|
79877
|
+
var require_resource_monitor_LVE1BoLs = __commonJS({
|
|
79878
|
+
"../system/dist/resource-monitor-LVE1BoLs.js"(exports) {
|
|
79879
79879
|
"use strict";
|
|
79880
79880
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
79881
|
+
var require_builtins_native_metrics_native_metrics_addon = require_native_metrics_addon();
|
|
79881
79882
|
var node_child_process = __require("child_process");
|
|
79882
|
-
var
|
|
79883
|
-
node_fs = require_chunk.__toESM(node_fs);
|
|
79883
|
+
var node_os = __require("os");
|
|
79884
79884
|
var resource_monitor_exports = /* @__PURE__ */ require_chunk.__exportAll({
|
|
79885
79885
|
getPidStats: () => getPidStats,
|
|
79886
79886
|
getSinglePidStats: () => getSinglePidStats
|
|
79887
79887
|
});
|
|
79888
|
-
function readProcRss(pid) {
|
|
79889
|
-
try {
|
|
79890
|
-
const status = node_fs.readFileSync(`/proc/${pid}/status`, "utf8");
|
|
79891
|
-
const anon = status.match(/^RssAnon:\s+(\d+)/m);
|
|
79892
|
-
const file = status.match(/^RssFile:\s+(\d+)/m);
|
|
79893
|
-
return {
|
|
79894
|
-
privateBytes: anon ? parseInt(anon[1], 10) * 1024 : void 0,
|
|
79895
|
-
sharedBytes: file ? parseInt(file[1], 10) * 1024 : void 0
|
|
79896
|
-
};
|
|
79897
|
-
} catch {
|
|
79898
|
-
return {};
|
|
79899
|
-
}
|
|
79900
|
-
}
|
|
79901
79888
|
function execPsForPids(pids) {
|
|
79902
79889
|
return new Promise((resolve, reject) => {
|
|
79903
79890
|
(0, node_child_process.execFile)("ps", [
|
|
@@ -79911,6 +79898,11 @@ var require_resource_monitor_CdnzxBLP = __commonJS({
|
|
|
79911
79898
|
});
|
|
79912
79899
|
});
|
|
79913
79900
|
}
|
|
79901
|
+
var defaultDeps = {
|
|
79902
|
+
platform: (0, node_os.platform)(),
|
|
79903
|
+
reader: require_builtins_native_metrics_native_metrics_addon.nodeProcReader,
|
|
79904
|
+
spawnPs: execPsForPids
|
|
79905
|
+
};
|
|
79914
79906
|
function parsePsOutput(stdout) {
|
|
79915
79907
|
const result = /* @__PURE__ */ new Map();
|
|
79916
79908
|
for (const line of stdout.trim().split("\n")) {
|
|
@@ -79924,17 +79916,47 @@ var require_resource_monitor_CdnzxBLP = __commonJS({
|
|
|
79924
79916
|
if (isNaN(pid) || isNaN(cpu) || isNaN(rssKb)) continue;
|
|
79925
79917
|
result.set(pid, {
|
|
79926
79918
|
cpu: Math.round(cpu * 10) / 10,
|
|
79927
|
-
memory: rssKb * 1024
|
|
79928
|
-
...readProcRss(pid)
|
|
79919
|
+
memory: rssKb * 1024
|
|
79929
79920
|
});
|
|
79930
79921
|
}
|
|
79931
79922
|
return result;
|
|
79932
79923
|
}
|
|
79933
|
-
async function
|
|
79924
|
+
async function readProcPidStats(pid, uptimeSec, reader) {
|
|
79925
|
+
let stat;
|
|
79926
|
+
let status;
|
|
79927
|
+
try {
|
|
79928
|
+
[stat, status] = await Promise.all([reader.readStat(pid), reader.readStatus(pid)]);
|
|
79929
|
+
} catch {
|
|
79930
|
+
return null;
|
|
79931
|
+
}
|
|
79932
|
+
const parsed = require_builtins_native_metrics_native_metrics_addon.parseProcStat(stat);
|
|
79933
|
+
if (parsed === null) return null;
|
|
79934
|
+
const rss = require_builtins_native_metrics_native_metrics_addon.parseProcStatusRss(status);
|
|
79935
|
+
if (rss.rssBytes === void 0) return null;
|
|
79936
|
+
return {
|
|
79937
|
+
cpu: require_builtins_native_metrics_native_metrics_addon.lifetimeCpuPercent({
|
|
79938
|
+
ticks: parsed.ticks,
|
|
79939
|
+
startTicks: parsed.startTicks,
|
|
79940
|
+
uptimeSec
|
|
79941
|
+
}),
|
|
79942
|
+
memory: rss.rssBytes,
|
|
79943
|
+
privateBytes: rss.privateBytes,
|
|
79944
|
+
sharedBytes: rss.sharedBytes
|
|
79945
|
+
};
|
|
79946
|
+
}
|
|
79947
|
+
async function readProcPidStatsAll(pids, reader) {
|
|
79948
|
+
const uptimeSec = await reader.readUptimeSec();
|
|
79949
|
+
const entries = await Promise.all(pids.map(async (pid) => [pid, await readProcPidStats(pid, uptimeSec, reader)]));
|
|
79950
|
+
const result = /* @__PURE__ */ new Map();
|
|
79951
|
+
for (const [pid, stats] of entries) if (stats !== null) result.set(pid, stats);
|
|
79952
|
+
return result;
|
|
79953
|
+
}
|
|
79954
|
+
async function getPidStats(pids, deps = defaultDeps) {
|
|
79934
79955
|
const pidArray = typeof pids === "number" ? [pids] : [...pids];
|
|
79935
79956
|
if (pidArray.length === 0) return /* @__PURE__ */ new Map();
|
|
79936
79957
|
try {
|
|
79937
|
-
return
|
|
79958
|
+
if (deps.platform === "linux") return await readProcPidStatsAll(pidArray, deps.reader);
|
|
79959
|
+
return parsePsOutput(await deps.spawnPs(pidArray));
|
|
79938
79960
|
} catch {
|
|
79939
79961
|
return /* @__PURE__ */ new Map();
|
|
79940
79962
|
}
|
|
@@ -79972,14 +79994,14 @@ var require_native_metrics_addon = __commonJS({
|
|
|
79972
79994
|
[Symbol.toStringTag]: { value: "Module" }
|
|
79973
79995
|
});
|
|
79974
79996
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
79975
|
-
var require_dist10 =
|
|
79997
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
79976
79998
|
var node_fs_promises = __require("fs/promises");
|
|
79977
|
-
var node_child_process = __require("child_process");
|
|
79978
|
-
var node_util = __require("util");
|
|
79979
79999
|
var node_fs = __require("fs");
|
|
79980
80000
|
node_fs = require_chunk.__toESM(node_fs);
|
|
80001
|
+
var node_child_process = __require("child_process");
|
|
79981
80002
|
var node_os = __require("os");
|
|
79982
80003
|
node_os = require_chunk.__toESM(node_os);
|
|
80004
|
+
var node_util = __require("util");
|
|
79983
80005
|
var nodeCgroupFileReader = { read(path) {
|
|
79984
80006
|
try {
|
|
79985
80007
|
return (0, node_fs.readFileSync)(path, "utf8");
|
|
@@ -80825,470 +80847,6 @@ var require_native_metrics_addon = __commonJS({
|
|
|
80825
80847
|
}
|
|
80826
80848
|
}
|
|
80827
80849
|
};
|
|
80828
|
-
var IS_DARWIN = node_os.platform() === "darwin";
|
|
80829
|
-
var IS_LINUX = node_os.platform() === "linux";
|
|
80830
|
-
var NativeMetricsProvider = class {
|
|
80831
|
-
id = "native";
|
|
80832
|
-
cachedSnapshot = null;
|
|
80833
|
-
samplingTimer = null;
|
|
80834
|
-
macMemTimer = null;
|
|
80835
|
-
prevCpu;
|
|
80836
|
-
diagnostics = null;
|
|
80837
|
-
consecutiveSampleErrors = 0;
|
|
80838
|
-
constructor() {
|
|
80839
|
-
this.prevCpu = aggregateCpuTimes();
|
|
80840
|
-
}
|
|
80841
|
-
/**
|
|
80842
|
-
* Optional diagnostics sink for sampling errors. The first failure and
|
|
80843
|
-
* every Nth failure thereafter are reported so a permanently-broken
|
|
80844
|
-
* collector doesn't spam logs but is still observable.
|
|
80845
|
-
*/
|
|
80846
|
-
setDiagnostics(diag) {
|
|
80847
|
-
this.diagnostics = diag;
|
|
80848
|
-
}
|
|
80849
|
-
startSampling(intervalMs) {
|
|
80850
|
-
if (IS_DARWIN) {
|
|
80851
|
-
sampleMacMemory(this);
|
|
80852
|
-
this.macMemTimer = setInterval(() => sampleMacMemory(this), 5e3);
|
|
80853
|
-
if (this.macMemTimer.unref) this.macMemTimer.unref();
|
|
80854
|
-
}
|
|
80855
|
-
this.collectSnapshot().then((s) => {
|
|
80856
|
-
this.cachedSnapshot = s;
|
|
80857
|
-
this.consecutiveSampleErrors = 0;
|
|
80858
|
-
}).catch((err) => this.reportSampleError(err));
|
|
80859
|
-
this.samplingTimer = setInterval(() => {
|
|
80860
|
-
this.collectSnapshot().then((s) => {
|
|
80861
|
-
this.cachedSnapshot = s;
|
|
80862
|
-
this.consecutiveSampleErrors = 0;
|
|
80863
|
-
}).catch((err) => this.reportSampleError(err));
|
|
80864
|
-
}, intervalMs);
|
|
80865
|
-
if (this.samplingTimer.unref) this.samplingTimer.unref();
|
|
80866
|
-
}
|
|
80867
|
-
reportSampleError(err) {
|
|
80868
|
-
this.consecutiveSampleErrors++;
|
|
80869
|
-
if (!this.diagnostics) return;
|
|
80870
|
-
if (!(this.consecutiveSampleErrors === 1 || this.consecutiveSampleErrors % 60 === 0)) return;
|
|
80871
|
-
this.diagnostics.warn("metrics-provider sample failed", {
|
|
80872
|
-
consecutiveErrors: this.consecutiveSampleErrors,
|
|
80873
|
-
error: err instanceof Error ? err.message : String(err)
|
|
80874
|
-
});
|
|
80875
|
-
}
|
|
80876
|
-
stopSampling() {
|
|
80877
|
-
if (this.samplingTimer) {
|
|
80878
|
-
clearInterval(this.samplingTimer);
|
|
80879
|
-
this.samplingTimer = null;
|
|
80880
|
-
}
|
|
80881
|
-
if (this.macMemTimer) {
|
|
80882
|
-
clearInterval(this.macMemTimer);
|
|
80883
|
-
this.macMemTimer = null;
|
|
80884
|
-
}
|
|
80885
|
-
}
|
|
80886
|
-
async collectSnapshot() {
|
|
80887
|
-
const cpu = this.sampleCpu();
|
|
80888
|
-
const memory = this.getMemoryInfo();
|
|
80889
|
-
const processInfo = getProcessResources();
|
|
80890
|
-
const [gpu, network, disk, cpuTemp] = await Promise.all([
|
|
80891
|
-
getGpuInfoInternal().catch(() => null),
|
|
80892
|
-
takeNetworkIoSnapshot(),
|
|
80893
|
-
takeDiskIoSnapshot(),
|
|
80894
|
-
getCpuTemperatureInternal().catch(() => null)
|
|
80895
|
-
]);
|
|
80896
|
-
const snapshot = {
|
|
80897
|
-
cpu,
|
|
80898
|
-
memory,
|
|
80899
|
-
gpu,
|
|
80900
|
-
network,
|
|
80901
|
-
disk,
|
|
80902
|
-
pressure: {
|
|
80903
|
-
cpu: getPressure("cpu"),
|
|
80904
|
-
memory: getPressure("memory"),
|
|
80905
|
-
io: getPressure("io")
|
|
80906
|
-
},
|
|
80907
|
-
process: processInfo,
|
|
80908
|
-
cpuTemperature: cpuTemp,
|
|
80909
|
-
timestampMs: Date.now()
|
|
80910
|
-
};
|
|
80911
|
-
this.cachedSnapshot = snapshot;
|
|
80912
|
-
return snapshot;
|
|
80913
|
-
}
|
|
80914
|
-
async getCached() {
|
|
80915
|
-
return this.cachedSnapshot;
|
|
80916
|
-
}
|
|
80917
|
-
async getCurrent() {
|
|
80918
|
-
const s = this.cachedSnapshot ?? await this.collectSnapshot();
|
|
80919
|
-
const mb = (bytes) => Math.round(bytes / 1024 / 1024);
|
|
80920
|
-
return {
|
|
80921
|
-
cpuPercent: s.cpu.total,
|
|
80922
|
-
memoryPercent: s.memory.percent,
|
|
80923
|
-
memoryUsedMB: mb(s.memory.usedBytes),
|
|
80924
|
-
memoryTotalMB: mb(s.memory.totalBytes),
|
|
80925
|
-
temperature: s.cpuTemperature ?? void 0,
|
|
80926
|
-
gpuPercent: s.gpu?.utilization,
|
|
80927
|
-
gpuMemoryPercent: s.gpu && s.gpu.memoryTotalBytes > 0 ? Math.round(s.gpu.memoryUsedBytes / s.gpu.memoryTotalBytes * 1e3) / 10 : void 0
|
|
80928
|
-
};
|
|
80929
|
-
}
|
|
80930
|
-
async getDiskSpace(input) {
|
|
80931
|
-
return getDiskSpaceInternal(input.dirPath);
|
|
80932
|
-
}
|
|
80933
|
-
async getGpuInfo() {
|
|
80934
|
-
return getGpuInfoInternal();
|
|
80935
|
-
}
|
|
80936
|
-
async getCpuTemperature() {
|
|
80937
|
-
return getCpuTemperatureInternal();
|
|
80938
|
-
}
|
|
80939
|
-
async getProcessStats(input) {
|
|
80940
|
-
const { getPidStats } = await Promise.resolve().then(() => require_resource_monitor_CdnzxBLP()).then((n) => n.resource_monitor_exports);
|
|
80941
|
-
const raw = await getPidStats(input.pids);
|
|
80942
|
-
const result = [];
|
|
80943
|
-
for (const [pid, s] of raw) result.push({
|
|
80944
|
-
pid,
|
|
80945
|
-
cpu: s.cpu,
|
|
80946
|
-
memory: s.memory,
|
|
80947
|
-
privateBytes: s.privateBytes,
|
|
80948
|
-
sharedBytes: s.sharedBytes
|
|
80949
|
-
});
|
|
80950
|
-
return result;
|
|
80951
|
-
}
|
|
80952
|
-
sampleCpu() {
|
|
80953
|
-
const curr = aggregateCpuTimes();
|
|
80954
|
-
const prev = this.prevCpu;
|
|
80955
|
-
this.prevCpu = curr;
|
|
80956
|
-
const dUser = curr.user - prev.user;
|
|
80957
|
-
const dNice = curr.nice - prev.nice;
|
|
80958
|
-
const dSys = curr.sys - prev.sys;
|
|
80959
|
-
const dIrq = curr.irq - prev.irq;
|
|
80960
|
-
const dIdle = curr.idle - prev.idle;
|
|
80961
|
-
const dTotal = dUser + dNice + dSys + dIrq + dIdle;
|
|
80962
|
-
const pct = (v) => dTotal === 0 ? 0 : Math.round(v / dTotal * 1e3) / 10;
|
|
80963
|
-
return {
|
|
80964
|
-
total: pct(dUser + dNice + dSys + dIrq),
|
|
80965
|
-
user: pct(dUser),
|
|
80966
|
-
system: pct(dSys),
|
|
80967
|
-
irq: pct(dIrq),
|
|
80968
|
-
nice: pct(dNice),
|
|
80969
|
-
loadAvg: node_os.loadavg(),
|
|
80970
|
-
cores: node_os.cpus().length
|
|
80971
|
-
};
|
|
80972
|
-
}
|
|
80973
|
-
/** Cached macOS memory (set by sampleMacMemory timer). */
|
|
80974
|
-
_cachedMacMem = null;
|
|
80975
|
-
getMemoryInfo() {
|
|
80976
|
-
const total = node_os.totalmem();
|
|
80977
|
-
if (total === 0) return {
|
|
80978
|
-
percent: 0,
|
|
80979
|
-
totalBytes: 0,
|
|
80980
|
-
usedBytes: 0,
|
|
80981
|
-
availableBytes: 0,
|
|
80982
|
-
swapUsedBytes: 0,
|
|
80983
|
-
swapTotalBytes: 0
|
|
80984
|
-
};
|
|
80985
|
-
if (IS_DARWIN && this._cachedMacMem !== null) return this._cachedMacMem;
|
|
80986
|
-
const free = node_os.freemem();
|
|
80987
|
-
const used = total - free;
|
|
80988
|
-
let swapUsedBytes = 0;
|
|
80989
|
-
let swapTotalBytes = 0;
|
|
80990
|
-
if (IS_LINUX) try {
|
|
80991
|
-
const meminfo = node_fs.readFileSync("/proc/meminfo", "utf-8");
|
|
80992
|
-
const swapTotal = parseInt(meminfo.match(/SwapTotal:\s+(\d+)/)?.[1] ?? "0", 10) * 1024;
|
|
80993
|
-
const swapFree = parseInt(meminfo.match(/SwapFree:\s+(\d+)/)?.[1] ?? "0", 10) * 1024;
|
|
80994
|
-
swapTotalBytes = swapTotal;
|
|
80995
|
-
swapUsedBytes = swapTotal - swapFree;
|
|
80996
|
-
} catch {
|
|
80997
|
-
}
|
|
80998
|
-
return {
|
|
80999
|
-
percent: Math.round((total - free) / total * 1e3) / 10,
|
|
81000
|
-
totalBytes: total,
|
|
81001
|
-
usedBytes: used,
|
|
81002
|
-
availableBytes: free,
|
|
81003
|
-
swapUsedBytes,
|
|
81004
|
-
swapTotalBytes
|
|
81005
|
-
};
|
|
81006
|
-
}
|
|
81007
|
-
};
|
|
81008
|
-
function aggregateCpuTimes() {
|
|
81009
|
-
const cpus = node_os.cpus();
|
|
81010
|
-
let user = 0, nice = 0, sys = 0, irq = 0, idle = 0;
|
|
81011
|
-
for (const cpu of cpus) {
|
|
81012
|
-
user += cpu.times.user;
|
|
81013
|
-
nice += cpu.times.nice;
|
|
81014
|
-
sys += cpu.times.sys;
|
|
81015
|
-
irq += cpu.times.irq;
|
|
81016
|
-
idle += cpu.times.idle;
|
|
81017
|
-
}
|
|
81018
|
-
return {
|
|
81019
|
-
user,
|
|
81020
|
-
nice,
|
|
81021
|
-
sys,
|
|
81022
|
-
irq,
|
|
81023
|
-
idle
|
|
81024
|
-
};
|
|
81025
|
-
}
|
|
81026
|
-
function sampleMacMemory(provider) {
|
|
81027
|
-
try {
|
|
81028
|
-
const output = (0, node_child_process.execFileSync)("vm_stat", {
|
|
81029
|
-
timeout: 2e3,
|
|
81030
|
-
encoding: "utf-8"
|
|
81031
|
-
});
|
|
81032
|
-
const pageSize = 16384;
|
|
81033
|
-
const parse4 = (label) => {
|
|
81034
|
-
const match = output.match(new RegExp(`${label}:\\s+(\\d+)`));
|
|
81035
|
-
return match ? parseInt(match[1], 10) * pageSize : 0;
|
|
81036
|
-
};
|
|
81037
|
-
const free = parse4("Pages free");
|
|
81038
|
-
const inactive = parse4("Pages inactive");
|
|
81039
|
-
const purgeable = parse4("Pages purgeable");
|
|
81040
|
-
const speculative = parse4("Pages speculative");
|
|
81041
|
-
const available = free + inactive + purgeable + speculative;
|
|
81042
|
-
const total = node_os.totalmem();
|
|
81043
|
-
const used = total - available;
|
|
81044
|
-
let swapUsedBytes = 0;
|
|
81045
|
-
let swapTotalBytes = 0;
|
|
81046
|
-
try {
|
|
81047
|
-
const swapOut = (0, node_child_process.execFileSync)("sysctl", ["-n", "vm.swapusage"], {
|
|
81048
|
-
timeout: 2e3,
|
|
81049
|
-
encoding: "utf-8"
|
|
81050
|
-
});
|
|
81051
|
-
const totalMatch = swapOut.match(/total\s*=\s*([\d.]+)M/);
|
|
81052
|
-
const usedMatch = swapOut.match(/used\s*=\s*([\d.]+)M/);
|
|
81053
|
-
if (totalMatch) swapTotalBytes = parseFloat(totalMatch[1]) * 1024 * 1024;
|
|
81054
|
-
if (usedMatch) swapUsedBytes = parseFloat(usedMatch[1]) * 1024 * 1024;
|
|
81055
|
-
} catch {
|
|
81056
|
-
}
|
|
81057
|
-
provider._cachedMacMem = {
|
|
81058
|
-
percent: Math.round(used / total * 1e3) / 10,
|
|
81059
|
-
totalBytes: total,
|
|
81060
|
-
usedBytes: used,
|
|
81061
|
-
availableBytes: available,
|
|
81062
|
-
swapUsedBytes,
|
|
81063
|
-
swapTotalBytes
|
|
81064
|
-
};
|
|
81065
|
-
} catch {
|
|
81066
|
-
provider._cachedMacMem = null;
|
|
81067
|
-
}
|
|
81068
|
-
}
|
|
81069
|
-
function getDiskSpaceInternal(dirPath) {
|
|
81070
|
-
return new Promise((resolve, reject) => {
|
|
81071
|
-
node_fs.statfs(dirPath, (err, stats) => {
|
|
81072
|
-
if (err) return reject(err);
|
|
81073
|
-
const totalBytes = stats.blocks * stats.bsize;
|
|
81074
|
-
const availableBytes = stats.bavail * stats.bsize;
|
|
81075
|
-
const usedBytes = totalBytes - stats.bfree * stats.bsize;
|
|
81076
|
-
resolve({
|
|
81077
|
-
path: dirPath,
|
|
81078
|
-
totalBytes,
|
|
81079
|
-
usedBytes,
|
|
81080
|
-
availableBytes,
|
|
81081
|
-
percent: totalBytes > 0 ? Math.round(usedBytes / totalBytes * 1e3) / 10 : 0
|
|
81082
|
-
});
|
|
81083
|
-
});
|
|
81084
|
-
});
|
|
81085
|
-
}
|
|
81086
|
-
async function takeDiskIoSnapshot() {
|
|
81087
|
-
const now = Date.now();
|
|
81088
|
-
if (IS_LINUX) try {
|
|
81089
|
-
const data = node_fs.readFileSync("/proc/diskstats", "utf-8");
|
|
81090
|
-
let readOps = 0, readBytes = 0, writeOps = 0, writeBytes = 0;
|
|
81091
|
-
for (const line of data.split("\n")) {
|
|
81092
|
-
const parts = line.trim().split(/\s+/);
|
|
81093
|
-
if (parts.length < 14) continue;
|
|
81094
|
-
const devName = parts[2];
|
|
81095
|
-
if (/\d+$/.test(devName) && !/^nvme\d+n\d+$/.test(devName)) continue;
|
|
81096
|
-
readOps += parseInt(parts[3], 10) || 0;
|
|
81097
|
-
readBytes += (parseInt(parts[5], 10) || 0) * 512;
|
|
81098
|
-
writeOps += parseInt(parts[7], 10) || 0;
|
|
81099
|
-
writeBytes += (parseInt(parts[9], 10) || 0) * 512;
|
|
81100
|
-
}
|
|
81101
|
-
return {
|
|
81102
|
-
readBytes,
|
|
81103
|
-
writeBytes,
|
|
81104
|
-
readOps,
|
|
81105
|
-
writeOps,
|
|
81106
|
-
timestampMs: now
|
|
81107
|
-
};
|
|
81108
|
-
} catch {
|
|
81109
|
-
}
|
|
81110
|
-
return {
|
|
81111
|
-
readBytes: 0,
|
|
81112
|
-
writeBytes: 0,
|
|
81113
|
-
readOps: 0,
|
|
81114
|
-
writeOps: 0,
|
|
81115
|
-
timestampMs: now
|
|
81116
|
-
};
|
|
81117
|
-
}
|
|
81118
|
-
async function takeNetworkIoSnapshot() {
|
|
81119
|
-
const now = Date.now();
|
|
81120
|
-
if (IS_LINUX) try {
|
|
81121
|
-
const data = node_fs.readFileSync("/proc/net/dev", "utf-8");
|
|
81122
|
-
let rxBytes = 0, txBytes = 0, rxPackets = 0, txPackets = 0, rxErrors = 0, txErrors = 0;
|
|
81123
|
-
for (const line of data.split("\n")) {
|
|
81124
|
-
const match = line.match(/^\s*(\w+):\s+(.+)$/);
|
|
81125
|
-
if (!match) continue;
|
|
81126
|
-
if (match[1] === "lo") continue;
|
|
81127
|
-
const cols = match[2].trim().split(/\s+/);
|
|
81128
|
-
rxBytes += parseInt(cols[0], 10) || 0;
|
|
81129
|
-
rxPackets += parseInt(cols[1], 10) || 0;
|
|
81130
|
-
rxErrors += parseInt(cols[2], 10) || 0;
|
|
81131
|
-
txBytes += parseInt(cols[8], 10) || 0;
|
|
81132
|
-
txPackets += parseInt(cols[9], 10) || 0;
|
|
81133
|
-
txErrors += parseInt(cols[10], 10) || 0;
|
|
81134
|
-
}
|
|
81135
|
-
return {
|
|
81136
|
-
rxBytes,
|
|
81137
|
-
txBytes,
|
|
81138
|
-
rxPackets,
|
|
81139
|
-
txPackets,
|
|
81140
|
-
rxErrors,
|
|
81141
|
-
txErrors,
|
|
81142
|
-
timestampMs: now
|
|
81143
|
-
};
|
|
81144
|
-
} catch {
|
|
81145
|
-
}
|
|
81146
|
-
if (IS_DARWIN) try {
|
|
81147
|
-
const stdout = await execAsync("netstat", ["-ib"]);
|
|
81148
|
-
let rxBytes = 0, txBytes = 0, rxPackets = 0, txPackets = 0, rxErrors = 0, txErrors = 0;
|
|
81149
|
-
for (const line of stdout.split("\n")) {
|
|
81150
|
-
const parts = line.trim().split(/\s+/);
|
|
81151
|
-
if (parts.length < 11) continue;
|
|
81152
|
-
if (parts[0] === "lo0" || parts[0] === "Name") continue;
|
|
81153
|
-
if (!parts[2]?.startsWith("Link#")) continue;
|
|
81154
|
-
rxPackets += parseInt(parts[4], 10) || 0;
|
|
81155
|
-
rxErrors += parseInt(parts[5], 10) || 0;
|
|
81156
|
-
rxBytes += parseInt(parts[6], 10) || 0;
|
|
81157
|
-
txPackets += parseInt(parts[7], 10) || 0;
|
|
81158
|
-
txErrors += parseInt(parts[8], 10) || 0;
|
|
81159
|
-
txBytes += parseInt(parts[9], 10) || 0;
|
|
81160
|
-
}
|
|
81161
|
-
return {
|
|
81162
|
-
rxBytes,
|
|
81163
|
-
txBytes,
|
|
81164
|
-
rxPackets,
|
|
81165
|
-
txPackets,
|
|
81166
|
-
rxErrors,
|
|
81167
|
-
txErrors,
|
|
81168
|
-
timestampMs: now
|
|
81169
|
-
};
|
|
81170
|
-
} catch {
|
|
81171
|
-
}
|
|
81172
|
-
return {
|
|
81173
|
-
rxBytes: 0,
|
|
81174
|
-
txBytes: 0,
|
|
81175
|
-
rxPackets: 0,
|
|
81176
|
-
txPackets: 0,
|
|
81177
|
-
rxErrors: 0,
|
|
81178
|
-
txErrors: 0,
|
|
81179
|
-
timestampMs: now
|
|
81180
|
-
};
|
|
81181
|
-
}
|
|
81182
|
-
async function getCpuTemperatureInternal() {
|
|
81183
|
-
if (IS_LINUX) for (const p of ["/sys/class/thermal/thermal_zone0/temp", "/sys/class/hwmon/hwmon0/temp1_input"]) try {
|
|
81184
|
-
const raw = node_fs.readFileSync(p, "utf-8").trim();
|
|
81185
|
-
const millideg = parseInt(raw, 10);
|
|
81186
|
-
if (!isNaN(millideg)) return Math.round(millideg / 100) / 10;
|
|
81187
|
-
} catch {
|
|
81188
|
-
continue;
|
|
81189
|
-
}
|
|
81190
|
-
if (IS_DARWIN) try {
|
|
81191
|
-
const match = (await execAsync("sudo", [
|
|
81192
|
-
"-n",
|
|
81193
|
-
"powermetrics",
|
|
81194
|
-
"--samplers",
|
|
81195
|
-
"smc",
|
|
81196
|
-
"-i",
|
|
81197
|
-
"1",
|
|
81198
|
-
"-n",
|
|
81199
|
-
"1"
|
|
81200
|
-
], 3e3)).match(/CPU die temperature:\s+([\d.]+)\s*C/);
|
|
81201
|
-
if (match) return Math.round(parseFloat(match[1]) * 10) / 10;
|
|
81202
|
-
} catch {
|
|
81203
|
-
}
|
|
81204
|
-
return null;
|
|
81205
|
-
}
|
|
81206
|
-
async function getGpuInfoInternal() {
|
|
81207
|
-
if (IS_DARWIN) try {
|
|
81208
|
-
const utilMatch = (await execAsync("ioreg", [
|
|
81209
|
-
"-r",
|
|
81210
|
-
"-d",
|
|
81211
|
-
"1",
|
|
81212
|
-
"-c",
|
|
81213
|
-
"IOAccelerator"
|
|
81214
|
-
])).match(/"GPU Core Utilization"\s*=\s*(\d+)/);
|
|
81215
|
-
const util = utilMatch ? parseInt(utilMatch[1], 10) : 0;
|
|
81216
|
-
const utilPct = util > 1e3 ? Math.round(util / 1e7) : util;
|
|
81217
|
-
return {
|
|
81218
|
-
utilization: Math.min(100, utilPct),
|
|
81219
|
-
model: "Apple Silicon GPU",
|
|
81220
|
-
memoryUsedBytes: 0,
|
|
81221
|
-
memoryTotalBytes: 0,
|
|
81222
|
-
temperature: null
|
|
81223
|
-
};
|
|
81224
|
-
} catch {
|
|
81225
|
-
}
|
|
81226
|
-
if (IS_LINUX) try {
|
|
81227
|
-
const parts = (await execAsync("nvidia-smi", ["--query-gpu=utilization.gpu,name,memory.used,memory.total,temperature.gpu", "--format=csv,noheader,nounits"])).trim().split(",").map((s) => s.trim());
|
|
81228
|
-
if (parts.length >= 5) return {
|
|
81229
|
-
utilization: parseInt(parts[0], 10) || 0,
|
|
81230
|
-
model: parts[1] ?? "Unknown GPU",
|
|
81231
|
-
memoryUsedBytes: (parseInt(parts[2], 10) || 0) * 1024 * 1024,
|
|
81232
|
-
memoryTotalBytes: (parseInt(parts[3], 10) || 0) * 1024 * 1024,
|
|
81233
|
-
temperature: parseInt(parts[4], 10) || null
|
|
81234
|
-
};
|
|
81235
|
-
} catch {
|
|
81236
|
-
}
|
|
81237
|
-
return null;
|
|
81238
|
-
}
|
|
81239
|
-
function getProcessResources() {
|
|
81240
|
-
let openFds = 0;
|
|
81241
|
-
let threadCount = 0;
|
|
81242
|
-
if (IS_LINUX) {
|
|
81243
|
-
try {
|
|
81244
|
-
openFds = node_fs.readdirSync(`/proc/${process.pid}/fd`).length;
|
|
81245
|
-
} catch {
|
|
81246
|
-
}
|
|
81247
|
-
try {
|
|
81248
|
-
const match = node_fs.readFileSync(`/proc/${process.pid}/status`, "utf-8").match(/Threads:\s+(\d+)/);
|
|
81249
|
-
if (match) threadCount = parseInt(match[1], 10);
|
|
81250
|
-
} catch {
|
|
81251
|
-
}
|
|
81252
|
-
}
|
|
81253
|
-
const nodeProcess = process;
|
|
81254
|
-
return {
|
|
81255
|
-
openFds,
|
|
81256
|
-
threadCount,
|
|
81257
|
-
activeHandles: (nodeProcess._getActiveHandles?.() ?? []).length,
|
|
81258
|
-
activeRequests: (nodeProcess._getActiveRequests?.() ?? []).length
|
|
81259
|
-
};
|
|
81260
|
-
}
|
|
81261
|
-
function getPressure(resource) {
|
|
81262
|
-
if (!IS_LINUX) return null;
|
|
81263
|
-
try {
|
|
81264
|
-
const data = node_fs.readFileSync(`/proc/pressure/${resource}`, "utf-8");
|
|
81265
|
-
const parseLine = (prefix) => {
|
|
81266
|
-
const match = data.match(new RegExp(`${prefix} avg10=(\\d+\\.\\d+) avg60=(\\d+\\.\\d+) avg300=(\\d+\\.\\d+)`));
|
|
81267
|
-
if (!match) return null;
|
|
81268
|
-
return {
|
|
81269
|
-
avg10: parseFloat(match[1]),
|
|
81270
|
-
avg60: parseFloat(match[2]),
|
|
81271
|
-
avg300: parseFloat(match[3])
|
|
81272
|
-
};
|
|
81273
|
-
};
|
|
81274
|
-
const some = parseLine("some");
|
|
81275
|
-
if (!some) return null;
|
|
81276
|
-
return {
|
|
81277
|
-
some,
|
|
81278
|
-
full: parseLine("full")
|
|
81279
|
-
};
|
|
81280
|
-
} catch {
|
|
81281
|
-
return null;
|
|
81282
|
-
}
|
|
81283
|
-
}
|
|
81284
|
-
function execAsync(cmd, args, timeoutMs = 5e3) {
|
|
81285
|
-
return new Promise((resolve, reject) => {
|
|
81286
|
-
(0, node_child_process.execFile)(cmd, args, { timeout: timeoutMs }, (err, stdout) => {
|
|
81287
|
-
if (err) return reject(err);
|
|
81288
|
-
resolve(stdout);
|
|
81289
|
-
});
|
|
81290
|
-
});
|
|
81291
|
-
}
|
|
81292
80850
|
var LOAD_SERIES_COLLECTION = "metrics:node-load-samples";
|
|
81293
80851
|
var DEFAULT_MAX_ROWS = 5e5;
|
|
81294
80852
|
var LOAD_SERIES_COLUMNS = [
|
|
@@ -81801,6 +81359,657 @@ var require_native_metrics_addon = __commonJS({
|
|
|
81801
81359
|
oldestAtMs
|
|
81802
81360
|
};
|
|
81803
81361
|
}
|
|
81362
|
+
var nodeAccessCheck = (path) => (0, node_fs_promises.access)(path, node_fs.constants.X_OK);
|
|
81363
|
+
async function findOnPath(binary, pathEnv, check = nodeAccessCheck) {
|
|
81364
|
+
const dirs = (pathEnv ?? "").split(":").filter((dir) => dir.length > 0);
|
|
81365
|
+
for (const dir of dirs) {
|
|
81366
|
+
const candidate = `${dir}/${binary}`;
|
|
81367
|
+
try {
|
|
81368
|
+
await check(candidate);
|
|
81369
|
+
return candidate;
|
|
81370
|
+
} catch {
|
|
81371
|
+
}
|
|
81372
|
+
}
|
|
81373
|
+
return null;
|
|
81374
|
+
}
|
|
81375
|
+
var NVIDIA_SMI_ARGS = ["--query-gpu=utilization.gpu,name,memory.used,memory.total,temperature.gpu", "--format=csv,noheader,nounits"];
|
|
81376
|
+
async function readNvidiaGpu(deps) {
|
|
81377
|
+
const binary = await deps.findOnPath("nvidia-smi");
|
|
81378
|
+
if (binary === null) return null;
|
|
81379
|
+
let stdout;
|
|
81380
|
+
try {
|
|
81381
|
+
stdout = await deps.exec(binary, NVIDIA_SMI_ARGS);
|
|
81382
|
+
} catch {
|
|
81383
|
+
return null;
|
|
81384
|
+
}
|
|
81385
|
+
const parts = stdout.trim().split(",").map((s) => s.trim());
|
|
81386
|
+
if (parts.length < 5) return null;
|
|
81387
|
+
return {
|
|
81388
|
+
utilization: parseInt(parts[0], 10) || 0,
|
|
81389
|
+
model: parts[1] ?? "Unknown GPU",
|
|
81390
|
+
memoryUsedBytes: (parseInt(parts[2], 10) || 0) * 1024 * 1024,
|
|
81391
|
+
memoryTotalBytes: (parseInt(parts[3], 10) || 0) * 1024 * 1024,
|
|
81392
|
+
temperature: parseInt(parts[4], 10) || null
|
|
81393
|
+
};
|
|
81394
|
+
}
|
|
81395
|
+
var IS_DARWIN = node_os.platform() === "darwin";
|
|
81396
|
+
var IS_LINUX = node_os.platform() === "linux";
|
|
81397
|
+
var NativeMetricsProvider = class {
|
|
81398
|
+
id = "native";
|
|
81399
|
+
cachedSnapshot = null;
|
|
81400
|
+
samplingTimer = null;
|
|
81401
|
+
macMemTimer = null;
|
|
81402
|
+
prevCpu;
|
|
81403
|
+
diagnostics = null;
|
|
81404
|
+
consecutiveSampleErrors = 0;
|
|
81405
|
+
constructor() {
|
|
81406
|
+
this.prevCpu = aggregateCpuTimes();
|
|
81407
|
+
}
|
|
81408
|
+
/**
|
|
81409
|
+
* Optional diagnostics sink for sampling errors. The first failure and
|
|
81410
|
+
* every Nth failure thereafter are reported so a permanently-broken
|
|
81411
|
+
* collector doesn't spam logs but is still observable.
|
|
81412
|
+
*/
|
|
81413
|
+
setDiagnostics(diag) {
|
|
81414
|
+
this.diagnostics = diag;
|
|
81415
|
+
}
|
|
81416
|
+
startSampling(intervalMs) {
|
|
81417
|
+
if (IS_DARWIN) {
|
|
81418
|
+
sampleMacMemory(this);
|
|
81419
|
+
this.macMemTimer = setInterval(() => sampleMacMemory(this), 5e3);
|
|
81420
|
+
if (this.macMemTimer.unref) this.macMemTimer.unref();
|
|
81421
|
+
}
|
|
81422
|
+
this.collectSnapshot().then((s) => {
|
|
81423
|
+
this.cachedSnapshot = s;
|
|
81424
|
+
this.consecutiveSampleErrors = 0;
|
|
81425
|
+
}).catch((err) => this.reportSampleError(err));
|
|
81426
|
+
this.samplingTimer = setInterval(() => {
|
|
81427
|
+
this.collectSnapshot().then((s) => {
|
|
81428
|
+
this.cachedSnapshot = s;
|
|
81429
|
+
this.consecutiveSampleErrors = 0;
|
|
81430
|
+
}).catch((err) => this.reportSampleError(err));
|
|
81431
|
+
}, intervalMs);
|
|
81432
|
+
if (this.samplingTimer.unref) this.samplingTimer.unref();
|
|
81433
|
+
}
|
|
81434
|
+
reportSampleError(err) {
|
|
81435
|
+
this.consecutiveSampleErrors++;
|
|
81436
|
+
if (!this.diagnostics) return;
|
|
81437
|
+
if (!(this.consecutiveSampleErrors === 1 || this.consecutiveSampleErrors % 60 === 0)) return;
|
|
81438
|
+
this.diagnostics.warn("metrics-provider sample failed", {
|
|
81439
|
+
consecutiveErrors: this.consecutiveSampleErrors,
|
|
81440
|
+
error: err instanceof Error ? err.message : String(err)
|
|
81441
|
+
});
|
|
81442
|
+
}
|
|
81443
|
+
stopSampling() {
|
|
81444
|
+
if (this.samplingTimer) {
|
|
81445
|
+
clearInterval(this.samplingTimer);
|
|
81446
|
+
this.samplingTimer = null;
|
|
81447
|
+
}
|
|
81448
|
+
if (this.macMemTimer) {
|
|
81449
|
+
clearInterval(this.macMemTimer);
|
|
81450
|
+
this.macMemTimer = null;
|
|
81451
|
+
}
|
|
81452
|
+
}
|
|
81453
|
+
async collectSnapshot() {
|
|
81454
|
+
const cpu = this.sampleCpu();
|
|
81455
|
+
const memory = this.getMemoryInfo();
|
|
81456
|
+
const processInfo = getProcessResources();
|
|
81457
|
+
const [gpu, network, disk, cpuTemp] = await Promise.all([
|
|
81458
|
+
getGpuInfoInternal().catch(() => null),
|
|
81459
|
+
takeNetworkIoSnapshot(),
|
|
81460
|
+
takeDiskIoSnapshot(),
|
|
81461
|
+
getCpuTemperatureInternal().catch(() => null)
|
|
81462
|
+
]);
|
|
81463
|
+
const snapshot = {
|
|
81464
|
+
cpu,
|
|
81465
|
+
memory,
|
|
81466
|
+
gpu,
|
|
81467
|
+
network,
|
|
81468
|
+
disk,
|
|
81469
|
+
pressure: {
|
|
81470
|
+
cpu: getPressure("cpu"),
|
|
81471
|
+
memory: getPressure("memory"),
|
|
81472
|
+
io: getPressure("io")
|
|
81473
|
+
},
|
|
81474
|
+
process: processInfo,
|
|
81475
|
+
cpuTemperature: cpuTemp,
|
|
81476
|
+
timestampMs: Date.now()
|
|
81477
|
+
};
|
|
81478
|
+
this.cachedSnapshot = snapshot;
|
|
81479
|
+
return snapshot;
|
|
81480
|
+
}
|
|
81481
|
+
async getCached() {
|
|
81482
|
+
return this.cachedSnapshot;
|
|
81483
|
+
}
|
|
81484
|
+
async getCurrent() {
|
|
81485
|
+
const s = this.cachedSnapshot ?? await this.collectSnapshot();
|
|
81486
|
+
const mb = (bytes) => Math.round(bytes / 1024 / 1024);
|
|
81487
|
+
return {
|
|
81488
|
+
cpuPercent: s.cpu.total,
|
|
81489
|
+
memoryPercent: s.memory.percent,
|
|
81490
|
+
memoryUsedMB: mb(s.memory.usedBytes),
|
|
81491
|
+
memoryTotalMB: mb(s.memory.totalBytes),
|
|
81492
|
+
temperature: s.cpuTemperature ?? void 0,
|
|
81493
|
+
gpuPercent: s.gpu?.utilization,
|
|
81494
|
+
gpuMemoryPercent: s.gpu && s.gpu.memoryTotalBytes > 0 ? Math.round(s.gpu.memoryUsedBytes / s.gpu.memoryTotalBytes * 1e3) / 10 : void 0
|
|
81495
|
+
};
|
|
81496
|
+
}
|
|
81497
|
+
async getDiskSpace(input) {
|
|
81498
|
+
return getDiskSpaceInternal(input.dirPath);
|
|
81499
|
+
}
|
|
81500
|
+
async getGpuInfo() {
|
|
81501
|
+
return getGpuInfoInternal();
|
|
81502
|
+
}
|
|
81503
|
+
async getCpuTemperature() {
|
|
81504
|
+
return getCpuTemperatureInternal();
|
|
81505
|
+
}
|
|
81506
|
+
async getProcessStats(input) {
|
|
81507
|
+
const { getPidStats } = await Promise.resolve().then(() => require_resource_monitor_LVE1BoLs()).then((n) => n.resource_monitor_exports);
|
|
81508
|
+
const raw = await getPidStats(input.pids);
|
|
81509
|
+
const result = [];
|
|
81510
|
+
for (const [pid, s] of raw) result.push({
|
|
81511
|
+
pid,
|
|
81512
|
+
cpu: s.cpu,
|
|
81513
|
+
memory: s.memory,
|
|
81514
|
+
privateBytes: s.privateBytes,
|
|
81515
|
+
sharedBytes: s.sharedBytes
|
|
81516
|
+
});
|
|
81517
|
+
return result;
|
|
81518
|
+
}
|
|
81519
|
+
sampleCpu() {
|
|
81520
|
+
const curr = aggregateCpuTimes();
|
|
81521
|
+
const prev = this.prevCpu;
|
|
81522
|
+
this.prevCpu = curr;
|
|
81523
|
+
const dUser = curr.user - prev.user;
|
|
81524
|
+
const dNice = curr.nice - prev.nice;
|
|
81525
|
+
const dSys = curr.sys - prev.sys;
|
|
81526
|
+
const dIrq = curr.irq - prev.irq;
|
|
81527
|
+
const dIdle = curr.idle - prev.idle;
|
|
81528
|
+
const dTotal = dUser + dNice + dSys + dIrq + dIdle;
|
|
81529
|
+
const pct = (v) => dTotal === 0 ? 0 : Math.round(v / dTotal * 1e3) / 10;
|
|
81530
|
+
return {
|
|
81531
|
+
total: pct(dUser + dNice + dSys + dIrq),
|
|
81532
|
+
user: pct(dUser),
|
|
81533
|
+
system: pct(dSys),
|
|
81534
|
+
irq: pct(dIrq),
|
|
81535
|
+
nice: pct(dNice),
|
|
81536
|
+
loadAvg: node_os.loadavg(),
|
|
81537
|
+
cores: node_os.cpus().length
|
|
81538
|
+
};
|
|
81539
|
+
}
|
|
81540
|
+
/** Cached macOS memory (set by sampleMacMemory timer). */
|
|
81541
|
+
_cachedMacMem = null;
|
|
81542
|
+
getMemoryInfo() {
|
|
81543
|
+
const total = node_os.totalmem();
|
|
81544
|
+
if (total === 0) return {
|
|
81545
|
+
percent: 0,
|
|
81546
|
+
totalBytes: 0,
|
|
81547
|
+
usedBytes: 0,
|
|
81548
|
+
availableBytes: 0,
|
|
81549
|
+
swapUsedBytes: 0,
|
|
81550
|
+
swapTotalBytes: 0
|
|
81551
|
+
};
|
|
81552
|
+
if (IS_DARWIN && this._cachedMacMem !== null) return this._cachedMacMem;
|
|
81553
|
+
const free = node_os.freemem();
|
|
81554
|
+
const used = total - free;
|
|
81555
|
+
let swapUsedBytes = 0;
|
|
81556
|
+
let swapTotalBytes = 0;
|
|
81557
|
+
if (IS_LINUX) try {
|
|
81558
|
+
const meminfo = node_fs.readFileSync("/proc/meminfo", "utf-8");
|
|
81559
|
+
const swapTotal = parseInt(meminfo.match(/SwapTotal:\s+(\d+)/)?.[1] ?? "0", 10) * 1024;
|
|
81560
|
+
const swapFree = parseInt(meminfo.match(/SwapFree:\s+(\d+)/)?.[1] ?? "0", 10) * 1024;
|
|
81561
|
+
swapTotalBytes = swapTotal;
|
|
81562
|
+
swapUsedBytes = swapTotal - swapFree;
|
|
81563
|
+
} catch {
|
|
81564
|
+
}
|
|
81565
|
+
return {
|
|
81566
|
+
percent: Math.round((total - free) / total * 1e3) / 10,
|
|
81567
|
+
totalBytes: total,
|
|
81568
|
+
usedBytes: used,
|
|
81569
|
+
availableBytes: free,
|
|
81570
|
+
swapUsedBytes,
|
|
81571
|
+
swapTotalBytes
|
|
81572
|
+
};
|
|
81573
|
+
}
|
|
81574
|
+
};
|
|
81575
|
+
function aggregateCpuTimes() {
|
|
81576
|
+
const cpus = node_os.cpus();
|
|
81577
|
+
let user = 0, nice = 0, sys = 0, irq = 0, idle = 0;
|
|
81578
|
+
for (const cpu of cpus) {
|
|
81579
|
+
user += cpu.times.user;
|
|
81580
|
+
nice += cpu.times.nice;
|
|
81581
|
+
sys += cpu.times.sys;
|
|
81582
|
+
irq += cpu.times.irq;
|
|
81583
|
+
idle += cpu.times.idle;
|
|
81584
|
+
}
|
|
81585
|
+
return {
|
|
81586
|
+
user,
|
|
81587
|
+
nice,
|
|
81588
|
+
sys,
|
|
81589
|
+
irq,
|
|
81590
|
+
idle
|
|
81591
|
+
};
|
|
81592
|
+
}
|
|
81593
|
+
function sampleMacMemory(provider) {
|
|
81594
|
+
try {
|
|
81595
|
+
const output = (0, node_child_process.execFileSync)("vm_stat", {
|
|
81596
|
+
timeout: 2e3,
|
|
81597
|
+
encoding: "utf-8"
|
|
81598
|
+
});
|
|
81599
|
+
const pageSize = 16384;
|
|
81600
|
+
const parse4 = (label) => {
|
|
81601
|
+
const match = output.match(new RegExp(`${label}:\\s+(\\d+)`));
|
|
81602
|
+
return match ? parseInt(match[1], 10) * pageSize : 0;
|
|
81603
|
+
};
|
|
81604
|
+
const free = parse4("Pages free");
|
|
81605
|
+
const inactive = parse4("Pages inactive");
|
|
81606
|
+
const purgeable = parse4("Pages purgeable");
|
|
81607
|
+
const speculative = parse4("Pages speculative");
|
|
81608
|
+
const available = free + inactive + purgeable + speculative;
|
|
81609
|
+
const total = node_os.totalmem();
|
|
81610
|
+
const used = total - available;
|
|
81611
|
+
let swapUsedBytes = 0;
|
|
81612
|
+
let swapTotalBytes = 0;
|
|
81613
|
+
try {
|
|
81614
|
+
const swapOut = (0, node_child_process.execFileSync)("sysctl", ["-n", "vm.swapusage"], {
|
|
81615
|
+
timeout: 2e3,
|
|
81616
|
+
encoding: "utf-8"
|
|
81617
|
+
});
|
|
81618
|
+
const totalMatch = swapOut.match(/total\s*=\s*([\d.]+)M/);
|
|
81619
|
+
const usedMatch = swapOut.match(/used\s*=\s*([\d.]+)M/);
|
|
81620
|
+
if (totalMatch) swapTotalBytes = parseFloat(totalMatch[1]) * 1024 * 1024;
|
|
81621
|
+
if (usedMatch) swapUsedBytes = parseFloat(usedMatch[1]) * 1024 * 1024;
|
|
81622
|
+
} catch {
|
|
81623
|
+
}
|
|
81624
|
+
provider._cachedMacMem = {
|
|
81625
|
+
percent: Math.round(used / total * 1e3) / 10,
|
|
81626
|
+
totalBytes: total,
|
|
81627
|
+
usedBytes: used,
|
|
81628
|
+
availableBytes: available,
|
|
81629
|
+
swapUsedBytes,
|
|
81630
|
+
swapTotalBytes
|
|
81631
|
+
};
|
|
81632
|
+
} catch {
|
|
81633
|
+
provider._cachedMacMem = null;
|
|
81634
|
+
}
|
|
81635
|
+
}
|
|
81636
|
+
function getDiskSpaceInternal(dirPath) {
|
|
81637
|
+
return new Promise((resolve, reject) => {
|
|
81638
|
+
node_fs.statfs(dirPath, (err, stats) => {
|
|
81639
|
+
if (err) return reject(err);
|
|
81640
|
+
const totalBytes = stats.blocks * stats.bsize;
|
|
81641
|
+
const availableBytes = stats.bavail * stats.bsize;
|
|
81642
|
+
const usedBytes = totalBytes - stats.bfree * stats.bsize;
|
|
81643
|
+
resolve({
|
|
81644
|
+
path: dirPath,
|
|
81645
|
+
totalBytes,
|
|
81646
|
+
usedBytes,
|
|
81647
|
+
availableBytes,
|
|
81648
|
+
percent: totalBytes > 0 ? Math.round(usedBytes / totalBytes * 1e3) / 10 : 0
|
|
81649
|
+
});
|
|
81650
|
+
});
|
|
81651
|
+
});
|
|
81652
|
+
}
|
|
81653
|
+
async function takeDiskIoSnapshot() {
|
|
81654
|
+
const now = Date.now();
|
|
81655
|
+
if (IS_LINUX) try {
|
|
81656
|
+
const data = node_fs.readFileSync("/proc/diskstats", "utf-8");
|
|
81657
|
+
let readOps = 0, readBytes = 0, writeOps = 0, writeBytes = 0;
|
|
81658
|
+
for (const line of data.split("\n")) {
|
|
81659
|
+
const parts = line.trim().split(/\s+/);
|
|
81660
|
+
if (parts.length < 14) continue;
|
|
81661
|
+
const devName = parts[2];
|
|
81662
|
+
if (/\d+$/.test(devName) && !/^nvme\d+n\d+$/.test(devName)) continue;
|
|
81663
|
+
readOps += parseInt(parts[3], 10) || 0;
|
|
81664
|
+
readBytes += (parseInt(parts[5], 10) || 0) * 512;
|
|
81665
|
+
writeOps += parseInt(parts[7], 10) || 0;
|
|
81666
|
+
writeBytes += (parseInt(parts[9], 10) || 0) * 512;
|
|
81667
|
+
}
|
|
81668
|
+
return {
|
|
81669
|
+
readBytes,
|
|
81670
|
+
writeBytes,
|
|
81671
|
+
readOps,
|
|
81672
|
+
writeOps,
|
|
81673
|
+
timestampMs: now
|
|
81674
|
+
};
|
|
81675
|
+
} catch {
|
|
81676
|
+
}
|
|
81677
|
+
return {
|
|
81678
|
+
readBytes: 0,
|
|
81679
|
+
writeBytes: 0,
|
|
81680
|
+
readOps: 0,
|
|
81681
|
+
writeOps: 0,
|
|
81682
|
+
timestampMs: now
|
|
81683
|
+
};
|
|
81684
|
+
}
|
|
81685
|
+
async function takeNetworkIoSnapshot() {
|
|
81686
|
+
const now = Date.now();
|
|
81687
|
+
if (IS_LINUX) try {
|
|
81688
|
+
const data = node_fs.readFileSync("/proc/net/dev", "utf-8");
|
|
81689
|
+
let rxBytes = 0, txBytes = 0, rxPackets = 0, txPackets = 0, rxErrors = 0, txErrors = 0;
|
|
81690
|
+
for (const line of data.split("\n")) {
|
|
81691
|
+
const match = line.match(/^\s*(\w+):\s+(.+)$/);
|
|
81692
|
+
if (!match) continue;
|
|
81693
|
+
if (match[1] === "lo") continue;
|
|
81694
|
+
const cols = match[2].trim().split(/\s+/);
|
|
81695
|
+
rxBytes += parseInt(cols[0], 10) || 0;
|
|
81696
|
+
rxPackets += parseInt(cols[1], 10) || 0;
|
|
81697
|
+
rxErrors += parseInt(cols[2], 10) || 0;
|
|
81698
|
+
txBytes += parseInt(cols[8], 10) || 0;
|
|
81699
|
+
txPackets += parseInt(cols[9], 10) || 0;
|
|
81700
|
+
txErrors += parseInt(cols[10], 10) || 0;
|
|
81701
|
+
}
|
|
81702
|
+
return {
|
|
81703
|
+
rxBytes,
|
|
81704
|
+
txBytes,
|
|
81705
|
+
rxPackets,
|
|
81706
|
+
txPackets,
|
|
81707
|
+
rxErrors,
|
|
81708
|
+
txErrors,
|
|
81709
|
+
timestampMs: now
|
|
81710
|
+
};
|
|
81711
|
+
} catch {
|
|
81712
|
+
}
|
|
81713
|
+
if (IS_DARWIN) try {
|
|
81714
|
+
const stdout = await execAsync("netstat", ["-ib"]);
|
|
81715
|
+
let rxBytes = 0, txBytes = 0, rxPackets = 0, txPackets = 0, rxErrors = 0, txErrors = 0;
|
|
81716
|
+
for (const line of stdout.split("\n")) {
|
|
81717
|
+
const parts = line.trim().split(/\s+/);
|
|
81718
|
+
if (parts.length < 11) continue;
|
|
81719
|
+
if (parts[0] === "lo0" || parts[0] === "Name") continue;
|
|
81720
|
+
if (!parts[2]?.startsWith("Link#")) continue;
|
|
81721
|
+
rxPackets += parseInt(parts[4], 10) || 0;
|
|
81722
|
+
rxErrors += parseInt(parts[5], 10) || 0;
|
|
81723
|
+
rxBytes += parseInt(parts[6], 10) || 0;
|
|
81724
|
+
txPackets += parseInt(parts[7], 10) || 0;
|
|
81725
|
+
txErrors += parseInt(parts[8], 10) || 0;
|
|
81726
|
+
txBytes += parseInt(parts[9], 10) || 0;
|
|
81727
|
+
}
|
|
81728
|
+
return {
|
|
81729
|
+
rxBytes,
|
|
81730
|
+
txBytes,
|
|
81731
|
+
rxPackets,
|
|
81732
|
+
txPackets,
|
|
81733
|
+
rxErrors,
|
|
81734
|
+
txErrors,
|
|
81735
|
+
timestampMs: now
|
|
81736
|
+
};
|
|
81737
|
+
} catch {
|
|
81738
|
+
}
|
|
81739
|
+
return {
|
|
81740
|
+
rxBytes: 0,
|
|
81741
|
+
txBytes: 0,
|
|
81742
|
+
rxPackets: 0,
|
|
81743
|
+
txPackets: 0,
|
|
81744
|
+
rxErrors: 0,
|
|
81745
|
+
txErrors: 0,
|
|
81746
|
+
timestampMs: now
|
|
81747
|
+
};
|
|
81748
|
+
}
|
|
81749
|
+
async function getCpuTemperatureInternal() {
|
|
81750
|
+
if (IS_LINUX) for (const p of ["/sys/class/thermal/thermal_zone0/temp", "/sys/class/hwmon/hwmon0/temp1_input"]) try {
|
|
81751
|
+
const raw = node_fs.readFileSync(p, "utf-8").trim();
|
|
81752
|
+
const millideg = parseInt(raw, 10);
|
|
81753
|
+
if (!isNaN(millideg)) return Math.round(millideg / 100) / 10;
|
|
81754
|
+
} catch {
|
|
81755
|
+
continue;
|
|
81756
|
+
}
|
|
81757
|
+
if (IS_DARWIN) try {
|
|
81758
|
+
const match = (await execAsync("sudo", [
|
|
81759
|
+
"-n",
|
|
81760
|
+
"powermetrics",
|
|
81761
|
+
"--samplers",
|
|
81762
|
+
"smc",
|
|
81763
|
+
"-i",
|
|
81764
|
+
"1",
|
|
81765
|
+
"-n",
|
|
81766
|
+
"1"
|
|
81767
|
+
], 3e3)).match(/CPU die temperature:\s+([\d.]+)\s*C/);
|
|
81768
|
+
if (match) return Math.round(parseFloat(match[1]) * 10) / 10;
|
|
81769
|
+
} catch {
|
|
81770
|
+
}
|
|
81771
|
+
return null;
|
|
81772
|
+
}
|
|
81773
|
+
async function getGpuInfoInternal() {
|
|
81774
|
+
if (IS_DARWIN) try {
|
|
81775
|
+
const utilMatch = (await execAsync("ioreg", [
|
|
81776
|
+
"-r",
|
|
81777
|
+
"-d",
|
|
81778
|
+
"1",
|
|
81779
|
+
"-c",
|
|
81780
|
+
"IOAccelerator"
|
|
81781
|
+
])).match(/"GPU Core Utilization"\s*=\s*(\d+)/);
|
|
81782
|
+
const util = utilMatch ? parseInt(utilMatch[1], 10) : 0;
|
|
81783
|
+
const utilPct = util > 1e3 ? Math.round(util / 1e7) : util;
|
|
81784
|
+
return {
|
|
81785
|
+
utilization: Math.min(100, utilPct),
|
|
81786
|
+
model: "Apple Silicon GPU",
|
|
81787
|
+
memoryUsedBytes: 0,
|
|
81788
|
+
memoryTotalBytes: 0,
|
|
81789
|
+
temperature: null
|
|
81790
|
+
};
|
|
81791
|
+
} catch {
|
|
81792
|
+
}
|
|
81793
|
+
if (IS_LINUX) return readNvidiaGpu({
|
|
81794
|
+
findOnPath: (binary) => findOnPath(binary, process.env["PATH"]),
|
|
81795
|
+
exec: (command, args) => execAsync(command, [...args])
|
|
81796
|
+
});
|
|
81797
|
+
return null;
|
|
81798
|
+
}
|
|
81799
|
+
function getProcessResources() {
|
|
81800
|
+
let openFds = 0;
|
|
81801
|
+
let threadCount = 0;
|
|
81802
|
+
if (IS_LINUX) {
|
|
81803
|
+
try {
|
|
81804
|
+
openFds = node_fs.readdirSync(`/proc/${process.pid}/fd`).length;
|
|
81805
|
+
} catch {
|
|
81806
|
+
}
|
|
81807
|
+
try {
|
|
81808
|
+
const match = node_fs.readFileSync(`/proc/${process.pid}/status`, "utf-8").match(/Threads:\s+(\d+)/);
|
|
81809
|
+
if (match) threadCount = parseInt(match[1], 10);
|
|
81810
|
+
} catch {
|
|
81811
|
+
}
|
|
81812
|
+
}
|
|
81813
|
+
const nodeProcess = process;
|
|
81814
|
+
return {
|
|
81815
|
+
openFds,
|
|
81816
|
+
threadCount,
|
|
81817
|
+
activeHandles: (nodeProcess._getActiveHandles?.() ?? []).length,
|
|
81818
|
+
activeRequests: (nodeProcess._getActiveRequests?.() ?? []).length
|
|
81819
|
+
};
|
|
81820
|
+
}
|
|
81821
|
+
function getPressure(resource) {
|
|
81822
|
+
if (!IS_LINUX) return null;
|
|
81823
|
+
try {
|
|
81824
|
+
const data = node_fs.readFileSync(`/proc/pressure/${resource}`, "utf-8");
|
|
81825
|
+
const parseLine = (prefix) => {
|
|
81826
|
+
const match = data.match(new RegExp(`${prefix} avg10=(\\d+\\.\\d+) avg60=(\\d+\\.\\d+) avg300=(\\d+\\.\\d+)`));
|
|
81827
|
+
if (!match) return null;
|
|
81828
|
+
return {
|
|
81829
|
+
avg10: parseFloat(match[1]),
|
|
81830
|
+
avg60: parseFloat(match[2]),
|
|
81831
|
+
avg300: parseFloat(match[3])
|
|
81832
|
+
};
|
|
81833
|
+
};
|
|
81834
|
+
const some = parseLine("some");
|
|
81835
|
+
if (!some) return null;
|
|
81836
|
+
return {
|
|
81837
|
+
some,
|
|
81838
|
+
full: parseLine("full")
|
|
81839
|
+
};
|
|
81840
|
+
} catch {
|
|
81841
|
+
return null;
|
|
81842
|
+
}
|
|
81843
|
+
}
|
|
81844
|
+
function execAsync(cmd, args, timeoutMs = 5e3) {
|
|
81845
|
+
return new Promise((resolve, reject) => {
|
|
81846
|
+
(0, node_child_process.execFile)(cmd, args, { timeout: timeoutMs }, (err, stdout) => {
|
|
81847
|
+
if (err) return reject(err);
|
|
81848
|
+
resolve(stdout);
|
|
81849
|
+
});
|
|
81850
|
+
});
|
|
81851
|
+
}
|
|
81852
|
+
function parseProcStat(line) {
|
|
81853
|
+
const close = line.lastIndexOf(")");
|
|
81854
|
+
const open = line.indexOf("(");
|
|
81855
|
+
if (close < 0 || open < 0 || close < open) return null;
|
|
81856
|
+
const pid = Number(line.slice(0, open).trim());
|
|
81857
|
+
const comm = line.slice(open + 1, close);
|
|
81858
|
+
const rest = line.slice(close + 1).trim().split(/\s+/);
|
|
81859
|
+
const state = rest[0];
|
|
81860
|
+
const ppid = Number(rest[1]);
|
|
81861
|
+
const pgid = Number(rest[2]);
|
|
81862
|
+
const utime = Number(rest[11]);
|
|
81863
|
+
const stime = Number(rest[12]);
|
|
81864
|
+
const startTicks = Number(rest[19]);
|
|
81865
|
+
const rssPages = Number(rest[21]);
|
|
81866
|
+
if (state === void 0 || state === "") return null;
|
|
81867
|
+
if (![
|
|
81868
|
+
pid,
|
|
81869
|
+
ppid,
|
|
81870
|
+
pgid,
|
|
81871
|
+
utime,
|
|
81872
|
+
stime,
|
|
81873
|
+
startTicks,
|
|
81874
|
+
rssPages
|
|
81875
|
+
].every(Number.isFinite)) return null;
|
|
81876
|
+
return {
|
|
81877
|
+
pid,
|
|
81878
|
+
comm,
|
|
81879
|
+
state,
|
|
81880
|
+
ppid,
|
|
81881
|
+
pgid,
|
|
81882
|
+
ticks: utime + stime,
|
|
81883
|
+
startTicks,
|
|
81884
|
+
rssPages
|
|
81885
|
+
};
|
|
81886
|
+
}
|
|
81887
|
+
function statusKb(status, key) {
|
|
81888
|
+
const match = status.match(new RegExp(`^${key}:\\s+(\\d+)`, "m"));
|
|
81889
|
+
return match ? parseInt(match[1], 10) * 1024 : void 0;
|
|
81890
|
+
}
|
|
81891
|
+
function parseProcStatusRss(status) {
|
|
81892
|
+
return {
|
|
81893
|
+
rssBytes: statusKb(status, "VmRSS"),
|
|
81894
|
+
privateBytes: statusKb(status, "RssAnon"),
|
|
81895
|
+
sharedBytes: statusKb(status, "RssFile")
|
|
81896
|
+
};
|
|
81897
|
+
}
|
|
81898
|
+
function elapsedSecSince(input) {
|
|
81899
|
+
return Math.max(0, Math.floor(input.uptimeSec - input.startTicks / 100));
|
|
81900
|
+
}
|
|
81901
|
+
function lifetimeCpuPercent(input) {
|
|
81902
|
+
const elapsedSec = input.uptimeSec - input.startTicks / 100;
|
|
81903
|
+
if (!(elapsedSec > 0)) return 0;
|
|
81904
|
+
const cpuSec = input.ticks / 100;
|
|
81905
|
+
return Math.round(cpuSec / elapsedSec * 1e3) / 10;
|
|
81906
|
+
}
|
|
81907
|
+
var PID_RE = /^\d+$/;
|
|
81908
|
+
var nodeProcReader = {
|
|
81909
|
+
listPids: async () => (await (0, node_fs_promises.readdir)("/proc")).filter((entry) => PID_RE.test(entry)).map((entry) => Number(entry)),
|
|
81910
|
+
readStat: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/stat`, "latin1"),
|
|
81911
|
+
readStatus: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/status`, "latin1"),
|
|
81912
|
+
readCmdline: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/cmdline`, "latin1"),
|
|
81913
|
+
readUptimeSec: async () => {
|
|
81914
|
+
const [first] = (await (0, node_fs_promises.readFile)("/proc/uptime", "latin1")).trim().split(/\s+/);
|
|
81915
|
+
const seconds = Number(first);
|
|
81916
|
+
if (!Number.isFinite(seconds)) throw new Error(`/proc/uptime unreadable: ${String(first)}`);
|
|
81917
|
+
return seconds;
|
|
81918
|
+
}
|
|
81919
|
+
};
|
|
81920
|
+
function commandFromCmdline(cmdline, comm) {
|
|
81921
|
+
const joined = cmdline.split("\0").filter((part) => part.length > 0).join(" ");
|
|
81922
|
+
return joined.length > 0 ? joined : `[${comm}]`;
|
|
81923
|
+
}
|
|
81924
|
+
var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
|
|
81925
|
+
async function readProcRow(pid, uptimeSec, reader) {
|
|
81926
|
+
let stat;
|
|
81927
|
+
let cmdline;
|
|
81928
|
+
let status;
|
|
81929
|
+
try {
|
|
81930
|
+
[stat, cmdline, status] = await Promise.all([
|
|
81931
|
+
reader.readStat(pid),
|
|
81932
|
+
reader.readCmdline(pid),
|
|
81933
|
+
reader.readStatus(pid)
|
|
81934
|
+
]);
|
|
81935
|
+
} catch {
|
|
81936
|
+
return null;
|
|
81937
|
+
}
|
|
81938
|
+
const parsed = parseProcStat(stat);
|
|
81939
|
+
if (parsed === null) return null;
|
|
81940
|
+
const rss = parseProcStatusRss(status);
|
|
81941
|
+
return {
|
|
81942
|
+
pid: parsed.pid,
|
|
81943
|
+
ppid: parsed.ppid,
|
|
81944
|
+
pgid: parsed.pgid,
|
|
81945
|
+
cpuPercent: lifetimeCpuPercent({
|
|
81946
|
+
ticks: parsed.ticks,
|
|
81947
|
+
startTicks: parsed.startTicks,
|
|
81948
|
+
uptimeSec
|
|
81949
|
+
}),
|
|
81950
|
+
memoryRssBytes: rss.rssBytes ?? 0,
|
|
81951
|
+
uptimeSec: elapsedSecSince({
|
|
81952
|
+
startTicks: parsed.startTicks,
|
|
81953
|
+
uptimeSec
|
|
81954
|
+
}),
|
|
81955
|
+
command: commandFromCmdline(cmdline, parsed.comm)
|
|
81956
|
+
};
|
|
81957
|
+
}
|
|
81958
|
+
async function readProcProcessTable(reader = nodeProcReader) {
|
|
81959
|
+
const [pids, uptimeSec] = await Promise.all([reader.listPids(), reader.readUptimeSec()]);
|
|
81960
|
+
return (await Promise.all(pids.map((pid) => readProcRow(pid, uptimeSec, reader)))).filter((row) => row !== null);
|
|
81961
|
+
}
|
|
81962
|
+
function parseEtime(etime) {
|
|
81963
|
+
const dashParts = etime.split("-");
|
|
81964
|
+
let days = 0;
|
|
81965
|
+
let hms = etime;
|
|
81966
|
+
if (dashParts.length === 2) {
|
|
81967
|
+
days = parseInt(dashParts[0], 10) || 0;
|
|
81968
|
+
hms = dashParts[1];
|
|
81969
|
+
}
|
|
81970
|
+
const parts = hms.split(":").map((p) => parseInt(p, 10) || 0);
|
|
81971
|
+
let hours = 0;
|
|
81972
|
+
let minutes = 0;
|
|
81973
|
+
let seconds = 0;
|
|
81974
|
+
if (parts.length === 3) [hours, minutes, seconds] = parts;
|
|
81975
|
+
else if (parts.length === 2) [minutes, seconds] = parts;
|
|
81976
|
+
else if (parts.length === 1) [seconds] = parts;
|
|
81977
|
+
return days * 86400 + hours * 3600 + minutes * 60 + seconds;
|
|
81978
|
+
}
|
|
81979
|
+
var PS_ROW_RE = /^(\d+)\s+(\d+)\s+(\d+)\s+([\d.]+)\s+(\d+)\s+(\S+)\s+(.+)$/;
|
|
81980
|
+
function parsePsTable(stdout) {
|
|
81981
|
+
const rows = [];
|
|
81982
|
+
for (const line of stdout.split("\n")) {
|
|
81983
|
+
const match = line.trim().match(PS_ROW_RE);
|
|
81984
|
+
if (!match) continue;
|
|
81985
|
+
const [, pidS, ppidS, pgidS, cpuS, rssS, etimeS, command] = match;
|
|
81986
|
+
rows.push({
|
|
81987
|
+
pid: parseInt(pidS, 10),
|
|
81988
|
+
ppid: parseInt(ppidS, 10),
|
|
81989
|
+
pgid: parseInt(pgidS, 10),
|
|
81990
|
+
cpuPercent: Math.round(parseFloat(cpuS) * 10) / 10,
|
|
81991
|
+
memoryRssBytes: parseInt(rssS, 10) * 1024,
|
|
81992
|
+
uptimeSec: parseEtime(etimeS),
|
|
81993
|
+
command
|
|
81994
|
+
});
|
|
81995
|
+
}
|
|
81996
|
+
return rows;
|
|
81997
|
+
}
|
|
81998
|
+
async function spawnPsTable() {
|
|
81999
|
+
const { stdout } = await execFileAsync("ps", ["-eo", "pid=,ppid=,pgid=,pcpu=,rss=,etime=,command="], {
|
|
82000
|
+
timeout: 5e3,
|
|
82001
|
+
maxBuffer: 8 * 1024 * 1024
|
|
82002
|
+
});
|
|
82003
|
+
return parsePsTable(stdout);
|
|
82004
|
+
}
|
|
82005
|
+
var defaultDeps = {
|
|
82006
|
+
platform: (0, node_os.platform)(),
|
|
82007
|
+
reader: nodeProcReader,
|
|
82008
|
+
spawnPs: spawnPsTable
|
|
82009
|
+
};
|
|
82010
|
+
function readProcessTable(deps = defaultDeps) {
|
|
82011
|
+
return deps.platform === "linux" ? readProcProcessTable(deps.reader) : deps.spawnPs();
|
|
82012
|
+
}
|
|
81804
82013
|
var CAMSTACK_CMD_RE = /(camstack|tsx\s+watch\s.*launcher\.ts|packages\/agent\/dist\/cli\.js|inference_pool\.py|bench-(inference-pool|nodeav)|node .*\/packages\/)/;
|
|
81805
82014
|
function classifyProcess(pid, selfPid, managed) {
|
|
81806
82015
|
if (pid === selfPid) return "root";
|
|
@@ -81933,7 +82142,6 @@ var require_native_metrics_addon = __commonJS({
|
|
|
81933
82142
|
return out;
|
|
81934
82143
|
}
|
|
81935
82144
|
};
|
|
81936
|
-
var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
|
|
81937
82145
|
var METRICS_SNAPSHOT_INTERVAL_MS = 5e3;
|
|
81938
82146
|
var METRICS_SNAPSHOT_HEARTBEAT_MS = 6e4;
|
|
81939
82147
|
function coarsenResourcesSnapshot(snapshot) {
|
|
@@ -82241,7 +82449,23 @@ var require_native_metrics_addon = __commonJS({
|
|
|
82241
82449
|
} });
|
|
82242
82450
|
}
|
|
82243
82451
|
}
|
|
82244
|
-
/**
|
|
82452
|
+
/**
|
|
82453
|
+
* (Re)arm the process-tree timer at the configured interval.
|
|
82454
|
+
*
|
|
82455
|
+
* The process-tree snapshot is FIXED-CADENCE, and its cadence is the
|
|
82456
|
+
* operator's `loadSeriesCadenceSec` (5-60 s, 10 by default).
|
|
82457
|
+
*
|
|
82458
|
+
* It used to emit only ON A CHANGE, with a 60 s fallback heartbeat, and the
|
|
82459
|
+
* dedup is gone rather than tuned. A conditional emit makes a hole in the
|
|
82460
|
+
* series mean two different things — "nothing changed" and "nobody reported"
|
|
82461
|
+
* — and telling those apart is the entire reason an operator opens this chart
|
|
82462
|
+
* after a spike. Now a gap means exactly one thing.
|
|
82463
|
+
*
|
|
82464
|
+
* It is not free: the emit rate is deterministic, so the durable table's row
|
|
82465
|
+
* count is too (nodes x processes / cadence, no discount for a quiet fleet).
|
|
82466
|
+
* The measured cost of that is in `docs/architecture/load-ledger.md`, and it
|
|
82467
|
+
* is why the retention default is six hours rather than three days.
|
|
82468
|
+
*/
|
|
82245
82469
|
startProcessSnapshotTimer() {
|
|
82246
82470
|
if (this.processSnapshotTimer) clearInterval(this.processSnapshotTimer);
|
|
82247
82471
|
this.processSnapshotTimer = setInterval(() => this.emitProcessesSnapshot(), this.loadConfig.cadenceSec * 1e3);
|
|
@@ -82304,7 +82528,8 @@ var require_native_metrics_addon = __commonJS({
|
|
|
82304
82528
|
/**
|
|
82305
82529
|
* Emit one `metrics.node-processes-snapshot` for this node.
|
|
82306
82530
|
*
|
|
82307
|
-
* Heavy — a full
|
|
82531
|
+
* Heavy — a full process-table read (`/proc` on Linux, `ps -eo` elsewhere;
|
|
82532
|
+
* `proc-process-table.ts`) plus a `$process.list` broker call — and
|
|
82308
82533
|
* UNCONDITIONAL. The change-detection that used to guard it is gone: with a
|
|
82309
82534
|
* fixed cadence a missing interval means exactly one thing, and that is the
|
|
82310
82535
|
* property an operator investigating a spike is actually looking for.
|
|
@@ -82408,34 +82633,18 @@ var require_native_metrics_addon = __commonJS({
|
|
|
82408
82633
|
cpuSplits
|
|
82409
82634
|
});
|
|
82410
82635
|
}
|
|
82411
|
-
/**
|
|
82636
|
+
/**
|
|
82637
|
+
* Every pid + command + resource stats on this node.
|
|
82638
|
+
*
|
|
82639
|
+
* From `/proc` on Linux — no fork. This used to be a `ps -eo` child on every
|
|
82640
|
+
* tick, i.e. a synchronous `fork()` of hub-main at p50 91 ms (D441, D452).
|
|
82641
|
+
* `ps` remains the source only on a platform without `/proc`.
|
|
82642
|
+
*/
|
|
82412
82643
|
async runPs() {
|
|
82413
82644
|
try {
|
|
82414
|
-
|
|
82415
|
-
timeout: 5e3,
|
|
82416
|
-
maxBuffer: 8 * 1024 * 1024
|
|
82417
|
-
});
|
|
82418
|
-
const lines = stdout.split("\n");
|
|
82419
|
-
const rows = [];
|
|
82420
|
-
for (const line of lines) {
|
|
82421
|
-
const trimmed = line.trim();
|
|
82422
|
-
if (!trimmed) continue;
|
|
82423
|
-
const match = trimmed.match(/^(\d+)\s+(\d+)\s+(\d+)\s+([\d.]+)\s+(\d+)\s+(\S+)\s+(.+)$/);
|
|
82424
|
-
if (!match) continue;
|
|
82425
|
-
const [, pidS, ppidS, pgidS, cpuS, rssS, etimeS, command] = match;
|
|
82426
|
-
rows.push({
|
|
82427
|
-
pid: parseInt(pidS, 10),
|
|
82428
|
-
ppid: parseInt(ppidS, 10),
|
|
82429
|
-
pgid: parseInt(pgidS, 10),
|
|
82430
|
-
cpuPercent: Math.round(parseFloat(cpuS) * 10) / 10,
|
|
82431
|
-
memoryRssBytes: parseInt(rssS, 10) * 1024,
|
|
82432
|
-
uptimeSec: parseEtime(etimeS),
|
|
82433
|
-
command
|
|
82434
|
-
});
|
|
82435
|
-
}
|
|
82436
|
-
return rows;
|
|
82645
|
+
return await readProcessTable();
|
|
82437
82646
|
} catch (err) {
|
|
82438
|
-
this.ctx.logger.warn("
|
|
82647
|
+
this.ctx.logger.warn("process table read failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
82439
82648
|
return [];
|
|
82440
82649
|
}
|
|
82441
82650
|
}
|
|
@@ -82520,23 +82729,12 @@ var require_native_metrics_addon = __commonJS({
|
|
|
82520
82729
|
}] });
|
|
82521
82730
|
}
|
|
82522
82731
|
};
|
|
82523
|
-
function parseEtime(etime) {
|
|
82524
|
-
const dashParts = etime.split("-");
|
|
82525
|
-
let days = 0;
|
|
82526
|
-
let hms = etime;
|
|
82527
|
-
if (dashParts.length === 2) {
|
|
82528
|
-
days = parseInt(dashParts[0], 10) || 0;
|
|
82529
|
-
hms = dashParts[1];
|
|
82530
|
-
}
|
|
82531
|
-
const parts = hms.split(":").map((p) => parseInt(p, 10) || 0);
|
|
82532
|
-
let hours = 0, minutes = 0, seconds = 0;
|
|
82533
|
-
if (parts.length === 3) [hours, minutes, seconds] = parts;
|
|
82534
|
-
else if (parts.length === 2) [minutes, seconds] = parts;
|
|
82535
|
-
else if (parts.length === 1) [seconds] = parts;
|
|
82536
|
-
return days * 86400 + hours * 3600 + minutes * 60 + seconds;
|
|
82537
|
-
}
|
|
82538
82732
|
exports.NativeMetricsProvider = NativeMetricsProvider;
|
|
82539
82733
|
exports.default = NativeMetricsAddon;
|
|
82734
|
+
exports.lifetimeCpuPercent = lifetimeCpuPercent;
|
|
82735
|
+
exports.nodeProcReader = nodeProcReader;
|
|
82736
|
+
exports.parseProcStat = parseProcStat;
|
|
82737
|
+
exports.parseProcStatusRss = parseProcStatusRss;
|
|
82540
82738
|
}
|
|
82541
82739
|
});
|
|
82542
82740
|
|
|
@@ -82549,7 +82747,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
82549
82747
|
[Symbol.toStringTag]: { value: "Module" }
|
|
82550
82748
|
});
|
|
82551
82749
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
82552
|
-
var require_dist10 =
|
|
82750
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
82553
82751
|
var node_crypto = __require("crypto");
|
|
82554
82752
|
var node_fs_promises = __require("fs/promises");
|
|
82555
82753
|
var node_path = __require("path");
|
|
@@ -82882,6 +83080,117 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
82882
83080
|
}
|
|
82883
83081
|
});
|
|
82884
83082
|
|
|
83083
|
+
// ../system/dist/wal-checkpoint-policy-CCJZngds.js
|
|
83084
|
+
var require_wal_checkpoint_policy_CCJZngds = __commonJS({
|
|
83085
|
+
"../system/dist/wal-checkpoint-policy-CCJZngds.js"(exports) {
|
|
83086
|
+
"use strict";
|
|
83087
|
+
var WAL_CHECKPOINT_MAX_INTERVAL_MS = 6e4;
|
|
83088
|
+
var WAL_CHECKPOINT_POLL_MS = 1e3;
|
|
83089
|
+
var WAL_CHECKPOINT_SLOW_MS = 1e3;
|
|
83090
|
+
function decideCheckpoint(input) {
|
|
83091
|
+
const intervalDue = input.sinceLastRunMs >= WAL_CHECKPOINT_MAX_INTERVAL_MS;
|
|
83092
|
+
if (input.mxFrame === null || input.nBackfill === null) return intervalDue ? {
|
|
83093
|
+
run: true,
|
|
83094
|
+
reason: "unknown-interval",
|
|
83095
|
+
pendingFrames: null
|
|
83096
|
+
} : {
|
|
83097
|
+
run: false,
|
|
83098
|
+
reason: "unknown-below-interval",
|
|
83099
|
+
pendingFrames: null
|
|
83100
|
+
};
|
|
83101
|
+
const pendingFrames = Math.max(0, input.mxFrame - input.nBackfill);
|
|
83102
|
+
if (pendingFrames === 0) return {
|
|
83103
|
+
run: false,
|
|
83104
|
+
reason: "nothing-pending",
|
|
83105
|
+
pendingFrames
|
|
83106
|
+
};
|
|
83107
|
+
if (pendingFrames >= 1e3) return {
|
|
83108
|
+
run: true,
|
|
83109
|
+
reason: "threshold",
|
|
83110
|
+
pendingFrames
|
|
83111
|
+
};
|
|
83112
|
+
if (intervalDue) return {
|
|
83113
|
+
run: true,
|
|
83114
|
+
reason: "interval",
|
|
83115
|
+
pendingFrames
|
|
83116
|
+
};
|
|
83117
|
+
return {
|
|
83118
|
+
run: false,
|
|
83119
|
+
reason: "below-threshold",
|
|
83120
|
+
pendingFrames
|
|
83121
|
+
};
|
|
83122
|
+
}
|
|
83123
|
+
var WAL_INDEX_MXFRAME_OFFSET = 16;
|
|
83124
|
+
var WAL_INDEX_HDR_SIZE = 48;
|
|
83125
|
+
var WAL_INDEX_NBACKFILL_OFFSET = 96;
|
|
83126
|
+
function parseWalIndexHeader(buffer) {
|
|
83127
|
+
if (buffer.length < 100) return null;
|
|
83128
|
+
const copy1 = buffer.subarray(0, WAL_INDEX_HDR_SIZE);
|
|
83129
|
+
const copy2 = buffer.subarray(WAL_INDEX_HDR_SIZE, WAL_INDEX_HDR_SIZE * 2);
|
|
83130
|
+
if (!copy1.equals(copy2)) return null;
|
|
83131
|
+
return {
|
|
83132
|
+
mxFrame: buffer.readUInt32LE(WAL_INDEX_MXFRAME_OFFSET),
|
|
83133
|
+
nBackfill: buffer.readUInt32LE(WAL_INDEX_NBACKFILL_OFFSET)
|
|
83134
|
+
};
|
|
83135
|
+
}
|
|
83136
|
+
function isRecord(value) {
|
|
83137
|
+
return typeof value === "object" && value !== null;
|
|
83138
|
+
}
|
|
83139
|
+
function isWorkerMessage(value) {
|
|
83140
|
+
if (!isRecord(value)) return false;
|
|
83141
|
+
switch (value["kind"]) {
|
|
83142
|
+
case "ready":
|
|
83143
|
+
return true;
|
|
83144
|
+
case "failed":
|
|
83145
|
+
return typeof value["error"] === "string";
|
|
83146
|
+
case "checkpointed":
|
|
83147
|
+
return typeof value["reason"] === "string" && (typeof value["pendingFrames"] === "number" || value["pendingFrames"] === null) && typeof value["walFrames"] === "number" && typeof value["checkpointedFrames"] === "number" && typeof value["busy"] === "boolean" && typeof value["ms"] === "number";
|
|
83148
|
+
default:
|
|
83149
|
+
return false;
|
|
83150
|
+
}
|
|
83151
|
+
}
|
|
83152
|
+
function isWorkerStop(value) {
|
|
83153
|
+
return isRecord(value) && value["kind"] === "stop";
|
|
83154
|
+
}
|
|
83155
|
+
Object.defineProperty(exports, "WAL_CHECKPOINT_POLL_MS", {
|
|
83156
|
+
enumerable: true,
|
|
83157
|
+
get: function() {
|
|
83158
|
+
return WAL_CHECKPOINT_POLL_MS;
|
|
83159
|
+
}
|
|
83160
|
+
});
|
|
83161
|
+
Object.defineProperty(exports, "WAL_CHECKPOINT_SLOW_MS", {
|
|
83162
|
+
enumerable: true,
|
|
83163
|
+
get: function() {
|
|
83164
|
+
return WAL_CHECKPOINT_SLOW_MS;
|
|
83165
|
+
}
|
|
83166
|
+
});
|
|
83167
|
+
Object.defineProperty(exports, "decideCheckpoint", {
|
|
83168
|
+
enumerable: true,
|
|
83169
|
+
get: function() {
|
|
83170
|
+
return decideCheckpoint;
|
|
83171
|
+
}
|
|
83172
|
+
});
|
|
83173
|
+
Object.defineProperty(exports, "isWorkerMessage", {
|
|
83174
|
+
enumerable: true,
|
|
83175
|
+
get: function() {
|
|
83176
|
+
return isWorkerMessage;
|
|
83177
|
+
}
|
|
83178
|
+
});
|
|
83179
|
+
Object.defineProperty(exports, "isWorkerStop", {
|
|
83180
|
+
enumerable: true,
|
|
83181
|
+
get: function() {
|
|
83182
|
+
return isWorkerStop;
|
|
83183
|
+
}
|
|
83184
|
+
});
|
|
83185
|
+
Object.defineProperty(exports, "parseWalIndexHeader", {
|
|
83186
|
+
enumerable: true,
|
|
83187
|
+
get: function() {
|
|
83188
|
+
return parseWalIndexHeader;
|
|
83189
|
+
}
|
|
83190
|
+
});
|
|
83191
|
+
}
|
|
83192
|
+
});
|
|
83193
|
+
|
|
82885
83194
|
// ../../node_modules/better-sqlite3/lib/util.js
|
|
82886
83195
|
var require_util2 = __commonJS({
|
|
82887
83196
|
"../../node_modules/better-sqlite3/lib/util.js"(exports) {
|
|
@@ -83665,13 +83974,17 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
83665
83974
|
[Symbol.toStringTag]: { value: "Module" }
|
|
83666
83975
|
});
|
|
83667
83976
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
83668
|
-
var require_dist10 =
|
|
83669
|
-
var require_retired_settings_keys =
|
|
83977
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
83978
|
+
var require_retired_settings_keys = require_retired_settings_keys_CjvB7Etx();
|
|
83979
|
+
var require_wal_checkpoint_policy = require_wal_checkpoint_policy_CCJZngds();
|
|
83670
83980
|
var node_crypto = __require("crypto");
|
|
83981
|
+
var node_path = __require("path");
|
|
83982
|
+
node_path = require_chunk.__toESM(node_path);
|
|
83671
83983
|
var node_fs = __require("fs");
|
|
83672
83984
|
var node_module = __require("module");
|
|
83673
83985
|
var better_sqlite3 = require_lib();
|
|
83674
83986
|
better_sqlite3 = require_chunk.__toESM(better_sqlite3);
|
|
83987
|
+
var node_worker_threads = __require("worker_threads");
|
|
83675
83988
|
var memo = /* @__PURE__ */ new Map();
|
|
83676
83989
|
function sqlShape(sql, collection) {
|
|
83677
83990
|
const key = `${collection}\0${sql}`;
|
|
@@ -83900,6 +84213,7 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
83900
84213
|
var SQLITE_PAGE_CACHE_FLOOR_KIB = -65536;
|
|
83901
84214
|
var SQLITE_MMAP_FLOOR_BYTES = 268435456;
|
|
83902
84215
|
var SQLITE_JOURNAL_SIZE_LIMIT_BYTES = 67108864;
|
|
84216
|
+
var SQLITE_WAL_AUTOCHECKPOINT_BOUND_PAGES = 1e4;
|
|
83903
84217
|
var MIB = 1048576;
|
|
83904
84218
|
var MMAP_SIZE_MULTIPLE = 1.25;
|
|
83905
84219
|
var SQLITE_MMAP_CEILING_BYTES = 2 * 1024 * MIB;
|
|
@@ -84331,6 +84645,7 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
84331
84645
|
this.db.pragma(`cache_size = ${pageCacheKib}`);
|
|
84332
84646
|
this.db.pragma(`mmap_size = ${mmapSizeBytes}`);
|
|
84333
84647
|
this.db.pragma(`journal_size_limit = ${SQLITE_JOURNAL_SIZE_LIMIT_BYTES}`);
|
|
84648
|
+
this.db.pragma(`wal_autocheckpoint = ${SQLITE_WAL_AUTOCHECKPOINT_BOUND_PAGES}`);
|
|
84334
84649
|
const occupancy = sqliteOccupancy({
|
|
84335
84650
|
pageCount: this.readPragmaNumber("page_count"),
|
|
84336
84651
|
freelistCount: this.readPragmaNumber("freelist_count"),
|
|
@@ -85719,6 +86034,154 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85719
86034
|
if (modelId !== null) out["modelId"] = modelId;
|
|
85720
86035
|
return out;
|
|
85721
86036
|
}
|
|
86037
|
+
var EMPTY_STATS = {
|
|
86038
|
+
checkpoints: 0,
|
|
86039
|
+
frames: 0,
|
|
86040
|
+
slow: 0,
|
|
86041
|
+
maxMs: 0,
|
|
86042
|
+
totalMs: 0,
|
|
86043
|
+
busy: 0
|
|
86044
|
+
};
|
|
86045
|
+
function defaultWorkerPath() {
|
|
86046
|
+
const require_ = (0, node_module.createRequire)(__require("url").pathToFileURL(__filename).href);
|
|
86047
|
+
const packageRoot = node_path.default.dirname(require_.resolve("@camstack/system/package.json"));
|
|
86048
|
+
return node_path.default.join(packageRoot, "dist", "wal-checkpoint-worker.js");
|
|
86049
|
+
}
|
|
86050
|
+
var WalCheckpointer = class {
|
|
86051
|
+
dbPath;
|
|
86052
|
+
logger;
|
|
86053
|
+
pollMs;
|
|
86054
|
+
slowMs;
|
|
86055
|
+
summaryIntervalMs;
|
|
86056
|
+
spawn;
|
|
86057
|
+
worker = null;
|
|
86058
|
+
summaryTimer = null;
|
|
86059
|
+
stopping = false;
|
|
86060
|
+
statsValue = EMPTY_STATS;
|
|
86061
|
+
constructor(options) {
|
|
86062
|
+
this.dbPath = options.dbPath;
|
|
86063
|
+
this.logger = options.logger;
|
|
86064
|
+
this.pollMs = options.pollMs ?? 1e3;
|
|
86065
|
+
this.slowMs = options.slowMs ?? 1e3;
|
|
86066
|
+
this.summaryIntervalMs = options.summaryIntervalMs ?? 6e5;
|
|
86067
|
+
const workerPath = options.workerPath ?? defaultWorkerPath();
|
|
86068
|
+
const execArgv = options.workerExecArgv;
|
|
86069
|
+
this.spawn = options.workerFactory ?? ((workerData) => new node_worker_threads.Worker(workerPath, {
|
|
86070
|
+
workerData,
|
|
86071
|
+
...execArgv !== void 0 ? { execArgv: [...execArgv] } : {}
|
|
86072
|
+
}));
|
|
86073
|
+
}
|
|
86074
|
+
/** Totals since the last summary line. */
|
|
86075
|
+
get stats() {
|
|
86076
|
+
return this.statsValue;
|
|
86077
|
+
}
|
|
86078
|
+
isRunning() {
|
|
86079
|
+
return this.worker !== null;
|
|
86080
|
+
}
|
|
86081
|
+
start() {
|
|
86082
|
+
if (this.worker !== null) return;
|
|
86083
|
+
this.stopping = false;
|
|
86084
|
+
const worker2 = this.spawn({
|
|
86085
|
+
dbPath: this.dbPath,
|
|
86086
|
+
pollMs: this.pollMs
|
|
86087
|
+
});
|
|
86088
|
+
this.worker = worker2;
|
|
86089
|
+
worker2.on("message", (message) => this.onMessage(message));
|
|
86090
|
+
worker2.on("error", (err) => {
|
|
86091
|
+
this.logger.error("WAL checkpoint worker threw", { meta: { error: require_dist10.errMsg(err) } });
|
|
86092
|
+
});
|
|
86093
|
+
worker2.on("exit", (code) => this.onExit(code));
|
|
86094
|
+
const summaryTimer = setInterval(() => this.logSummary(), this.summaryIntervalMs);
|
|
86095
|
+
summaryTimer.unref?.();
|
|
86096
|
+
this.summaryTimer = summaryTimer;
|
|
86097
|
+
this.logger.info("WAL checkpoint worker armed", { meta: {
|
|
86098
|
+
pollMs: this.pollMs,
|
|
86099
|
+
slowMs: this.slowMs
|
|
86100
|
+
} });
|
|
86101
|
+
}
|
|
86102
|
+
/** Ask the thread to close its connection and exit; resolves when it has. */
|
|
86103
|
+
async stop() {
|
|
86104
|
+
const worker2 = this.worker;
|
|
86105
|
+
if (worker2 === null) return;
|
|
86106
|
+
this.stopping = true;
|
|
86107
|
+
if (this.summaryTimer !== null) {
|
|
86108
|
+
clearInterval(this.summaryTimer);
|
|
86109
|
+
this.summaryTimer = null;
|
|
86110
|
+
}
|
|
86111
|
+
const stop = { kind: "stop" };
|
|
86112
|
+
const exited = new Promise((resolve) => worker2.once("exit", () => resolve()));
|
|
86113
|
+
worker2.postMessage(stop);
|
|
86114
|
+
await exited;
|
|
86115
|
+
this.worker = null;
|
|
86116
|
+
}
|
|
86117
|
+
/** One message off the port. Public so the spec can feed it directly. */
|
|
86118
|
+
onMessage(message) {
|
|
86119
|
+
if (!require_wal_checkpoint_policy.isWorkerMessage(message)) {
|
|
86120
|
+
this.logger.warn("WAL checkpoint worker sent an unreadable message", { meta: { message: String(message) } });
|
|
86121
|
+
return;
|
|
86122
|
+
}
|
|
86123
|
+
this.handle(message);
|
|
86124
|
+
}
|
|
86125
|
+
handle(message) {
|
|
86126
|
+
switch (message.kind) {
|
|
86127
|
+
case "ready":
|
|
86128
|
+
return;
|
|
86129
|
+
case "failed":
|
|
86130
|
+
this.logger.warn("WAL checkpoint failed on the worker", { meta: { error: message.error } });
|
|
86131
|
+
return;
|
|
86132
|
+
case "checkpointed":
|
|
86133
|
+
this.record(message);
|
|
86134
|
+
return;
|
|
86135
|
+
}
|
|
86136
|
+
}
|
|
86137
|
+
record(report) {
|
|
86138
|
+
const slow = report.ms >= this.slowMs;
|
|
86139
|
+
const prev = this.statsValue;
|
|
86140
|
+
this.statsValue = {
|
|
86141
|
+
checkpoints: prev.checkpoints + 1,
|
|
86142
|
+
frames: prev.frames + report.checkpointedFrames,
|
|
86143
|
+
slow: prev.slow + (slow ? 1 : 0),
|
|
86144
|
+
maxMs: Math.max(prev.maxMs, report.ms),
|
|
86145
|
+
totalMs: prev.totalMs + report.ms,
|
|
86146
|
+
busy: prev.busy + (report.busy ? 1 : 0)
|
|
86147
|
+
};
|
|
86148
|
+
if (slow) this.logger.warn("WAL checkpoint held the worker", { meta: {
|
|
86149
|
+
ms: report.ms,
|
|
86150
|
+
reason: report.reason,
|
|
86151
|
+
pendingFrames: report.pendingFrames,
|
|
86152
|
+
walFrames: report.walFrames,
|
|
86153
|
+
checkpointedFrames: report.checkpointedFrames,
|
|
86154
|
+
busy: report.busy
|
|
86155
|
+
} });
|
|
86156
|
+
}
|
|
86157
|
+
logSummary() {
|
|
86158
|
+
const stats = this.statsValue;
|
|
86159
|
+
this.statsValue = EMPTY_STATS;
|
|
86160
|
+
if (stats.checkpoints === 0) return;
|
|
86161
|
+
this.logger.info("WAL checkpoints on the worker", { meta: {
|
|
86162
|
+
windowMs: this.summaryIntervalMs,
|
|
86163
|
+
checkpoints: stats.checkpoints,
|
|
86164
|
+
frames: stats.frames,
|
|
86165
|
+
slow: stats.slow,
|
|
86166
|
+
maxMs: stats.maxMs,
|
|
86167
|
+
totalMs: stats.totalMs,
|
|
86168
|
+
busy: stats.busy
|
|
86169
|
+
} });
|
|
86170
|
+
}
|
|
86171
|
+
onExit(code) {
|
|
86172
|
+
const wasStopping = this.stopping;
|
|
86173
|
+
this.worker = null;
|
|
86174
|
+
if (this.summaryTimer !== null) {
|
|
86175
|
+
clearInterval(this.summaryTimer);
|
|
86176
|
+
this.summaryTimer = null;
|
|
86177
|
+
}
|
|
86178
|
+
if (wasStopping) return;
|
|
86179
|
+
this.logger.error("WAL checkpoint worker died \u2014 the engine autocheckpoint bound is now the only checkpoint", { meta: {
|
|
86180
|
+
exitCode: code,
|
|
86181
|
+
dbPath: this.dbPath
|
|
86182
|
+
} });
|
|
86183
|
+
}
|
|
86184
|
+
};
|
|
85722
86185
|
var WAL_HIGH_WATER_BYTES = 67108864;
|
|
85723
86186
|
var WAL_IDLE_QUIET_MS = 3e4;
|
|
85724
86187
|
var WAL_CHECKPOINT_BUSY_TIMEOUT_MS = 250;
|
|
@@ -85869,6 +86332,7 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85869
86332
|
backend = null;
|
|
85870
86333
|
vectorIndex = null;
|
|
85871
86334
|
walMaintenance = null;
|
|
86335
|
+
walCheckpointer = null;
|
|
85872
86336
|
constructor() {
|
|
85873
86337
|
super({});
|
|
85874
86338
|
}
|
|
@@ -85941,6 +86405,12 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85941
86405
|
maintenance.start();
|
|
85942
86406
|
this.walMaintenance = maintenance;
|
|
85943
86407
|
}
|
|
86408
|
+
const checkpointer = new WalCheckpointer({
|
|
86409
|
+
dbPath,
|
|
86410
|
+
logger: this.ctx.logger.child("WalCheckpoint")
|
|
86411
|
+
});
|
|
86412
|
+
checkpointer.start();
|
|
86413
|
+
this.walCheckpointer = checkpointer;
|
|
85944
86414
|
this.ctx.logger.info("Initialized successfully");
|
|
85945
86415
|
return [{
|
|
85946
86416
|
capability: require_dist10.dataStoreProviderCapability,
|
|
@@ -85953,6 +86423,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85953
86423
|
async onShutdown() {
|
|
85954
86424
|
this.walMaintenance?.stop();
|
|
85955
86425
|
this.walMaintenance = null;
|
|
86426
|
+
await this.walCheckpointer?.stop();
|
|
86427
|
+
this.walCheckpointer = null;
|
|
85956
86428
|
await this.backend?.shutdown();
|
|
85957
86429
|
}
|
|
85958
86430
|
getBackend() {
|
|
@@ -86170,7 +86642,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
86170
86642
|
[Symbol.toStringTag]: { value: "Module" }
|
|
86171
86643
|
});
|
|
86172
86644
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
86173
|
-
var require_dist10 =
|
|
86645
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
86174
86646
|
var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
|
|
86175
86647
|
var zod = require_zod();
|
|
86176
86648
|
var node_crypto = __require("crypto");
|
|
@@ -89820,7 +90292,7 @@ var require_system_config_addon = __commonJS({
|
|
|
89820
90292
|
[Symbol.toStringTag]: { value: "Module" }
|
|
89821
90293
|
});
|
|
89822
90294
|
require_chunk_Cek0wNdY();
|
|
89823
|
-
var require_dist10 =
|
|
90295
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
89824
90296
|
var SECTION_TITLES = {
|
|
89825
90297
|
server: "Server",
|
|
89826
90298
|
auth: "Authentication"
|
|
@@ -107881,7 +108353,7 @@ var require_winston_logging = __commonJS({
|
|
|
107881
108353
|
[Symbol.toStringTag]: { value: "Module" }
|
|
107882
108354
|
});
|
|
107883
108355
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
107884
|
-
var require_dist10 =
|
|
108356
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
107885
108357
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
107886
108358
|
var node_path = __require("path");
|
|
107887
108359
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -108018,17 +108490,17 @@ var require_winston_logging = __commonJS({
|
|
|
108018
108490
|
}
|
|
108019
108491
|
});
|
|
108020
108492
|
|
|
108021
|
-
// ../system/dist/event-loop-stall-monitor-
|
|
108022
|
-
var
|
|
108023
|
-
"../system/dist/event-loop-stall-monitor-
|
|
108493
|
+
// ../system/dist/event-loop-stall-monitor-CAsHdMwP.js
|
|
108494
|
+
var require_event_loop_stall_monitor_CAsHdMwP = __commonJS({
|
|
108495
|
+
"../system/dist/event-loop-stall-monitor-CAsHdMwP.js"(exports) {
|
|
108024
108496
|
"use strict";
|
|
108025
108497
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
108026
108498
|
var node_crypto = __require("crypto");
|
|
108027
108499
|
var node_path = __require("path");
|
|
108028
108500
|
node_path = require_chunk.__toESM(node_path);
|
|
108029
|
-
var node_util = __require("util");
|
|
108030
108501
|
var node_fs = __require("fs");
|
|
108031
108502
|
node_fs = require_chunk.__toESM(node_fs);
|
|
108503
|
+
var node_util = __require("util");
|
|
108032
108504
|
var node_http = __require("http");
|
|
108033
108505
|
var node_zlib = __require("zlib");
|
|
108034
108506
|
var node_perf_hooks = __require("perf_hooks");
|
|
@@ -109004,19 +109476,19 @@ var require_event_loop_stall_monitor_DM9OAzy8 = __commonJS({
|
|
|
109004
109476
|
}
|
|
109005
109477
|
});
|
|
109006
109478
|
|
|
109007
|
-
// ../system/dist/tls-
|
|
109008
|
-
var
|
|
109009
|
-
"../system/dist/tls-
|
|
109479
|
+
// ../system/dist/tls-BFs4PzoW.js
|
|
109480
|
+
var require_tls_BFs4PzoW = __commonJS({
|
|
109481
|
+
"../system/dist/tls-BFs4PzoW.js"(exports) {
|
|
109010
109482
|
"use strict";
|
|
109011
109483
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
109012
109484
|
var node_crypto = __require("crypto");
|
|
109013
109485
|
var node_fs_promises = __require("fs/promises");
|
|
109014
109486
|
var node_path = __require("path");
|
|
109015
|
-
var node_child_process = __require("child_process");
|
|
109016
|
-
var node_util = __require("util");
|
|
109017
109487
|
var node_fs = __require("fs");
|
|
109488
|
+
var node_child_process = __require("child_process");
|
|
109018
109489
|
var node_os = __require("os");
|
|
109019
109490
|
node_os = require_chunk.__toESM(node_os);
|
|
109491
|
+
var node_util = __require("util");
|
|
109020
109492
|
var node_http = __require("http");
|
|
109021
109493
|
var node_net = __require("net");
|
|
109022
109494
|
var DEFAULT_HTTP_PORT = 4480;
|
|
@@ -120515,9 +120987,9 @@ var require_dist2 = __commonJS({
|
|
|
120515
120987
|
}
|
|
120516
120988
|
});
|
|
120517
120989
|
|
|
120518
|
-
// ../system/dist/manifest-system-deps-
|
|
120519
|
-
var
|
|
120520
|
-
"../system/dist/manifest-system-deps-
|
|
120990
|
+
// ../system/dist/manifest-system-deps-g_nK0xsF.js
|
|
120991
|
+
var require_manifest_system_deps_g_nK0xsF = __commonJS({
|
|
120992
|
+
"../system/dist/manifest-system-deps-g_nK0xsF.js"(exports) {
|
|
120521
120993
|
"use strict";
|
|
120522
120994
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
120523
120995
|
require_hub_cap_forward_DmHNjbB0();
|
|
@@ -120527,12 +120999,12 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
120527
120999
|
var node_fs_promises = __require("fs/promises");
|
|
120528
121000
|
var node_path = __require("path");
|
|
120529
121001
|
node_path = require_chunk.__toESM(node_path);
|
|
120530
|
-
var node_child_process = __require("child_process");
|
|
120531
|
-
var node_util = __require("util");
|
|
120532
121002
|
var node_fs = __require("fs");
|
|
120533
121003
|
node_fs = require_chunk.__toESM(node_fs);
|
|
121004
|
+
var node_child_process = __require("child_process");
|
|
120534
121005
|
var node_os = __require("os");
|
|
120535
121006
|
node_os = require_chunk.__toESM(node_os);
|
|
121007
|
+
var node_util = __require("util");
|
|
120536
121008
|
var node_http = __require("http");
|
|
120537
121009
|
var node_v8 = __require("v8");
|
|
120538
121010
|
node_v8 = require_chunk.__toESM(node_v8);
|
|
@@ -120688,12 +121160,15 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
120688
121160
|
peers.push({
|
|
120689
121161
|
peerId: child.childId,
|
|
120690
121162
|
tx: traffic.tx,
|
|
120691
|
-
rx: traffic.rx
|
|
121163
|
+
rx: traffic.rx,
|
|
121164
|
+
queuedBytes: registry.getChildQueuedBytes(child.childId)
|
|
120692
121165
|
});
|
|
120693
121166
|
}
|
|
121167
|
+
const forward = registry.readForwardCensus?.();
|
|
120694
121168
|
return {
|
|
120695
121169
|
peers,
|
|
120696
|
-
peersConnected: listed.length
|
|
121170
|
+
peersConnected: listed.length,
|
|
121171
|
+
...forward === void 0 ? {} : { forward }
|
|
120697
121172
|
};
|
|
120698
121173
|
} catch {
|
|
120699
121174
|
return;
|
|
@@ -120701,7 +121176,36 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
120701
121176
|
};
|
|
120702
121177
|
}
|
|
120703
121178
|
var SOCKET_PLANE_TOP_N = 5;
|
|
121179
|
+
var SOCKET_QUEUE_TOP_N = 3;
|
|
121180
|
+
function readSocketQueues(current) {
|
|
121181
|
+
let totalBytes = 0;
|
|
121182
|
+
let unmeasured = 0;
|
|
121183
|
+
const holding = [];
|
|
121184
|
+
for (const peer of current.peers) {
|
|
121185
|
+
if (peer.queuedBytes === null) {
|
|
121186
|
+
unmeasured += 1;
|
|
121187
|
+
continue;
|
|
121188
|
+
}
|
|
121189
|
+
totalBytes += peer.queuedBytes;
|
|
121190
|
+
if (peer.queuedBytes > 0) holding.push({
|
|
121191
|
+
peerId: peer.peerId,
|
|
121192
|
+
bytes: peer.queuedBytes
|
|
121193
|
+
});
|
|
121194
|
+
}
|
|
121195
|
+
return {
|
|
121196
|
+
totalBytes,
|
|
121197
|
+
unmeasured,
|
|
121198
|
+
top: holding.toSorted((a, b) => b.bytes - a.bytes || a.peerId.localeCompare(b.peerId)).slice(0, 3)
|
|
121199
|
+
};
|
|
121200
|
+
}
|
|
120704
121201
|
var EMPTY_SOCKET_PLANE_BASELINE = { peers: /* @__PURE__ */ new Map() };
|
|
121202
|
+
function diffForward(current, before) {
|
|
121203
|
+
if (current === void 0) return void 0;
|
|
121204
|
+
return {
|
|
121205
|
+
raw: Math.max(0, current.raw - (before?.raw ?? 0)),
|
|
121206
|
+
decoded: Math.max(0, current.decoded - (before?.decoded ?? 0))
|
|
121207
|
+
};
|
|
121208
|
+
}
|
|
120705
121209
|
function diffDirection(current, before) {
|
|
120706
121210
|
const previous = before ?? EMPTY_SOCKET_DIRECTION;
|
|
120707
121211
|
return {
|
|
@@ -120726,6 +121230,9 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
120726
121230
|
function peerMessages(delta) {
|
|
120727
121231
|
return socketDirectionMessages(delta.tx) + socketDirectionMessages(delta.rx);
|
|
120728
121232
|
}
|
|
121233
|
+
function peerBytes(delta) {
|
|
121234
|
+
return socketDirectionBytes(delta.tx) + socketDirectionBytes(delta.rx);
|
|
121235
|
+
}
|
|
120729
121236
|
function diffSocketPlane(baseline, current, topN = 5) {
|
|
120730
121237
|
const deltas = [];
|
|
120731
121238
|
let tx = EMPTY_SOCKET_DIRECTION;
|
|
@@ -120741,12 +121248,16 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
120741
121248
|
rx = addDirection(rx, delta.rx);
|
|
120742
121249
|
if (peerMessages(delta) > 0) deltas.push(delta);
|
|
120743
121250
|
}
|
|
121251
|
+
const forward = diffForward(current.forward, baseline.forward);
|
|
120744
121252
|
return {
|
|
120745
121253
|
peersConnected: current.peersConnected,
|
|
120746
121254
|
peersMeasured: current.peers.length,
|
|
120747
121255
|
tx,
|
|
120748
121256
|
rx,
|
|
120749
|
-
top: deltas.toSorted((a, b) => peerMessages(b) - peerMessages(a) || a.peerId.localeCompare(b.peerId)).slice(0, topN)
|
|
121257
|
+
top: deltas.toSorted((a, b) => peerMessages(b) - peerMessages(a) || a.peerId.localeCompare(b.peerId)).slice(0, topN),
|
|
121258
|
+
topBytes: deltas.toSorted((a, b) => peerBytes(b) - peerBytes(a) || a.peerId.localeCompare(b.peerId)).slice(0, topN),
|
|
121259
|
+
queued: readSocketQueues(current),
|
|
121260
|
+
...forward === void 0 ? {} : { forward }
|
|
120750
121261
|
};
|
|
120751
121262
|
}
|
|
120752
121263
|
function createSocketPlaneMeter(reader, topN = 5) {
|
|
@@ -120755,23 +121266,166 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
120755
121266
|
const current = reader();
|
|
120756
121267
|
if (current === void 0) return void 0;
|
|
120757
121268
|
const window2 = diffSocketPlane(baseline, current, topN);
|
|
120758
|
-
baseline = {
|
|
121269
|
+
baseline = {
|
|
121270
|
+
peers: new Map(current.peers.map((p) => [p.peerId, p])),
|
|
121271
|
+
...current.forward === void 0 ? {} : { forward: current.forward }
|
|
121272
|
+
};
|
|
120759
121273
|
return window2;
|
|
120760
121274
|
} };
|
|
120761
121275
|
}
|
|
120762
|
-
function kb(bytes) {
|
|
121276
|
+
function kb$1(bytes) {
|
|
120763
121277
|
return Math.round(bytes / 1024);
|
|
120764
121278
|
}
|
|
120765
121279
|
function formatDirection(sample) {
|
|
120766
|
-
return `req:${sample.reqMessages}/${kb(sample.reqBytes)}kB,res:${sample.resMessages}/${kb(sample.resBytes)}kB,evt:${sample.evtMessages}/${kb(sample.evtBytes)}kB`;
|
|
121280
|
+
return `req:${sample.reqMessages}/${kb$1(sample.reqBytes)}kB,res:${sample.resMessages}/${kb$1(sample.resBytes)}kB,evt:${sample.evtMessages}/${kb$1(sample.evtBytes)}kB`;
|
|
121281
|
+
}
|
|
121282
|
+
function formatPeerBytes(sample) {
|
|
121283
|
+
return `${kb$1(sample.reqBytes)}/${kb$1(sample.resBytes)}/${kb$1(sample.evtBytes)}`;
|
|
120767
121284
|
}
|
|
120768
121285
|
function formatPeer(delta) {
|
|
120769
|
-
return `${delta.peerId}:tx=${delta.tx.reqMessages}/${delta.tx.resMessages}/${delta.tx.evtMessages}:rx=${delta.rx.reqMessages}/${delta.rx.resMessages}/${delta.rx.evtMessages}:
|
|
121286
|
+
return `${delta.peerId}:tx=${delta.tx.reqMessages}/${delta.tx.resMessages}/${delta.tx.evtMessages}:rx=${delta.rx.reqMessages}/${delta.rx.resMessages}/${delta.rx.evtMessages}:txkB=${formatPeerBytes(delta.tx)}:rxkB=${formatPeerBytes(delta.rx)}`;
|
|
120770
121287
|
}
|
|
120771
121288
|
function formatSocketPlane(window2) {
|
|
120772
121289
|
if (window2 === void 0) return "";
|
|
120773
121290
|
const top = window2.top.map(formatPeer).join(",");
|
|
120774
|
-
|
|
121291
|
+
const named = new Set(window2.top.map((p) => p.peerId));
|
|
121292
|
+
const topBytes = window2.topBytes.filter((p) => !named.has(p.peerId)).map(formatPeer).join(",");
|
|
121293
|
+
const queuedTop = window2.queued.top.map((p) => `${p.peerId}:${kb$1(p.bytes)}`).join(",");
|
|
121294
|
+
return ` socketPeers=${window2.peersMeasured}/${window2.peersConnected} socketTx=${formatDirection(window2.tx)} socketRx=${formatDirection(window2.rx)}` + (top.length === 0 ? "" : ` socketTop=${top}`) + (topBytes.length === 0 ? "" : ` socketTopBytes=${topBytes}`) + ` socketQueued=${kb$1(window2.queued.totalBytes)}kB` + (window2.queued.unmeasured === 0 ? "" : ` socketQueuedUnmeasured=${window2.queued.unmeasured}`) + (queuedTop.length === 0 ? "" : ` socketQueuedTop=${queuedTop}`) + (window2.forward === void 0 ? "" : ` socketFwd=${window2.forward.raw}/${window2.forward.decoded}`);
|
|
121295
|
+
}
|
|
121296
|
+
function isRecord$1(value) {
|
|
121297
|
+
return typeof value === "object" && value !== null;
|
|
121298
|
+
}
|
|
121299
|
+
function writerSocketsOf(broker) {
|
|
121300
|
+
if (!isRecord$1(broker)) return void 0;
|
|
121301
|
+
const transit = broker["transit"];
|
|
121302
|
+
if (!isRecord$1(transit)) return void 0;
|
|
121303
|
+
const transporter = transit["tx"];
|
|
121304
|
+
if (!isRecord$1(transporter)) return void 0;
|
|
121305
|
+
const writer = transporter["writer"];
|
|
121306
|
+
if (!isRecord$1(writer)) return void 0;
|
|
121307
|
+
const sockets = writer["sockets"];
|
|
121308
|
+
return sockets instanceof Map ? sockets : void 0;
|
|
121309
|
+
}
|
|
121310
|
+
function readSocket(nodeId, socket) {
|
|
121311
|
+
if (typeof nodeId !== "string" || !isRecord$1(socket)) return void 0;
|
|
121312
|
+
const queuedBytes = socket["writableLength"];
|
|
121313
|
+
const bytesWritten = socket["bytesWritten"];
|
|
121314
|
+
if (typeof queuedBytes !== "number" || typeof bytesWritten !== "number") return void 0;
|
|
121315
|
+
return {
|
|
121316
|
+
nodeId,
|
|
121317
|
+
queuedBytes,
|
|
121318
|
+
bytesWritten
|
|
121319
|
+
};
|
|
121320
|
+
}
|
|
121321
|
+
function createMeshQueueReader(getBroker) {
|
|
121322
|
+
return () => {
|
|
121323
|
+
try {
|
|
121324
|
+
const sockets = writerSocketsOf(getBroker());
|
|
121325
|
+
if (sockets === void 0) return void 0;
|
|
121326
|
+
const peers = [];
|
|
121327
|
+
for (const [nodeId, socket] of sockets) {
|
|
121328
|
+
const peer = readSocket(nodeId, socket);
|
|
121329
|
+
if (peer !== void 0) peers.push(peer);
|
|
121330
|
+
}
|
|
121331
|
+
return peers;
|
|
121332
|
+
} catch {
|
|
121333
|
+
return;
|
|
121334
|
+
}
|
|
121335
|
+
};
|
|
121336
|
+
}
|
|
121337
|
+
var MESH_QUEUE_TOP_N = 3;
|
|
121338
|
+
function kb(bytes) {
|
|
121339
|
+
return Math.round(bytes / 1024);
|
|
121340
|
+
}
|
|
121341
|
+
function formatMeshQueue(peers) {
|
|
121342
|
+
if (peers === void 0) return "";
|
|
121343
|
+
const total = peers.reduce((sum, p) => sum + p.queuedBytes, 0);
|
|
121344
|
+
const top = peers.filter((p) => p.queuedBytes > 0).toSorted((a, b) => b.queuedBytes - a.queuedBytes || a.nodeId.localeCompare(b.nodeId)).slice(0, 3).map((p) => `${p.nodeId}:${kb(p.queuedBytes)}`).join(",");
|
|
121345
|
+
return ` meshQueued=${kb(total)}kB` + (top.length === 0 ? "" : ` meshQueuedTop=${top}`);
|
|
121346
|
+
}
|
|
121347
|
+
var OUTBOUND_QUEUE_THRESHOLD_BYTES = 64 * 1024 * 1024;
|
|
121348
|
+
var OUTBOUND_QUEUE_SUSTAIN_MS = 6e4;
|
|
121349
|
+
var OUTBOUND_QUEUE_COOLDOWN_MS = 10 * 6e4;
|
|
121350
|
+
var RELEASE_RATIO = 0.5;
|
|
121351
|
+
function createOutboundQueueGate(options = {}) {
|
|
121352
|
+
const thresholdBytes = options.thresholdBytes ?? 67108864;
|
|
121353
|
+
const sustainMs = options.sustainMs ?? 6e4;
|
|
121354
|
+
const cooldownMs = options.cooldownMs ?? 6e5;
|
|
121355
|
+
const tracked = /* @__PURE__ */ new Map();
|
|
121356
|
+
const judgeOne = (peerId, bytes, at) => {
|
|
121357
|
+
const state = tracked.get(peerId);
|
|
121358
|
+
if (bytes >= thresholdBytes) {
|
|
121359
|
+
const next = state === void 0 ? {
|
|
121360
|
+
aboveSince: at,
|
|
121361
|
+
peakBytes: bytes,
|
|
121362
|
+
lastNamedAt: null
|
|
121363
|
+
} : {
|
|
121364
|
+
...state,
|
|
121365
|
+
peakBytes: Math.max(state.peakBytes, bytes)
|
|
121366
|
+
};
|
|
121367
|
+
const heldForMs = at - next.aboveSince;
|
|
121368
|
+
const due = heldForMs >= sustainMs && (next.lastNamedAt === null || at - next.lastNamedAt >= cooldownMs);
|
|
121369
|
+
tracked.set(peerId, due ? {
|
|
121370
|
+
...next,
|
|
121371
|
+
lastNamedAt: at
|
|
121372
|
+
} : next);
|
|
121373
|
+
return due ? {
|
|
121374
|
+
kind: "sustained",
|
|
121375
|
+
peerId,
|
|
121376
|
+
bytes,
|
|
121377
|
+
peakBytes: next.peakBytes,
|
|
121378
|
+
heldForMs
|
|
121379
|
+
} : void 0;
|
|
121380
|
+
}
|
|
121381
|
+
if (state === void 0) return void 0;
|
|
121382
|
+
if (bytes >= thresholdBytes * RELEASE_RATIO) return void 0;
|
|
121383
|
+
tracked.delete(peerId);
|
|
121384
|
+
if (state.lastNamedAt === null) return void 0;
|
|
121385
|
+
return {
|
|
121386
|
+
kind: "released",
|
|
121387
|
+
peerId,
|
|
121388
|
+
peakBytes: state.peakBytes,
|
|
121389
|
+
toBytes: bytes,
|
|
121390
|
+
heldForMs: at - state.aboveSince,
|
|
121391
|
+
gone: false
|
|
121392
|
+
};
|
|
121393
|
+
};
|
|
121394
|
+
return { observe(readings, at) {
|
|
121395
|
+
const verdicts = [];
|
|
121396
|
+
const seen = /* @__PURE__ */ new Set();
|
|
121397
|
+
for (const reading of readings) {
|
|
121398
|
+
seen.add(reading.peerId);
|
|
121399
|
+
const verdict = judgeOne(reading.peerId, reading.bytes, at);
|
|
121400
|
+
if (verdict !== void 0) verdicts.push(verdict);
|
|
121401
|
+
}
|
|
121402
|
+
for (const [peerId, state] of tracked) {
|
|
121403
|
+
if (seen.has(peerId)) continue;
|
|
121404
|
+
tracked.delete(peerId);
|
|
121405
|
+
if (state.lastNamedAt === null) continue;
|
|
121406
|
+
verdicts.push({
|
|
121407
|
+
kind: "released",
|
|
121408
|
+
peerId,
|
|
121409
|
+
peakBytes: state.peakBytes,
|
|
121410
|
+
toBytes: 0,
|
|
121411
|
+
heldForMs: at - state.aboveSince,
|
|
121412
|
+
gone: true
|
|
121413
|
+
});
|
|
121414
|
+
}
|
|
121415
|
+
return verdicts;
|
|
121416
|
+
} };
|
|
121417
|
+
}
|
|
121418
|
+
var BYTES_PER_MB$1 = 1048576;
|
|
121419
|
+
function mb$2(bytes) {
|
|
121420
|
+
return Math.round(bytes / BYTES_PER_MB$1);
|
|
121421
|
+
}
|
|
121422
|
+
function duration(ms) {
|
|
121423
|
+
const seconds = Math.round(ms / 1e3);
|
|
121424
|
+
return seconds < 120 ? `${seconds}s` : `${Math.round(seconds / 60)}m`;
|
|
121425
|
+
}
|
|
121426
|
+
function formatOutboundQueueVerdict(label, verdict) {
|
|
121427
|
+
if (verdict.kind === "sustained") return `[mem] ${label} outbound queue to ${verdict.peerId} has held ${mb$2(verdict.bytes)}MB (peak ${mb$2(verdict.peakBytes)}MB) for ${duration(verdict.heldForMs)} \u2014 the peer is not draining what this process writes to it. This is socket.writableLength on the channel itself; a sum over _getActiveHandles() does not list an unref'd socket and would miss it.`;
|
|
121428
|
+
return `[mem] ${label} outbound queue to ${verdict.peerId} RELEASED \u2014 ${mb$2(verdict.peakBytes)}MB at peak, ${mb$2(verdict.toBytes)}MB now, held ${duration(verdict.heldForMs)}` + (verdict.gone ? " (peer gone: the socket closed and dropped its queue)" : " (drained)");
|
|
120775
121429
|
}
|
|
120776
121430
|
var DECISIVE_HEAP_SPACES = ["old_space", "large_object_space"];
|
|
120777
121431
|
var HEAP_SPACE_REPORT_MIN_MB = 32;
|
|
@@ -121097,6 +121751,21 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
121097
121751
|
if (loop === void 0) return `${line}${suffix}`;
|
|
121098
121752
|
return `${line} loopP50=${loop.p50Ms}ms loopP99=${loop.p99Ms}ms loopMax=${loop.maxMs}ms${suffix}`;
|
|
121099
121753
|
}
|
|
121754
|
+
function outboundQueueReadings(uds, mesh) {
|
|
121755
|
+
const readings = [];
|
|
121756
|
+
for (const peer of uds?.peers ?? []) {
|
|
121757
|
+
if (peer.queuedBytes === null) continue;
|
|
121758
|
+
readings.push({
|
|
121759
|
+
peerId: `uds:${peer.peerId}`,
|
|
121760
|
+
bytes: peer.queuedBytes
|
|
121761
|
+
});
|
|
121762
|
+
}
|
|
121763
|
+
for (const node of mesh ?? []) readings.push({
|
|
121764
|
+
peerId: `mesh:${node.nodeId}`,
|
|
121765
|
+
bytes: node.queuedBytes
|
|
121766
|
+
});
|
|
121767
|
+
return readings;
|
|
121768
|
+
}
|
|
121100
121769
|
function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS, reclaimOptions, loopDelay = createLoopDelayMeter(), execArgv = process.execArgv, announceCeilingOrigin = true, rssBudget, probes) {
|
|
121101
121770
|
const readSpaces = probes?.readSpaces ?? readHeapSpaces;
|
|
121102
121771
|
const eventPlane = probes?.eventPlane === void 0 ? void 0 : createEventPlaneMeter(probes.eventPlane);
|
|
@@ -121178,7 +121847,7 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
121178
121847
|
const due = at - lastLoggedAt >= intervalMs;
|
|
121179
121848
|
if (mode === "escalated" || due) {
|
|
121180
121849
|
lastLoggedAt = at;
|
|
121181
|
-
const line = format2(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()));
|
|
121850
|
+
const line = format2(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()));
|
|
121182
121851
|
if (sample.nearLimit) sink.warn(`${line} \u2014 APPROACHING HEAP LIMIT`);
|
|
121183
121852
|
else if (mode === "escalated") sink.warn(`${line} \u2014 heap elevated, sampling every ${probeIntervalMs}ms`);
|
|
121184
121853
|
else sink.info(line);
|
|
@@ -121187,9 +121856,18 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
121187
121856
|
checkRssBudget(sample, at);
|
|
121188
121857
|
maybeReclaim(sample);
|
|
121189
121858
|
judgeArrayBuffers(sample, at);
|
|
121859
|
+
judgeOutboundQueues(at);
|
|
121190
121860
|
} catch {
|
|
121191
121861
|
}
|
|
121192
121862
|
};
|
|
121863
|
+
const meshQueue = probes?.meshQueue;
|
|
121864
|
+
const queueReader = probes?.socketPlane;
|
|
121865
|
+
const queueGate = queueReader === void 0 && meshQueue === void 0 ? void 0 : createOutboundQueueGate(probes?.outboundQueue);
|
|
121866
|
+
const judgeOutboundQueues = (at) => {
|
|
121867
|
+
if (queueGate === void 0) return;
|
|
121868
|
+
const readings = outboundQueueReadings(queueReader?.(), meshQueue?.());
|
|
121869
|
+
for (const verdict of queueGate.observe(readings, at)) sink.warn(formatOutboundQueueVerdict(label, verdict));
|
|
121870
|
+
};
|
|
121193
121871
|
const censusProbe = probes?.arrayBufferCensus;
|
|
121194
121872
|
const censusGate = censusProbe === void 0 ? void 0 : createArrayBufferCensusGate(censusProbe);
|
|
121195
121873
|
let censusInFlight = false;
|
|
@@ -124414,6 +125092,32 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
124414
125092
|
Buffer.from(body.buffer, body.byteOffset, body.byteLength).copy(out, 4);
|
|
124415
125093
|
return out;
|
|
124416
125094
|
}
|
|
125095
|
+
var PAYLOAD_KEY_BYTES = Buffer.from([162, ...Buffer.from("pl")]);
|
|
125096
|
+
var BIN32_MARKER = 198;
|
|
125097
|
+
var FIXMAP_BASE = 128;
|
|
125098
|
+
var FIXMAP_MAX_COUNT = 15;
|
|
125099
|
+
function encodeFrameHead(frame, payload) {
|
|
125100
|
+
const envelope = encode(frame, ENCODE_OPTIONS);
|
|
125101
|
+
const first = envelope[0];
|
|
125102
|
+
if (envelope.byteLength === 0 || first === void 0 || first < FIXMAP_BASE || first > 142) throw new Error(`encodeFrameHead: envelope must be a msgpack fixmap with at most ${FIXMAP_MAX_COUNT - 1} keys (got leading byte 0x${(first ?? 0).toString(16)})`);
|
|
125103
|
+
const bodyLength = envelope.byteLength + PAYLOAD_KEY_BYTES.byteLength + 5 + payload.byteLength;
|
|
125104
|
+
const head = Buffer.allocUnsafe(HEADER_BYTES + envelope.byteLength + PAYLOAD_KEY_BYTES.byteLength + 5);
|
|
125105
|
+
head.writeUInt32BE(bodyLength, 0);
|
|
125106
|
+
Buffer.from(envelope.buffer, envelope.byteOffset, envelope.byteLength).copy(head, HEADER_BYTES);
|
|
125107
|
+
head[HEADER_BYTES] = first + 1;
|
|
125108
|
+
let at = HEADER_BYTES + envelope.byteLength;
|
|
125109
|
+
PAYLOAD_KEY_BYTES.copy(head, at);
|
|
125110
|
+
at += PAYLOAD_KEY_BYTES.byteLength;
|
|
125111
|
+
head[at] = BIN32_MARKER;
|
|
125112
|
+
head.writeUInt32BE(payload.byteLength, at + 1);
|
|
125113
|
+
return head;
|
|
125114
|
+
}
|
|
125115
|
+
function packPayload(value) {
|
|
125116
|
+
return encode(value, ENCODE_OPTIONS);
|
|
125117
|
+
}
|
|
125118
|
+
function unpackPayload(bytes) {
|
|
125119
|
+
return decode(bytes);
|
|
125120
|
+
}
|
|
124417
125121
|
var HEADER_BYTES = 4;
|
|
124418
125122
|
var SLAB_WASTE_MAX_BYTES = 4096;
|
|
124419
125123
|
var FrameDecoder = class {
|
|
@@ -124531,6 +125235,14 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
124531
125235
|
if (process.platform === "win32") return `\\\\.\\pipe\\camstack-${safe}`;
|
|
124532
125236
|
return (0, node_path.join)((0, node_os.tmpdir)(), `camstack-${safe}.sock`);
|
|
124533
125237
|
}
|
|
125238
|
+
var PayloadReply = class {
|
|
125239
|
+
body;
|
|
125240
|
+
payload;
|
|
125241
|
+
constructor(body, payload) {
|
|
125242
|
+
this.body = body;
|
|
125243
|
+
this.payload = payload;
|
|
125244
|
+
}
|
|
125245
|
+
};
|
|
124534
125246
|
var SocketChannel = class {
|
|
124535
125247
|
socket;
|
|
124536
125248
|
nextId = 1;
|
|
@@ -124590,7 +125302,7 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
124590
125302
|
k: "req",
|
|
124591
125303
|
id,
|
|
124592
125304
|
body
|
|
124593
|
-
});
|
|
125305
|
+
}, opts?.payload);
|
|
124594
125306
|
});
|
|
124595
125307
|
}
|
|
124596
125308
|
emit(body) {
|
|
@@ -124630,11 +125342,38 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
124630
125342
|
rx: sampleSocketDirection(this.rxCounters)
|
|
124631
125343
|
};
|
|
124632
125344
|
}
|
|
124633
|
-
|
|
125345
|
+
/**
|
|
125346
|
+
* Bytes handed to the socket that the kernel has not taken yet — the
|
|
125347
|
+
* `Writable` buffer plus the write in flight. Read LIVE, never cached: this
|
|
125348
|
+
* is the number that says whether the peer is draining what we write, and
|
|
125349
|
+
* it is read on every heartbeat probe (D446). An unref'd socket keeps it
|
|
125350
|
+
* exactly like a ref'd one, which is why it is read here and not summed
|
|
125351
|
+
* over `_getActiveHandles()`.
|
|
125352
|
+
*/
|
|
125353
|
+
queuedBytes() {
|
|
125354
|
+
return this.socket.writableLength;
|
|
125355
|
+
}
|
|
125356
|
+
/**
|
|
125357
|
+
* Write one frame. With a payload the head and the tail are two `write`
|
|
125358
|
+
* calls under `cork()` — the kernel sees one `writev`, and the payload bytes
|
|
125359
|
+
* are never copied into the head. A forwarded payload is a view into the
|
|
125360
|
+
* frame it arrived on, and that frame's buffer is never mutated, so handing
|
|
125361
|
+
* the view to the socket is safe.
|
|
125362
|
+
*/
|
|
125363
|
+
send(frame, payload) {
|
|
124634
125364
|
if (this.closed) return;
|
|
124635
|
-
|
|
124636
|
-
|
|
124637
|
-
|
|
125365
|
+
if (payload === void 0) {
|
|
125366
|
+
const encoded = encodeFrame(frame);
|
|
125367
|
+
recordSocketFrame(this.txCounters, frame.k, encoded.byteLength);
|
|
125368
|
+
this.socket.write(encoded);
|
|
125369
|
+
return;
|
|
125370
|
+
}
|
|
125371
|
+
const head = encodeFrameHead(frame, payload);
|
|
125372
|
+
recordSocketFrame(this.txCounters, frame.k, head.byteLength + payload.byteLength);
|
|
125373
|
+
this.socket.cork();
|
|
125374
|
+
this.socket.write(head);
|
|
125375
|
+
this.socket.write(payload);
|
|
125376
|
+
this.socket.uncork();
|
|
124638
125377
|
}
|
|
124639
125378
|
onData(chunk) {
|
|
124640
125379
|
const frames = this.decoder.push(chunk);
|
|
@@ -124654,8 +125393,14 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
124654
125393
|
recordSocketFrame(this.rxCounters, frame.k, wireBytes);
|
|
124655
125394
|
if (frame.k === "req") {
|
|
124656
125395
|
try {
|
|
124657
|
-
const result = await this.requestHandler(frame.body);
|
|
124658
|
-
this.send({
|
|
125396
|
+
const result = await this.requestHandler(frame.body, frame.pl);
|
|
125397
|
+
if (result instanceof PayloadReply) this.send({
|
|
125398
|
+
k: "res",
|
|
125399
|
+
id: frame.id,
|
|
125400
|
+
ok: true,
|
|
125401
|
+
body: result.body
|
|
125402
|
+
}, result.payload);
|
|
125403
|
+
else this.send({
|
|
124659
125404
|
k: "res",
|
|
124660
125405
|
id: frame.id,
|
|
124661
125406
|
ok: true,
|
|
@@ -124676,8 +125421,9 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
124676
125421
|
if (!p) return;
|
|
124677
125422
|
this.pending.delete(frame.id);
|
|
124678
125423
|
if (p.timer !== null) clearTimeout(p.timer);
|
|
124679
|
-
if (frame.ok) p.
|
|
124680
|
-
else p.
|
|
125424
|
+
if (!frame.ok) p.reject(new Error(frame.err));
|
|
125425
|
+
else if (frame.pl !== void 0) p.resolve(new PayloadReply(frame.body, frame.pl));
|
|
125426
|
+
else p.resolve(frame.body);
|
|
124681
125427
|
return;
|
|
124682
125428
|
}
|
|
124683
125429
|
this.eventHandler(frame.body);
|
|
@@ -125066,397 +125812,15 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
125066
125812
|
}
|
|
125067
125813
|
}
|
|
125068
125814
|
}
|
|
125069
|
-
|
|
125070
|
-
|
|
125071
|
-
|
|
125072
|
-
|
|
125073
|
-
const type = err.type;
|
|
125074
|
-
return typeof type === "string" && DISCOVERY_ERROR_TYPES.has(type);
|
|
125075
|
-
}
|
|
125076
|
-
async function callWithServiceDiscovery(broker, serviceName, action, params, opts, discoveryTimeoutMs = DEFAULT_DISCOVERY_TIMEOUT_MS$1) {
|
|
125077
|
-
try {
|
|
125078
|
-
return await broker.call(action, params, opts);
|
|
125079
|
-
} catch (err) {
|
|
125080
|
-
if (!isDiscoveryError(err)) throw err;
|
|
125081
|
-
await broker.waitForServices([serviceName], discoveryTimeoutMs);
|
|
125082
|
-
return await broker.call(action, params, opts);
|
|
125083
|
-
}
|
|
125084
|
-
}
|
|
125085
|
-
function buildMessage(capName, method, detail) {
|
|
125086
|
-
const call = method !== void 0 ? `${capName}.${method}` : capName;
|
|
125087
|
-
const target = detail.nodeId !== void 0 ? ` to node ${detail.nodeId}` : "";
|
|
125088
|
-
const rejectedStr = detail.rejected.map((r) => `${r.kind}=${r.why}`).join("; ");
|
|
125089
|
-
const rejectedClause = rejectedStr.length > 0 ? ` (rejected: ${rejectedStr})` : "";
|
|
125090
|
-
return `${call} not routable${target}: ${detail.reason}${rejectedClause}`;
|
|
125091
|
-
}
|
|
125092
|
-
var CapRouteError = class extends Error {
|
|
125093
|
-
reason;
|
|
125094
|
-
nodeId;
|
|
125095
|
-
rejected;
|
|
125096
|
-
/**
|
|
125097
|
-
* @param cause Optional original error that triggered this routing failure.
|
|
125098
|
-
* Stored as `Error.cause` (TC39 standard option, Node 16.9+).
|
|
125099
|
-
* Dispatchers wrapping transport errors MUST pass the original.
|
|
125100
|
-
*/
|
|
125101
|
-
constructor(capName, method, detail, cause) {
|
|
125102
|
-
super(buildMessage(capName, method, detail), cause !== void 0 ? { cause } : void 0);
|
|
125103
|
-
this.name = "CapRouteError";
|
|
125104
|
-
this.reason = detail.reason;
|
|
125105
|
-
this.nodeId = detail.nodeId;
|
|
125106
|
-
this.rejected = detail.rejected;
|
|
125107
|
-
}
|
|
125108
|
-
};
|
|
125109
|
-
function classifyCapRoute(capName, opts, snapshot) {
|
|
125110
|
-
const rejected = [];
|
|
125111
|
-
if (opts.nodeId !== void 0) return classifyExplicitNode(capName, opts.nodeId, opts.deviceId, snapshot, rejected);
|
|
125112
|
-
return classifySingleton(capName, opts.deviceId, snapshot, rejected);
|
|
125113
|
-
}
|
|
125114
|
-
function classifyExplicitNode(capName, nodeId, deviceId, snap, rejected) {
|
|
125115
|
-
if (nodeId === snap.hubNodeId) {
|
|
125116
|
-
const residentProvides = snap.hubResidentProvides;
|
|
125117
|
-
const providesOnHub = residentProvides ?? snap.hubInProcessProvides;
|
|
125118
|
-
const getRef = residentProvides !== void 0 ? snap.getHubResidentProviderRef : snap.getInProcessProviderRef;
|
|
125119
|
-
if (providesOnHub(capName)) {
|
|
125120
|
-
const ref = getRef?.(capName) ?? null;
|
|
125121
|
-
if (ref !== null) return {
|
|
125122
|
-
kind: "hub-in-process",
|
|
125123
|
-
capName,
|
|
125124
|
-
ref
|
|
125125
|
-
};
|
|
125126
|
-
rejected.push({
|
|
125127
|
-
kind: "hub-in-process",
|
|
125128
|
-
why: "provider ref not available in snapshot"
|
|
125129
|
-
});
|
|
125130
|
-
throw new CapRouteError(capName, void 0, {
|
|
125131
|
-
reason: "no-provider",
|
|
125132
|
-
nodeId,
|
|
125133
|
-
rejected
|
|
125134
|
-
});
|
|
125135
|
-
}
|
|
125136
|
-
if (snap.hubLocalChildProvides(capName, deviceId)) {
|
|
125137
|
-
const childId = snap.getHubLocalChildId?.(capName, deviceId) ?? null;
|
|
125138
|
-
if (childId !== null) return {
|
|
125139
|
-
kind: "hub-local-uds",
|
|
125140
|
-
capName,
|
|
125141
|
-
childId
|
|
125142
|
-
};
|
|
125143
|
-
rejected.push({
|
|
125144
|
-
kind: "hub-local-uds",
|
|
125145
|
-
why: "child id not resolvable from snapshot"
|
|
125146
|
-
});
|
|
125147
|
-
throw new CapRouteError(capName, void 0, {
|
|
125148
|
-
reason: "no-provider",
|
|
125149
|
-
nodeId,
|
|
125150
|
-
rejected
|
|
125151
|
-
});
|
|
125152
|
-
}
|
|
125153
|
-
rejected.push({
|
|
125154
|
-
kind: "hub-in-process",
|
|
125155
|
-
why: "hub does not provide this cap in-process"
|
|
125156
|
-
});
|
|
125157
|
-
rejected.push({
|
|
125158
|
-
kind: "hub-local-uds",
|
|
125159
|
-
why: "no hub-local child provides this cap"
|
|
125160
|
-
});
|
|
125161
|
-
throw new CapRouteError(capName, void 0, {
|
|
125162
|
-
reason: "no-provider",
|
|
125163
|
-
nodeId,
|
|
125164
|
-
rejected
|
|
125165
|
-
});
|
|
125166
|
-
}
|
|
125167
|
-
if (!snap.nodeOnline(nodeId)) {
|
|
125168
|
-
rejected.push({
|
|
125169
|
-
kind: "remote-moleculer",
|
|
125170
|
-
why: `node ${nodeId} is offline`
|
|
125171
|
-
});
|
|
125172
|
-
throw new CapRouteError(capName, void 0, {
|
|
125173
|
-
reason: "node-offline",
|
|
125174
|
-
nodeId,
|
|
125175
|
-
rejected
|
|
125176
|
-
});
|
|
125177
|
-
}
|
|
125178
|
-
if (snap.nodeIsAgent(nodeId)) {
|
|
125179
|
-
if (snap.nodeKnowsCap(nodeId, capName)) return {
|
|
125180
|
-
kind: "agent-child-forward",
|
|
125181
|
-
capName,
|
|
125182
|
-
agentNodeId: nodeId,
|
|
125183
|
-
childId: snap.getAgentChildId?.(nodeId, capName) ?? void 0
|
|
125184
|
-
};
|
|
125185
|
-
rejected.push({
|
|
125186
|
-
kind: "agent-child-forward",
|
|
125187
|
-
why: `agent ${nodeId} does not know cap ${capName}`
|
|
125188
|
-
});
|
|
125189
|
-
throw new CapRouteError(capName, void 0, {
|
|
125190
|
-
reason: "no-provider",
|
|
125191
|
-
nodeId,
|
|
125192
|
-
rejected
|
|
125193
|
-
});
|
|
125194
|
-
}
|
|
125195
|
-
return {
|
|
125196
|
-
kind: "remote-moleculer",
|
|
125197
|
-
capName,
|
|
125198
|
-
nodeId
|
|
125199
|
-
};
|
|
125200
|
-
}
|
|
125201
|
-
function classifySingleton(capName, deviceId, snap, rejected) {
|
|
125202
|
-
if (snap.hubInProcessProvides(capName)) {
|
|
125203
|
-
const ref = snap.getInProcessProviderRef?.(capName) ?? null;
|
|
125204
|
-
if (ref !== null) return {
|
|
125205
|
-
kind: "hub-in-process",
|
|
125206
|
-
capName,
|
|
125207
|
-
ref
|
|
125208
|
-
};
|
|
125209
|
-
rejected.push({
|
|
125210
|
-
kind: "hub-in-process",
|
|
125211
|
-
why: "provider ref not available in snapshot"
|
|
125212
|
-
});
|
|
125213
|
-
} else rejected.push({
|
|
125214
|
-
kind: "hub-in-process",
|
|
125215
|
-
why: "hub does not provide this cap in-process"
|
|
125216
|
-
});
|
|
125217
|
-
if (snap.hubLocalChildProvides(capName, deviceId)) {
|
|
125218
|
-
const childId = snap.getHubLocalChildId?.(capName, deviceId) ?? null;
|
|
125219
|
-
if (childId !== null) return {
|
|
125220
|
-
kind: "hub-local-uds",
|
|
125221
|
-
capName,
|
|
125222
|
-
childId
|
|
125223
|
-
};
|
|
125224
|
-
rejected.push({
|
|
125225
|
-
kind: "hub-local-uds",
|
|
125226
|
-
why: "child id not resolvable from snapshot"
|
|
125227
|
-
});
|
|
125228
|
-
} else rejected.push({
|
|
125229
|
-
kind: "hub-local-uds",
|
|
125230
|
-
why: "no hub-local child provides this cap"
|
|
125231
|
-
});
|
|
125232
|
-
const knownNodes = snap.listKnownNodeIds?.() ?? [];
|
|
125233
|
-
for (const nodeId of knownNodes) if (nodeId !== snap.hubNodeId && snap.nodeOnline(nodeId) && snap.nodeKnowsCap(nodeId, capName)) return {
|
|
125234
|
-
kind: "remote-moleculer",
|
|
125235
|
-
capName,
|
|
125236
|
-
nodeId
|
|
125237
|
-
};
|
|
125238
|
-
rejected.push({
|
|
125239
|
-
kind: "remote-moleculer",
|
|
125240
|
-
why: "no online remote node knows this cap"
|
|
125241
|
-
});
|
|
125242
|
-
throw new CapRouteError(capName, void 0, {
|
|
125243
|
-
reason: "no-provider",
|
|
125244
|
-
rejected
|
|
125245
|
-
});
|
|
125246
|
-
}
|
|
125247
|
-
var AGENT_CAP_FWD_SERVICE = "$agent-cap-fwd";
|
|
125248
|
-
var AGENT_CAP_FWD_ACTION = `${AGENT_CAP_FWD_SERVICE}.forward`;
|
|
125249
|
-
var REMOTE_CALL_TIMEOUT_MS = 6e4;
|
|
125250
|
-
function extractDeviceId(args) {
|
|
125251
|
-
if (args === null || typeof args !== "object") return void 0;
|
|
125252
|
-
const raw = Reflect.get(args, "deviceId");
|
|
125253
|
-
return typeof raw === "number" ? raw : void 0;
|
|
125254
|
-
}
|
|
125255
|
-
function extractNodeId(args) {
|
|
125256
|
-
if (args === null || typeof args !== "object") return void 0;
|
|
125257
|
-
const raw = Reflect.get(args, "nodeId");
|
|
125258
|
-
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
125259
|
-
}
|
|
125260
|
-
function withCallerAddonId(args, callerAddonId) {
|
|
125261
|
-
if (callerAddonId === void 0) return args;
|
|
125262
|
-
if (args === null || typeof args !== "object" || Array.isArray(args)) return args;
|
|
125815
|
+
function liftRoutingHints(args) {
|
|
125816
|
+
if (args === null || typeof args !== "object" || Array.isArray(args)) return {};
|
|
125817
|
+
const nodeId = Reflect.get(args, "nodeId");
|
|
125818
|
+
const addonId = Reflect.get(args, "addonId");
|
|
125263
125819
|
return {
|
|
125264
|
-
...
|
|
125265
|
-
|
|
125820
|
+
...typeof nodeId === "string" && nodeId.length > 0 ? { nodeId } : {},
|
|
125821
|
+
...typeof addonId === "string" && addonId.length > 0 ? { addonId } : {}
|
|
125266
125822
|
};
|
|
125267
125823
|
}
|
|
125268
|
-
var CapRouteResolver = class {
|
|
125269
|
-
hubNodeId;
|
|
125270
|
-
broker;
|
|
125271
|
-
hubLocalRegistry;
|
|
125272
|
-
nodeAuthority;
|
|
125273
|
-
inProcessProviders;
|
|
125274
|
-
hubResidentProviders;
|
|
125275
|
-
capTimeoutMs;
|
|
125276
|
-
snapshot;
|
|
125277
|
-
constructor(deps) {
|
|
125278
|
-
this.hubNodeId = deps.hubNodeId;
|
|
125279
|
-
this.broker = deps.broker;
|
|
125280
|
-
this.hubLocalRegistry = deps.hubLocalRegistry;
|
|
125281
|
-
this.nodeAuthority = deps.nodeAuthority;
|
|
125282
|
-
this.inProcessProviders = deps.inProcessProviders;
|
|
125283
|
-
this.hubResidentProviders = deps.hubResidentProviders;
|
|
125284
|
-
this.capTimeoutMs = deps.capTimeoutMs;
|
|
125285
|
-
this.snapshot = this.buildSnapshot();
|
|
125286
|
-
}
|
|
125287
|
-
/** Per-call RPC timeout: the cap method's declared override, else the default. */
|
|
125288
|
-
callTimeout(capName, method) {
|
|
125289
|
-
return this.capTimeoutMs?.(capName, method) ?? REMOTE_CALL_TIMEOUT_MS;
|
|
125290
|
-
}
|
|
125291
|
-
resolveCapRoute(capName, opts) {
|
|
125292
|
-
return classifyCapRoute(capName, opts, this.snapshot);
|
|
125293
|
-
}
|
|
125294
|
-
/**
|
|
125295
|
-
* Resolve the hub-local-uds route for a cap owned by a forked hub-local
|
|
125296
|
-
* child, IGNORING any in-hub provider registered for the same cap name.
|
|
125297
|
-
*
|
|
125298
|
-
* `resolveCapRoute` gives Priority 1 to `hub-in-process`: when an in-hub
|
|
125299
|
-
* provider (e.g. a wrapper) is registered for the cap, the route always
|
|
125300
|
-
* classifies as `hub-in-process` and the hub-local-uds NATIVE child is never
|
|
125301
|
-
* reached. That is correct for the generic dispatch path (the wrapper is the
|
|
125302
|
-
* active provider), but WRONG for the native-cap fallback
|
|
125303
|
-
* (`setNativeFallback`), whose contract is to reach the NATIVE provider in
|
|
125304
|
-
* the forked vendor child so a wrapper can delegate to it. A wrapper cap
|
|
125305
|
-
* with a forked native (today: `snapshot`) otherwise resolves to the wrapper
|
|
125306
|
-
* itself, the native is never invoked, and the wrapper silently falls
|
|
125307
|
-
* through to its secondary strategy.
|
|
125308
|
-
*
|
|
125309
|
-
* This method consults ONLY the hub-local-child authority
|
|
125310
|
-
* (`hubLocalChildProvides` + `getHubLocalChildId`, both deviceId-aware), so
|
|
125311
|
-
* it returns the native child route regardless of any in-process shadow.
|
|
125312
|
-
* Returns null when no hub-local child owns `(capName, deviceId)` — the
|
|
125313
|
-
* caller then falls through to its remote-resolution branch.
|
|
125314
|
-
*/
|
|
125315
|
-
resolveHubLocalUdsRoute(capName, deviceId) {
|
|
125316
|
-
if (!this.snapshot.hubLocalChildProvides(capName, deviceId)) return null;
|
|
125317
|
-
const childId = this.snapshot.getHubLocalChildId?.(capName, deviceId) ?? null;
|
|
125318
|
-
if (childId === null) return null;
|
|
125319
|
-
return {
|
|
125320
|
-
kind: "hub-local-uds",
|
|
125321
|
-
capName,
|
|
125322
|
-
childId
|
|
125323
|
-
};
|
|
125324
|
-
}
|
|
125325
|
-
/**
|
|
125326
|
-
* @param addonId Optional out-of-band PROVIDER-selection hint (Task 7.5a):
|
|
125327
|
-
* the addonId of the provider the CALLER already resolved (e.g.
|
|
125328
|
-
* `buildCapCallFn`'s `deps.addonId` for a registered grouped-runner
|
|
125329
|
-
* provider). Only meaningful for `agent-child-forward` — a `remote-moleculer`
|
|
125330
|
-
* route already encodes the provider in its action name
|
|
125331
|
-
* (`${addonId}.${cap}.${method}`, via `NodeCapAuthority.getAddonId`), and a
|
|
125332
|
-
* `hub-local-uds` caller that already knows the addonId (`buildCapCallFn`)
|
|
125333
|
-
* talks to `LocalChildRegistry.callCapOnChild` directly rather than through
|
|
125334
|
-
* `dispatch`.
|
|
125335
|
-
* @param callerAddonId Optional out-of-band CALLER-identity hint — the
|
|
125336
|
-
* addon that ORIGINATED the call, distinct from `addonId` above (which
|
|
125337
|
-
* names the resolved PROVIDER, not the caller). Set by
|
|
125338
|
-
* `onUnownedCall` from `CapCallInput.callerAddonId`
|
|
125339
|
-
* (`LocalChildRegistry` stamped it off the registered `childId`). Only
|
|
125340
|
-
* the `hub-in-process` branch consumes it — merged into `args` so a
|
|
125341
|
-
* diagnostic tool deep in that provider (e.g. device-manager's
|
|
125342
|
-
* fleet-read census) can read it without every provider method changing
|
|
125343
|
-
* signature, the same "extra field the provider destructures or
|
|
125344
|
-
* ignores" convention `nodeId` already uses on this path.
|
|
125345
|
-
*/
|
|
125346
|
-
async dispatch(route, method, args, addonId, callerAddonId) {
|
|
125347
|
-
try {
|
|
125348
|
-
return await this.dispatchInner(route, method, args, addonId, callerAddonId);
|
|
125349
|
-
} catch (err) {
|
|
125350
|
-
if (err instanceof CapRouteError) throw err;
|
|
125351
|
-
const nodeId = this.routeNodeId(route);
|
|
125352
|
-
const cause = err instanceof Error ? err : new Error(String(err));
|
|
125353
|
-
throw new CapRouteError(route.capName, method, {
|
|
125354
|
-
reason: "transport-failed",
|
|
125355
|
-
nodeId,
|
|
125356
|
-
rejected: [{
|
|
125357
|
-
kind: route.kind,
|
|
125358
|
-
why: cause.message
|
|
125359
|
-
}]
|
|
125360
|
-
}, cause);
|
|
125361
|
-
}
|
|
125362
|
-
}
|
|
125363
|
-
/**
|
|
125364
|
-
* Inner dispatch: may throw CapRouteError (validation failures) or arbitrary
|
|
125365
|
-
* transport errors. The outer `dispatch` wraps non-CapRouteErrors.
|
|
125366
|
-
*/
|
|
125367
|
-
async dispatchInner(route, method, args, addonId, callerAddonId) {
|
|
125368
|
-
switch (route.kind) {
|
|
125369
|
-
case "hub-in-process":
|
|
125370
|
-
return route.ref.invoke(method, withCallerAddonId(args, callerAddonId));
|
|
125371
|
-
case "hub-local-uds": {
|
|
125372
|
-
const registry = this.hubLocalRegistry;
|
|
125373
|
-
if (registry === null) throw new CapRouteError(route.capName, method, {
|
|
125374
|
-
reason: "no-provider",
|
|
125375
|
-
rejected: [{
|
|
125376
|
-
kind: "hub-local-uds",
|
|
125377
|
-
why: "UDS registry not available"
|
|
125378
|
-
}]
|
|
125379
|
-
});
|
|
125380
|
-
const deviceId = extractDeviceId(args);
|
|
125381
|
-
const input = {
|
|
125382
|
-
capName: route.capName,
|
|
125383
|
-
method,
|
|
125384
|
-
args,
|
|
125385
|
-
...deviceId !== void 0 ? { deviceId } : {}
|
|
125386
|
-
};
|
|
125387
|
-
return registry.callCapOnChild(route.childId, input);
|
|
125388
|
-
}
|
|
125389
|
-
case "remote-moleculer": {
|
|
125390
|
-
const addonId2 = this.nodeAuthority.getAddonId(route.nodeId, route.capName);
|
|
125391
|
-
if (addonId2 === null) throw new CapRouteError(route.capName, method, {
|
|
125392
|
-
reason: "no-provider",
|
|
125393
|
-
nodeId: route.nodeId,
|
|
125394
|
-
rejected: [{
|
|
125395
|
-
kind: "remote-moleculer",
|
|
125396
|
-
why: `no addonId known for ${route.nodeId}/${route.capName}`
|
|
125397
|
-
}]
|
|
125398
|
-
});
|
|
125399
|
-
const deviceId = extractDeviceId(args);
|
|
125400
|
-
const isNative = this.nodeAuthority.isNativeCap(route.nodeId, route.capName, deviceId);
|
|
125401
|
-
const action = capActionName(addonId2, route.capName, method, isNative);
|
|
125402
|
-
return callWithServiceDiscovery(this.broker, addonId2, action, args, {
|
|
125403
|
-
nodeID: route.nodeId,
|
|
125404
|
-
timeout: this.callTimeout(route.capName, method)
|
|
125405
|
-
});
|
|
125406
|
-
}
|
|
125407
|
-
case "agent-child-forward": {
|
|
125408
|
-
const deviceId = extractDeviceId(args);
|
|
125409
|
-
const params = {
|
|
125410
|
-
capName: route.capName,
|
|
125411
|
-
method,
|
|
125412
|
-
args,
|
|
125413
|
-
...route.childId !== void 0 ? { childId: route.childId } : {},
|
|
125414
|
-
...deviceId !== void 0 ? { deviceId } : {},
|
|
125415
|
-
...addonId !== void 0 ? { addonId } : {}
|
|
125416
|
-
};
|
|
125417
|
-
return callWithServiceDiscovery(this.broker, AGENT_CAP_FWD_SERVICE, AGENT_CAP_FWD_ACTION, params, {
|
|
125418
|
-
nodeID: route.agentNodeId,
|
|
125419
|
-
timeout: this.callTimeout(route.capName, method)
|
|
125420
|
-
});
|
|
125421
|
-
}
|
|
125422
|
-
}
|
|
125423
|
-
}
|
|
125424
|
-
buildSnapshot() {
|
|
125425
|
-
const hubLocalRegistry = this.hubLocalRegistry;
|
|
125426
|
-
const nodeAuthority = this.nodeAuthority;
|
|
125427
|
-
const inProcessProviders = this.inProcessProviders;
|
|
125428
|
-
const hubResidentProviders = this.hubResidentProviders;
|
|
125429
|
-
return {
|
|
125430
|
-
hubNodeId: this.hubNodeId,
|
|
125431
|
-
hubInProcessProvides: (cap) => inProcessProviders(cap) !== null,
|
|
125432
|
-
...hubResidentProviders !== void 0 ? {
|
|
125433
|
-
hubResidentProvides: (cap) => hubResidentProviders(cap) !== null,
|
|
125434
|
-
getHubResidentProviderRef: (cap) => hubResidentProviders(cap)
|
|
125435
|
-
} : {},
|
|
125436
|
-
hubLocalChildProvides: (cap, deviceId) => hubLocalRegistry !== null && hubLocalRegistry.resolveChildId(cap, deviceId) !== null,
|
|
125437
|
-
nodeKnowsCap: (nodeId, cap) => nodeAuthority.nodeKnowsCap(nodeId, cap),
|
|
125438
|
-
nodeIsAgent: (nodeId) => nodeAuthority.nodeIsAgent(nodeId),
|
|
125439
|
-
nodeOnline: (nodeId) => nodeAuthority.nodeOnline(nodeId),
|
|
125440
|
-
listKnownNodeIds: () => nodeAuthority.listNodeIds(),
|
|
125441
|
-
getInProcessProviderRef: (cap) => inProcessProviders(cap),
|
|
125442
|
-
getHubLocalChildId: (cap, deviceId) => hubLocalRegistry !== null ? hubLocalRegistry.resolveChildId(cap, deviceId) : null,
|
|
125443
|
-
getAgentChildId: (agentNodeId, cap) => nodeAuthority.getAgentChildId(agentNodeId, cap)
|
|
125444
|
-
};
|
|
125445
|
-
}
|
|
125446
|
-
/** Extract a nodeId string from a route for error reporting, or undefined. */
|
|
125447
|
-
routeNodeId(route) {
|
|
125448
|
-
switch (route.kind) {
|
|
125449
|
-
case "hub-in-process":
|
|
125450
|
-
return this.hubNodeId;
|
|
125451
|
-
case "hub-local-uds":
|
|
125452
|
-
return `${this.hubNodeId}/${route.childId}`;
|
|
125453
|
-
case "remote-moleculer":
|
|
125454
|
-
return route.nodeId;
|
|
125455
|
-
case "agent-child-forward":
|
|
125456
|
-
return route.agentNodeId;
|
|
125457
|
-
}
|
|
125458
|
-
}
|
|
125459
|
-
};
|
|
125460
125824
|
function readFanoutMode() {
|
|
125461
125825
|
const raw = process.env.CAMSTACK_UDS_EVENT_FANOUT;
|
|
125462
125826
|
if (raw === "shadow" || raw === "broadcast") return raw;
|
|
@@ -125484,6 +125848,9 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
125484
125848
|
/** See {@link LocalChildRegistryOptions.isAggregatedCollectionMethod}. */
|
|
125485
125849
|
isAggregatedCollectionMethod;
|
|
125486
125850
|
isAddonPinnedCall;
|
|
125851
|
+
/** See {@link ForwardCensus}. Mutable counters on the hot path, by design. */
|
|
125852
|
+
forwardedRaw = 0;
|
|
125853
|
+
forwardedDecoded = 0;
|
|
125487
125854
|
/** See {@link LocalChildRegistryOptions.capTimeoutMs}. */
|
|
125488
125855
|
capTimeoutMs;
|
|
125489
125856
|
/** See {@link LocalChildRegistryOptions.capUsageObserver}. */
|
|
@@ -125559,6 +125926,24 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
125559
125926
|
return entry.channel.readTraffic?.() ?? null;
|
|
125560
125927
|
}
|
|
125561
125928
|
/**
|
|
125929
|
+
* Bytes this process has written to a child that the child has not yet
|
|
125930
|
+
* taken, live, or `null` when the channel keeps no such reading. Read on
|
|
125931
|
+
* every heartbeat probe (D446) — a child that stops draining is the shape
|
|
125932
|
+
* of an outbound-queue episode, and the number lives on the channel.
|
|
125933
|
+
*/
|
|
125934
|
+
getChildQueuedBytes(childId) {
|
|
125935
|
+
const entry = this.children.get(childId);
|
|
125936
|
+
if (entry === void 0) return null;
|
|
125937
|
+
return entry.channel.queuedBytes?.() ?? null;
|
|
125938
|
+
}
|
|
125939
|
+
/** Cumulative {@link ForwardCensus} of this parent's `cap-call-out` routing. */
|
|
125940
|
+
readForwardCensus() {
|
|
125941
|
+
return {
|
|
125942
|
+
raw: this.forwardedRaw,
|
|
125943
|
+
decoded: this.forwardedDecoded
|
|
125944
|
+
};
|
|
125945
|
+
}
|
|
125946
|
+
/**
|
|
125562
125947
|
* The regime the counters above were produced under, read once from
|
|
125563
125948
|
* `CAMSTACK_UDS_EVENT_FANOUT` at construction.
|
|
125564
125949
|
*
|
|
@@ -125937,7 +126322,7 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
125937
126322
|
return;
|
|
125938
126323
|
}
|
|
125939
126324
|
});
|
|
125940
|
-
channel.onRequest(async (body) => {
|
|
126325
|
+
channel.onRequest(async (body, payload) => {
|
|
125941
126326
|
const msg = body;
|
|
125942
126327
|
if (msg.kind === "register") {
|
|
125943
126328
|
if (childId !== null && childId !== msg.childId) throw new Error(`child attempted to change identity from "${childId}" to "${msg.childId}"`);
|
|
@@ -125954,7 +126339,8 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
125954
126339
|
channel,
|
|
125955
126340
|
caps: msg.caps,
|
|
125956
126341
|
eventPatterns,
|
|
125957
|
-
incarnation
|
|
126342
|
+
incarnation,
|
|
126343
|
+
rawForward: msg.rawForward === true
|
|
125958
126344
|
});
|
|
125959
126345
|
this.logPatternSet(msg.childId, eventPatterns);
|
|
125960
126346
|
this.registeredHandler({
|
|
@@ -125963,23 +126349,28 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
125963
126349
|
incarnation,
|
|
125964
126350
|
...msg.customActions !== void 0 ? { customActions: msg.customActions } : {}
|
|
125965
126351
|
});
|
|
125966
|
-
return {
|
|
126352
|
+
return {
|
|
126353
|
+
ok: true,
|
|
126354
|
+
rawForward: true
|
|
126355
|
+
};
|
|
125967
126356
|
}
|
|
125968
126357
|
if (msg.kind === "cap-call-out") {
|
|
125969
126358
|
const out = msg;
|
|
125970
|
-
const
|
|
126359
|
+
const hints = out.hints ?? liftRoutingHints(out.args);
|
|
126360
|
+
const materialise = () => payload !== void 0 ? unpackPayload(payload) : out.args;
|
|
126361
|
+
const buildInput = () => ({
|
|
125971
126362
|
capName: out.capName,
|
|
125972
126363
|
method: out.method,
|
|
125973
|
-
args:
|
|
126364
|
+
args: materialise(),
|
|
125974
126365
|
...out.deviceId !== void 0 ? { deviceId: out.deviceId } : {},
|
|
125975
126366
|
...out.nodeId !== void 0 ? { nodeId: out.nodeId } : {},
|
|
125976
126367
|
...out.native === true ? { native: true } : {},
|
|
125977
126368
|
...childId !== null ? { callerAddonId: childId } : {}
|
|
125978
|
-
};
|
|
125979
|
-
const pinnedNodeId = out.nodeId ??
|
|
126369
|
+
});
|
|
126370
|
+
const pinnedNodeId = out.nodeId ?? hints.nodeId;
|
|
125980
126371
|
const pinTargetsThisNode = pinnedNodeId !== void 0 && this.ownNodeId !== void 0 && pinnedNodeId === this.ownNodeId;
|
|
125981
126372
|
const aggregated = pinnedNodeId === void 0 && this.isAggregatedCollectionMethod?.(out.capName, out.method) === true;
|
|
125982
|
-
const addonPinned = pinnedNodeId === void 0 && this.isAddonPinnedCall?.(out.capName, out.method,
|
|
126373
|
+
const addonPinned = pinnedNodeId === void 0 && this.isAddonPinnedCall?.(out.capName, out.method, hints) === true;
|
|
125983
126374
|
const target = !(out.native === true) && !aggregated && !addonPinned && (pinnedNodeId === void 0 || pinTargetsThisNode) ? this.resolveChildId(out.capName, out.deviceId) : null;
|
|
125984
126375
|
this.recordCapUsage(childId, target, out.capName, out.method);
|
|
125985
126376
|
if (target !== null) {
|
|
@@ -125987,9 +126378,27 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
125987
126378
|
this.egressRoutedCaps.add(out.capName);
|
|
125988
126379
|
this.logger?.info("routed child egress over UDS", { capName: out.capName });
|
|
125989
126380
|
}
|
|
125990
|
-
|
|
126381
|
+
const entry = this.children.get(target);
|
|
126382
|
+
if (payload !== void 0 && entry !== void 0 && entry.rawForward) {
|
|
126383
|
+
this.forwardedRaw += 1;
|
|
126384
|
+
const forward = {
|
|
126385
|
+
kind: "cap-call",
|
|
126386
|
+
capName: out.capName,
|
|
126387
|
+
method: out.method,
|
|
126388
|
+
args: void 0,
|
|
126389
|
+
...out.deviceId !== void 0 ? { deviceId: out.deviceId } : {}
|
|
126390
|
+
};
|
|
126391
|
+
const declared = this.capTimeoutMs?.(out.capName, out.method);
|
|
126392
|
+
return entry.channel.request(forward, {
|
|
126393
|
+
...typeof declared === "number" ? { timeoutMs: declared } : {},
|
|
126394
|
+
payload
|
|
126395
|
+
});
|
|
126396
|
+
}
|
|
126397
|
+
this.forwardedDecoded += 1;
|
|
126398
|
+
return this.callCap(buildInput());
|
|
125991
126399
|
}
|
|
125992
|
-
|
|
126400
|
+
this.forwardedDecoded += 1;
|
|
126401
|
+
if (this.onUnownedCall !== void 0) return this.onUnownedCall(buildInput());
|
|
125993
126402
|
throw new Error(`${UDS_NO_ROUTE_PREFIX}: cap-call-out has no local provider for "${out.capName}" and no fallback`);
|
|
125994
126403
|
}
|
|
125995
126404
|
if (msg.kind === "readiness-request") return {
|
|
@@ -126017,6 +126426,10 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126017
126426
|
});
|
|
126018
126427
|
}
|
|
126019
126428
|
};
|
|
126429
|
+
function ackAcceptsRawForward(ack) {
|
|
126430
|
+
if (ack === null || typeof ack !== "object") return false;
|
|
126431
|
+
return ack.rawForward === true;
|
|
126432
|
+
}
|
|
126020
126433
|
var LocalChildClient = class {
|
|
126021
126434
|
options;
|
|
126022
126435
|
client = null;
|
|
@@ -126057,6 +126470,13 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126057
126470
|
latestCustomActions = null;
|
|
126058
126471
|
/** Events and logs queued while the channel is not yet open. */
|
|
126059
126472
|
pendingEmits = [];
|
|
126473
|
+
/**
|
|
126474
|
+
* Whether the parent acknowledged raw-forward at `register`. Until it has,
|
|
126475
|
+
* `callOut` sends args inline exactly as every child always did — a legacy
|
|
126476
|
+
* parent would decode a payload-borne call to `args: undefined` and run the
|
|
126477
|
+
* provider on nothing, silently. Re-read on every re-register.
|
|
126478
|
+
*/
|
|
126479
|
+
parentRawForward = false;
|
|
126060
126480
|
/** Handler for parent→child events. Registered via `onEvent`. */
|
|
126061
126481
|
eventHandler = null;
|
|
126062
126482
|
/**
|
|
@@ -126164,15 +126584,20 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126164
126584
|
if (this.client !== null) throw new Error("LocalChildClient: already started \u2014 call close() first");
|
|
126165
126585
|
const client = createLocalTransport().createClient(this.options.nodeId);
|
|
126166
126586
|
const channel = await client.connect();
|
|
126167
|
-
channel.onRequest(async (body) => {
|
|
126587
|
+
channel.onRequest(async (body, payload) => {
|
|
126168
126588
|
const msg = body;
|
|
126169
|
-
if (msg.kind === "cap-call")
|
|
126170
|
-
|
|
126171
|
-
|
|
126172
|
-
|
|
126173
|
-
|
|
126174
|
-
|
|
126175
|
-
|
|
126589
|
+
if (msg.kind === "cap-call") {
|
|
126590
|
+
const args = payload !== void 0 ? unpackPayload(payload) : msg.args;
|
|
126591
|
+
const result = await this.options.dispatch({
|
|
126592
|
+
capName: msg.capName,
|
|
126593
|
+
method: msg.method,
|
|
126594
|
+
args,
|
|
126595
|
+
...msg.deviceId !== void 0 ? { deviceId: msg.deviceId } : {},
|
|
126596
|
+
...msg.addonId !== void 0 ? { addonId: msg.addonId } : {}
|
|
126597
|
+
});
|
|
126598
|
+
if (payload !== void 0 && result !== void 0) return new PayloadReply(void 0, packPayload(result));
|
|
126599
|
+
return result;
|
|
126600
|
+
}
|
|
126176
126601
|
if (msg.kind === "addon-call") {
|
|
126177
126602
|
if (this.addonCallHandler === null) throw new Error(`LocalChildClient: addon-call for "${msg.addonId}" arrived but no onAddonCall handler is registered`);
|
|
126178
126603
|
return this.addonCallHandler({
|
|
@@ -126196,7 +126621,7 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126196
126621
|
});
|
|
126197
126622
|
const register = this.registerFrame(this.latestCaps);
|
|
126198
126623
|
try {
|
|
126199
|
-
await channel.request(register);
|
|
126624
|
+
this.parentRawForward = ackAcceptsRawForward(await channel.request(register));
|
|
126200
126625
|
} catch (err) {
|
|
126201
126626
|
await client.close();
|
|
126202
126627
|
throw err;
|
|
@@ -126224,7 +126649,7 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126224
126649
|
this.latestCaps = caps;
|
|
126225
126650
|
if (customActions !== void 0) this.latestCustomActions = customActions;
|
|
126226
126651
|
if (this.channel === null) return;
|
|
126227
|
-
await this.channel.request(this.registerFrame(caps));
|
|
126652
|
+
this.parentRawForward = ackAcceptsRawForward(await this.channel.request(this.registerFrame(caps)));
|
|
126228
126653
|
}
|
|
126229
126654
|
/**
|
|
126230
126655
|
* The register frame: caps, plus everything a re-register must atomically
|
|
@@ -126238,7 +126663,8 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126238
126663
|
childId: this.options.childId,
|
|
126239
126664
|
caps,
|
|
126240
126665
|
...this.hasDeclaredEventPatterns ? { eventPatterns: this.latestEventPatterns } : {},
|
|
126241
|
-
...this.latestCustomActions !== null ? { customActions: this.latestCustomActions } : {}
|
|
126666
|
+
...this.latestCustomActions !== null ? { customActions: this.latestCustomActions } : {},
|
|
126667
|
+
rawForward: true
|
|
126242
126668
|
};
|
|
126243
126669
|
}
|
|
126244
126670
|
/**
|
|
@@ -126289,14 +126715,29 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126289
126715
|
*/
|
|
126290
126716
|
async callOut(input) {
|
|
126291
126717
|
if (this.channel === null) throw new Error("LocalChildClient: callOut before start");
|
|
126718
|
+
const routing = {
|
|
126719
|
+
...input.deviceId !== void 0 ? { deviceId: input.deviceId } : {},
|
|
126720
|
+
...input.nodeId !== void 0 ? { nodeId: input.nodeId } : {},
|
|
126721
|
+
...input.native === true ? { native: true } : {}
|
|
126722
|
+
};
|
|
126723
|
+
if (this.parentRawForward && input.args !== void 0) {
|
|
126724
|
+
const hints = liftRoutingHints(input.args);
|
|
126725
|
+
const msg2 = {
|
|
126726
|
+
kind: "cap-call-out",
|
|
126727
|
+
capName: input.capName,
|
|
126728
|
+
method: input.method,
|
|
126729
|
+
...Object.keys(hints).length > 0 ? { hints } : {},
|
|
126730
|
+
...routing
|
|
126731
|
+
};
|
|
126732
|
+
const reply = await this.channel.request(msg2, { payload: packPayload(input.args) });
|
|
126733
|
+
return reply instanceof PayloadReply ? unpackPayload(reply.payload) : reply;
|
|
126734
|
+
}
|
|
126292
126735
|
const msg = {
|
|
126293
126736
|
kind: "cap-call-out",
|
|
126294
126737
|
capName: input.capName,
|
|
126295
126738
|
method: input.method,
|
|
126296
126739
|
args: input.args,
|
|
126297
|
-
...
|
|
126298
|
-
...input.nodeId !== void 0 ? { nodeId: input.nodeId } : {},
|
|
126299
|
-
...input.native === true ? { native: true } : {}
|
|
126740
|
+
...routing
|
|
126300
126741
|
};
|
|
126301
126742
|
return this.channel.request(msg);
|
|
126302
126743
|
}
|
|
@@ -126307,6 +126748,397 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
126307
126748
|
this.channel = null;
|
|
126308
126749
|
}
|
|
126309
126750
|
};
|
|
126751
|
+
function buildMessage(capName, method, detail) {
|
|
126752
|
+
const call = method !== void 0 ? `${capName}.${method}` : capName;
|
|
126753
|
+
const target = detail.nodeId !== void 0 ? ` to node ${detail.nodeId}` : "";
|
|
126754
|
+
const rejectedStr = detail.rejected.map((r) => `${r.kind}=${r.why}`).join("; ");
|
|
126755
|
+
const rejectedClause = rejectedStr.length > 0 ? ` (rejected: ${rejectedStr})` : "";
|
|
126756
|
+
return `${call} not routable${target}: ${detail.reason}${rejectedClause}`;
|
|
126757
|
+
}
|
|
126758
|
+
var CapRouteError = class extends Error {
|
|
126759
|
+
reason;
|
|
126760
|
+
nodeId;
|
|
126761
|
+
rejected;
|
|
126762
|
+
/**
|
|
126763
|
+
* @param cause Optional original error that triggered this routing failure.
|
|
126764
|
+
* Stored as `Error.cause` (TC39 standard option, Node 16.9+).
|
|
126765
|
+
* Dispatchers wrapping transport errors MUST pass the original.
|
|
126766
|
+
*/
|
|
126767
|
+
constructor(capName, method, detail, cause) {
|
|
126768
|
+
super(buildMessage(capName, method, detail), cause !== void 0 ? { cause } : void 0);
|
|
126769
|
+
this.name = "CapRouteError";
|
|
126770
|
+
this.reason = detail.reason;
|
|
126771
|
+
this.nodeId = detail.nodeId;
|
|
126772
|
+
this.rejected = detail.rejected;
|
|
126773
|
+
}
|
|
126774
|
+
};
|
|
126775
|
+
function classifyCapRoute(capName, opts, snapshot) {
|
|
126776
|
+
const rejected = [];
|
|
126777
|
+
if (opts.nodeId !== void 0) return classifyExplicitNode(capName, opts.nodeId, opts.deviceId, snapshot, rejected);
|
|
126778
|
+
return classifySingleton(capName, opts.deviceId, snapshot, rejected);
|
|
126779
|
+
}
|
|
126780
|
+
function classifyExplicitNode(capName, nodeId, deviceId, snap, rejected) {
|
|
126781
|
+
if (nodeId === snap.hubNodeId) {
|
|
126782
|
+
const residentProvides = snap.hubResidentProvides;
|
|
126783
|
+
const providesOnHub = residentProvides ?? snap.hubInProcessProvides;
|
|
126784
|
+
const getRef = residentProvides !== void 0 ? snap.getHubResidentProviderRef : snap.getInProcessProviderRef;
|
|
126785
|
+
if (providesOnHub(capName)) {
|
|
126786
|
+
const ref = getRef?.(capName) ?? null;
|
|
126787
|
+
if (ref !== null) return {
|
|
126788
|
+
kind: "hub-in-process",
|
|
126789
|
+
capName,
|
|
126790
|
+
ref
|
|
126791
|
+
};
|
|
126792
|
+
rejected.push({
|
|
126793
|
+
kind: "hub-in-process",
|
|
126794
|
+
why: "provider ref not available in snapshot"
|
|
126795
|
+
});
|
|
126796
|
+
throw new CapRouteError(capName, void 0, {
|
|
126797
|
+
reason: "no-provider",
|
|
126798
|
+
nodeId,
|
|
126799
|
+
rejected
|
|
126800
|
+
});
|
|
126801
|
+
}
|
|
126802
|
+
if (snap.hubLocalChildProvides(capName, deviceId)) {
|
|
126803
|
+
const childId = snap.getHubLocalChildId?.(capName, deviceId) ?? null;
|
|
126804
|
+
if (childId !== null) return {
|
|
126805
|
+
kind: "hub-local-uds",
|
|
126806
|
+
capName,
|
|
126807
|
+
childId
|
|
126808
|
+
};
|
|
126809
|
+
rejected.push({
|
|
126810
|
+
kind: "hub-local-uds",
|
|
126811
|
+
why: "child id not resolvable from snapshot"
|
|
126812
|
+
});
|
|
126813
|
+
throw new CapRouteError(capName, void 0, {
|
|
126814
|
+
reason: "no-provider",
|
|
126815
|
+
nodeId,
|
|
126816
|
+
rejected
|
|
126817
|
+
});
|
|
126818
|
+
}
|
|
126819
|
+
rejected.push({
|
|
126820
|
+
kind: "hub-in-process",
|
|
126821
|
+
why: "hub does not provide this cap in-process"
|
|
126822
|
+
});
|
|
126823
|
+
rejected.push({
|
|
126824
|
+
kind: "hub-local-uds",
|
|
126825
|
+
why: "no hub-local child provides this cap"
|
|
126826
|
+
});
|
|
126827
|
+
throw new CapRouteError(capName, void 0, {
|
|
126828
|
+
reason: "no-provider",
|
|
126829
|
+
nodeId,
|
|
126830
|
+
rejected
|
|
126831
|
+
});
|
|
126832
|
+
}
|
|
126833
|
+
if (!snap.nodeOnline(nodeId)) {
|
|
126834
|
+
rejected.push({
|
|
126835
|
+
kind: "remote-moleculer",
|
|
126836
|
+
why: `node ${nodeId} is offline`
|
|
126837
|
+
});
|
|
126838
|
+
throw new CapRouteError(capName, void 0, {
|
|
126839
|
+
reason: "node-offline",
|
|
126840
|
+
nodeId,
|
|
126841
|
+
rejected
|
|
126842
|
+
});
|
|
126843
|
+
}
|
|
126844
|
+
if (snap.nodeIsAgent(nodeId)) {
|
|
126845
|
+
if (snap.nodeKnowsCap(nodeId, capName)) return {
|
|
126846
|
+
kind: "agent-child-forward",
|
|
126847
|
+
capName,
|
|
126848
|
+
agentNodeId: nodeId,
|
|
126849
|
+
childId: snap.getAgentChildId?.(nodeId, capName) ?? void 0
|
|
126850
|
+
};
|
|
126851
|
+
rejected.push({
|
|
126852
|
+
kind: "agent-child-forward",
|
|
126853
|
+
why: `agent ${nodeId} does not know cap ${capName}`
|
|
126854
|
+
});
|
|
126855
|
+
throw new CapRouteError(capName, void 0, {
|
|
126856
|
+
reason: "no-provider",
|
|
126857
|
+
nodeId,
|
|
126858
|
+
rejected
|
|
126859
|
+
});
|
|
126860
|
+
}
|
|
126861
|
+
return {
|
|
126862
|
+
kind: "remote-moleculer",
|
|
126863
|
+
capName,
|
|
126864
|
+
nodeId
|
|
126865
|
+
};
|
|
126866
|
+
}
|
|
126867
|
+
function classifySingleton(capName, deviceId, snap, rejected) {
|
|
126868
|
+
if (snap.hubInProcessProvides(capName)) {
|
|
126869
|
+
const ref = snap.getInProcessProviderRef?.(capName) ?? null;
|
|
126870
|
+
if (ref !== null) return {
|
|
126871
|
+
kind: "hub-in-process",
|
|
126872
|
+
capName,
|
|
126873
|
+
ref
|
|
126874
|
+
};
|
|
126875
|
+
rejected.push({
|
|
126876
|
+
kind: "hub-in-process",
|
|
126877
|
+
why: "provider ref not available in snapshot"
|
|
126878
|
+
});
|
|
126879
|
+
} else rejected.push({
|
|
126880
|
+
kind: "hub-in-process",
|
|
126881
|
+
why: "hub does not provide this cap in-process"
|
|
126882
|
+
});
|
|
126883
|
+
if (snap.hubLocalChildProvides(capName, deviceId)) {
|
|
126884
|
+
const childId = snap.getHubLocalChildId?.(capName, deviceId) ?? null;
|
|
126885
|
+
if (childId !== null) return {
|
|
126886
|
+
kind: "hub-local-uds",
|
|
126887
|
+
capName,
|
|
126888
|
+
childId
|
|
126889
|
+
};
|
|
126890
|
+
rejected.push({
|
|
126891
|
+
kind: "hub-local-uds",
|
|
126892
|
+
why: "child id not resolvable from snapshot"
|
|
126893
|
+
});
|
|
126894
|
+
} else rejected.push({
|
|
126895
|
+
kind: "hub-local-uds",
|
|
126896
|
+
why: "no hub-local child provides this cap"
|
|
126897
|
+
});
|
|
126898
|
+
const knownNodes = snap.listKnownNodeIds?.() ?? [];
|
|
126899
|
+
for (const nodeId of knownNodes) if (nodeId !== snap.hubNodeId && snap.nodeOnline(nodeId) && snap.nodeKnowsCap(nodeId, capName)) return {
|
|
126900
|
+
kind: "remote-moleculer",
|
|
126901
|
+
capName,
|
|
126902
|
+
nodeId
|
|
126903
|
+
};
|
|
126904
|
+
rejected.push({
|
|
126905
|
+
kind: "remote-moleculer",
|
|
126906
|
+
why: "no online remote node knows this cap"
|
|
126907
|
+
});
|
|
126908
|
+
throw new CapRouteError(capName, void 0, {
|
|
126909
|
+
reason: "no-provider",
|
|
126910
|
+
rejected
|
|
126911
|
+
});
|
|
126912
|
+
}
|
|
126913
|
+
var DISCOVERY_ERROR_TYPES = /* @__PURE__ */ new Set(["SERVICE_NOT_FOUND", "SERVICE_NOT_AVAILABLE"]);
|
|
126914
|
+
var DEFAULT_DISCOVERY_TIMEOUT_MS$1 = 3e4;
|
|
126915
|
+
function isDiscoveryError(err) {
|
|
126916
|
+
if (typeof err !== "object" || err === null) return false;
|
|
126917
|
+
const type = err.type;
|
|
126918
|
+
return typeof type === "string" && DISCOVERY_ERROR_TYPES.has(type);
|
|
126919
|
+
}
|
|
126920
|
+
async function callWithServiceDiscovery(broker, serviceName, action, params, opts, discoveryTimeoutMs = DEFAULT_DISCOVERY_TIMEOUT_MS$1) {
|
|
126921
|
+
try {
|
|
126922
|
+
return await broker.call(action, params, opts);
|
|
126923
|
+
} catch (err) {
|
|
126924
|
+
if (!isDiscoveryError(err)) throw err;
|
|
126925
|
+
await broker.waitForServices([serviceName], discoveryTimeoutMs);
|
|
126926
|
+
return await broker.call(action, params, opts);
|
|
126927
|
+
}
|
|
126928
|
+
}
|
|
126929
|
+
var AGENT_CAP_FWD_SERVICE = "$agent-cap-fwd";
|
|
126930
|
+
var AGENT_CAP_FWD_ACTION = `${AGENT_CAP_FWD_SERVICE}.forward`;
|
|
126931
|
+
var REMOTE_CALL_TIMEOUT_MS = 6e4;
|
|
126932
|
+
function extractDeviceId(args) {
|
|
126933
|
+
if (args === null || typeof args !== "object") return void 0;
|
|
126934
|
+
const raw = Reflect.get(args, "deviceId");
|
|
126935
|
+
return typeof raw === "number" ? raw : void 0;
|
|
126936
|
+
}
|
|
126937
|
+
function extractNodeId(args) {
|
|
126938
|
+
if (args === null || typeof args !== "object") return void 0;
|
|
126939
|
+
const raw = Reflect.get(args, "nodeId");
|
|
126940
|
+
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
126941
|
+
}
|
|
126942
|
+
function withCallerAddonId(args, callerAddonId) {
|
|
126943
|
+
if (callerAddonId === void 0) return args;
|
|
126944
|
+
if (args === null || typeof args !== "object" || Array.isArray(args)) return args;
|
|
126945
|
+
return {
|
|
126946
|
+
...args,
|
|
126947
|
+
callerAddonId
|
|
126948
|
+
};
|
|
126949
|
+
}
|
|
126950
|
+
var CapRouteResolver = class {
|
|
126951
|
+
hubNodeId;
|
|
126952
|
+
broker;
|
|
126953
|
+
hubLocalRegistry;
|
|
126954
|
+
nodeAuthority;
|
|
126955
|
+
inProcessProviders;
|
|
126956
|
+
hubResidentProviders;
|
|
126957
|
+
capTimeoutMs;
|
|
126958
|
+
snapshot;
|
|
126959
|
+
constructor(deps) {
|
|
126960
|
+
this.hubNodeId = deps.hubNodeId;
|
|
126961
|
+
this.broker = deps.broker;
|
|
126962
|
+
this.hubLocalRegistry = deps.hubLocalRegistry;
|
|
126963
|
+
this.nodeAuthority = deps.nodeAuthority;
|
|
126964
|
+
this.inProcessProviders = deps.inProcessProviders;
|
|
126965
|
+
this.hubResidentProviders = deps.hubResidentProviders;
|
|
126966
|
+
this.capTimeoutMs = deps.capTimeoutMs;
|
|
126967
|
+
this.snapshot = this.buildSnapshot();
|
|
126968
|
+
}
|
|
126969
|
+
/** Per-call RPC timeout: the cap method's declared override, else the default. */
|
|
126970
|
+
callTimeout(capName, method) {
|
|
126971
|
+
return this.capTimeoutMs?.(capName, method) ?? REMOTE_CALL_TIMEOUT_MS;
|
|
126972
|
+
}
|
|
126973
|
+
resolveCapRoute(capName, opts) {
|
|
126974
|
+
return classifyCapRoute(capName, opts, this.snapshot);
|
|
126975
|
+
}
|
|
126976
|
+
/**
|
|
126977
|
+
* Resolve the hub-local-uds route for a cap owned by a forked hub-local
|
|
126978
|
+
* child, IGNORING any in-hub provider registered for the same cap name.
|
|
126979
|
+
*
|
|
126980
|
+
* `resolveCapRoute` gives Priority 1 to `hub-in-process`: when an in-hub
|
|
126981
|
+
* provider (e.g. a wrapper) is registered for the cap, the route always
|
|
126982
|
+
* classifies as `hub-in-process` and the hub-local-uds NATIVE child is never
|
|
126983
|
+
* reached. That is correct for the generic dispatch path (the wrapper is the
|
|
126984
|
+
* active provider), but WRONG for the native-cap fallback
|
|
126985
|
+
* (`setNativeFallback`), whose contract is to reach the NATIVE provider in
|
|
126986
|
+
* the forked vendor child so a wrapper can delegate to it. A wrapper cap
|
|
126987
|
+
* with a forked native (today: `snapshot`) otherwise resolves to the wrapper
|
|
126988
|
+
* itself, the native is never invoked, and the wrapper silently falls
|
|
126989
|
+
* through to its secondary strategy.
|
|
126990
|
+
*
|
|
126991
|
+
* This method consults ONLY the hub-local-child authority
|
|
126992
|
+
* (`hubLocalChildProvides` + `getHubLocalChildId`, both deviceId-aware), so
|
|
126993
|
+
* it returns the native child route regardless of any in-process shadow.
|
|
126994
|
+
* Returns null when no hub-local child owns `(capName, deviceId)` — the
|
|
126995
|
+
* caller then falls through to its remote-resolution branch.
|
|
126996
|
+
*/
|
|
126997
|
+
resolveHubLocalUdsRoute(capName, deviceId) {
|
|
126998
|
+
if (!this.snapshot.hubLocalChildProvides(capName, deviceId)) return null;
|
|
126999
|
+
const childId = this.snapshot.getHubLocalChildId?.(capName, deviceId) ?? null;
|
|
127000
|
+
if (childId === null) return null;
|
|
127001
|
+
return {
|
|
127002
|
+
kind: "hub-local-uds",
|
|
127003
|
+
capName,
|
|
127004
|
+
childId
|
|
127005
|
+
};
|
|
127006
|
+
}
|
|
127007
|
+
/**
|
|
127008
|
+
* @param addonId Optional out-of-band PROVIDER-selection hint (Task 7.5a):
|
|
127009
|
+
* the addonId of the provider the CALLER already resolved (e.g.
|
|
127010
|
+
* `buildCapCallFn`'s `deps.addonId` for a registered grouped-runner
|
|
127011
|
+
* provider). Only meaningful for `agent-child-forward` — a `remote-moleculer`
|
|
127012
|
+
* route already encodes the provider in its action name
|
|
127013
|
+
* (`${addonId}.${cap}.${method}`, via `NodeCapAuthority.getAddonId`), and a
|
|
127014
|
+
* `hub-local-uds` caller that already knows the addonId (`buildCapCallFn`)
|
|
127015
|
+
* talks to `LocalChildRegistry.callCapOnChild` directly rather than through
|
|
127016
|
+
* `dispatch`.
|
|
127017
|
+
* @param callerAddonId Optional out-of-band CALLER-identity hint — the
|
|
127018
|
+
* addon that ORIGINATED the call, distinct from `addonId` above (which
|
|
127019
|
+
* names the resolved PROVIDER, not the caller). Set by
|
|
127020
|
+
* `onUnownedCall` from `CapCallInput.callerAddonId`
|
|
127021
|
+
* (`LocalChildRegistry` stamped it off the registered `childId`). Only
|
|
127022
|
+
* the `hub-in-process` branch consumes it — merged into `args` so a
|
|
127023
|
+
* diagnostic tool deep in that provider (e.g. device-manager's
|
|
127024
|
+
* fleet-read census) can read it without every provider method changing
|
|
127025
|
+
* signature, the same "extra field the provider destructures or
|
|
127026
|
+
* ignores" convention `nodeId` already uses on this path.
|
|
127027
|
+
*/
|
|
127028
|
+
async dispatch(route, method, args, addonId, callerAddonId) {
|
|
127029
|
+
try {
|
|
127030
|
+
return await this.dispatchInner(route, method, args, addonId, callerAddonId);
|
|
127031
|
+
} catch (err) {
|
|
127032
|
+
if (err instanceof CapRouteError) throw err;
|
|
127033
|
+
const nodeId = this.routeNodeId(route);
|
|
127034
|
+
const cause = err instanceof Error ? err : new Error(String(err));
|
|
127035
|
+
throw new CapRouteError(route.capName, method, {
|
|
127036
|
+
reason: "transport-failed",
|
|
127037
|
+
nodeId,
|
|
127038
|
+
rejected: [{
|
|
127039
|
+
kind: route.kind,
|
|
127040
|
+
why: cause.message
|
|
127041
|
+
}]
|
|
127042
|
+
}, cause);
|
|
127043
|
+
}
|
|
127044
|
+
}
|
|
127045
|
+
/**
|
|
127046
|
+
* Inner dispatch: may throw CapRouteError (validation failures) or arbitrary
|
|
127047
|
+
* transport errors. The outer `dispatch` wraps non-CapRouteErrors.
|
|
127048
|
+
*/
|
|
127049
|
+
async dispatchInner(route, method, args, addonId, callerAddonId) {
|
|
127050
|
+
switch (route.kind) {
|
|
127051
|
+
case "hub-in-process":
|
|
127052
|
+
return route.ref.invoke(method, withCallerAddonId(args, callerAddonId));
|
|
127053
|
+
case "hub-local-uds": {
|
|
127054
|
+
const registry = this.hubLocalRegistry;
|
|
127055
|
+
if (registry === null) throw new CapRouteError(route.capName, method, {
|
|
127056
|
+
reason: "no-provider",
|
|
127057
|
+
rejected: [{
|
|
127058
|
+
kind: "hub-local-uds",
|
|
127059
|
+
why: "UDS registry not available"
|
|
127060
|
+
}]
|
|
127061
|
+
});
|
|
127062
|
+
const deviceId = extractDeviceId(args);
|
|
127063
|
+
const input = {
|
|
127064
|
+
capName: route.capName,
|
|
127065
|
+
method,
|
|
127066
|
+
args,
|
|
127067
|
+
...deviceId !== void 0 ? { deviceId } : {}
|
|
127068
|
+
};
|
|
127069
|
+
return registry.callCapOnChild(route.childId, input);
|
|
127070
|
+
}
|
|
127071
|
+
case "remote-moleculer": {
|
|
127072
|
+
const addonId2 = this.nodeAuthority.getAddonId(route.nodeId, route.capName);
|
|
127073
|
+
if (addonId2 === null) throw new CapRouteError(route.capName, method, {
|
|
127074
|
+
reason: "no-provider",
|
|
127075
|
+
nodeId: route.nodeId,
|
|
127076
|
+
rejected: [{
|
|
127077
|
+
kind: "remote-moleculer",
|
|
127078
|
+
why: `no addonId known for ${route.nodeId}/${route.capName}`
|
|
127079
|
+
}]
|
|
127080
|
+
});
|
|
127081
|
+
const deviceId = extractDeviceId(args);
|
|
127082
|
+
const isNative = this.nodeAuthority.isNativeCap(route.nodeId, route.capName, deviceId);
|
|
127083
|
+
const action = capActionName(addonId2, route.capName, method, isNative);
|
|
127084
|
+
return callWithServiceDiscovery(this.broker, addonId2, action, args, {
|
|
127085
|
+
nodeID: route.nodeId,
|
|
127086
|
+
timeout: this.callTimeout(route.capName, method)
|
|
127087
|
+
});
|
|
127088
|
+
}
|
|
127089
|
+
case "agent-child-forward": {
|
|
127090
|
+
const deviceId = extractDeviceId(args);
|
|
127091
|
+
const params = {
|
|
127092
|
+
capName: route.capName,
|
|
127093
|
+
method,
|
|
127094
|
+
args,
|
|
127095
|
+
...route.childId !== void 0 ? { childId: route.childId } : {},
|
|
127096
|
+
...deviceId !== void 0 ? { deviceId } : {},
|
|
127097
|
+
...addonId !== void 0 ? { addonId } : {}
|
|
127098
|
+
};
|
|
127099
|
+
return callWithServiceDiscovery(this.broker, AGENT_CAP_FWD_SERVICE, AGENT_CAP_FWD_ACTION, params, {
|
|
127100
|
+
nodeID: route.agentNodeId,
|
|
127101
|
+
timeout: this.callTimeout(route.capName, method)
|
|
127102
|
+
});
|
|
127103
|
+
}
|
|
127104
|
+
}
|
|
127105
|
+
}
|
|
127106
|
+
buildSnapshot() {
|
|
127107
|
+
const hubLocalRegistry = this.hubLocalRegistry;
|
|
127108
|
+
const nodeAuthority = this.nodeAuthority;
|
|
127109
|
+
const inProcessProviders = this.inProcessProviders;
|
|
127110
|
+
const hubResidentProviders = this.hubResidentProviders;
|
|
127111
|
+
return {
|
|
127112
|
+
hubNodeId: this.hubNodeId,
|
|
127113
|
+
hubInProcessProvides: (cap) => inProcessProviders(cap) !== null,
|
|
127114
|
+
...hubResidentProviders !== void 0 ? {
|
|
127115
|
+
hubResidentProvides: (cap) => hubResidentProviders(cap) !== null,
|
|
127116
|
+
getHubResidentProviderRef: (cap) => hubResidentProviders(cap)
|
|
127117
|
+
} : {},
|
|
127118
|
+
hubLocalChildProvides: (cap, deviceId) => hubLocalRegistry !== null && hubLocalRegistry.resolveChildId(cap, deviceId) !== null,
|
|
127119
|
+
nodeKnowsCap: (nodeId, cap) => nodeAuthority.nodeKnowsCap(nodeId, cap),
|
|
127120
|
+
nodeIsAgent: (nodeId) => nodeAuthority.nodeIsAgent(nodeId),
|
|
127121
|
+
nodeOnline: (nodeId) => nodeAuthority.nodeOnline(nodeId),
|
|
127122
|
+
listKnownNodeIds: () => nodeAuthority.listNodeIds(),
|
|
127123
|
+
getInProcessProviderRef: (cap) => inProcessProviders(cap),
|
|
127124
|
+
getHubLocalChildId: (cap, deviceId) => hubLocalRegistry !== null ? hubLocalRegistry.resolveChildId(cap, deviceId) : null,
|
|
127125
|
+
getAgentChildId: (agentNodeId, cap) => nodeAuthority.getAgentChildId(agentNodeId, cap)
|
|
127126
|
+
};
|
|
127127
|
+
}
|
|
127128
|
+
/** Extract a nodeId string from a route for error reporting, or undefined. */
|
|
127129
|
+
routeNodeId(route) {
|
|
127130
|
+
switch (route.kind) {
|
|
127131
|
+
case "hub-in-process":
|
|
127132
|
+
return this.hubNodeId;
|
|
127133
|
+
case "hub-local-uds":
|
|
127134
|
+
return `${this.hubNodeId}/${route.childId}`;
|
|
127135
|
+
case "remote-moleculer":
|
|
127136
|
+
return route.nodeId;
|
|
127137
|
+
case "agent-child-forward":
|
|
127138
|
+
return route.agentNodeId;
|
|
127139
|
+
}
|
|
127140
|
+
}
|
|
127141
|
+
};
|
|
126310
127142
|
var LEVEL_ORDER = {
|
|
126311
127143
|
debug: 0,
|
|
126312
127144
|
info: 1,
|
|
@@ -128380,12 +129212,36 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
128380
129212
|
return LocalChildRegistry;
|
|
128381
129213
|
}
|
|
128382
129214
|
});
|
|
129215
|
+
Object.defineProperty(exports, "MESH_QUEUE_TOP_N", {
|
|
129216
|
+
enumerable: true,
|
|
129217
|
+
get: function() {
|
|
129218
|
+
return MESH_QUEUE_TOP_N;
|
|
129219
|
+
}
|
|
129220
|
+
});
|
|
128383
129221
|
Object.defineProperty(exports, "NATIVE_PROVIDER_SERVICE_INFIX", {
|
|
128384
129222
|
enumerable: true,
|
|
128385
129223
|
get: function() {
|
|
128386
129224
|
return NATIVE_PROVIDER_SERVICE_INFIX;
|
|
128387
129225
|
}
|
|
128388
129226
|
});
|
|
129227
|
+
Object.defineProperty(exports, "OUTBOUND_QUEUE_COOLDOWN_MS", {
|
|
129228
|
+
enumerable: true,
|
|
129229
|
+
get: function() {
|
|
129230
|
+
return OUTBOUND_QUEUE_COOLDOWN_MS;
|
|
129231
|
+
}
|
|
129232
|
+
});
|
|
129233
|
+
Object.defineProperty(exports, "OUTBOUND_QUEUE_SUSTAIN_MS", {
|
|
129234
|
+
enumerable: true,
|
|
129235
|
+
get: function() {
|
|
129236
|
+
return OUTBOUND_QUEUE_SUSTAIN_MS;
|
|
129237
|
+
}
|
|
129238
|
+
});
|
|
129239
|
+
Object.defineProperty(exports, "OUTBOUND_QUEUE_THRESHOLD_BYTES", {
|
|
129240
|
+
enumerable: true,
|
|
129241
|
+
get: function() {
|
|
129242
|
+
return OUTBOUND_QUEUE_THRESHOLD_BYTES;
|
|
129243
|
+
}
|
|
129244
|
+
});
|
|
128389
129245
|
Object.defineProperty(exports, "PARENT_ROUTED_PROVIDER_ADDON_ID", {
|
|
128390
129246
|
enumerable: true,
|
|
128391
129247
|
get: function() {
|
|
@@ -128422,6 +129278,12 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
128422
129278
|
return SOCKET_PLANE_TOP_N;
|
|
128423
129279
|
}
|
|
128424
129280
|
});
|
|
129281
|
+
Object.defineProperty(exports, "SOCKET_QUEUE_TOP_N", {
|
|
129282
|
+
enumerable: true,
|
|
129283
|
+
get: function() {
|
|
129284
|
+
return SOCKET_QUEUE_TOP_N;
|
|
129285
|
+
}
|
|
129286
|
+
});
|
|
128425
129287
|
Object.defineProperty(exports, "SocketChannel", {
|
|
128426
129288
|
enumerable: true,
|
|
128427
129289
|
get: function() {
|
|
@@ -128620,6 +129482,18 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
128620
129482
|
return createLoopDelayMeter;
|
|
128621
129483
|
}
|
|
128622
129484
|
});
|
|
129485
|
+
Object.defineProperty(exports, "createMeshQueueReader", {
|
|
129486
|
+
enumerable: true,
|
|
129487
|
+
get: function() {
|
|
129488
|
+
return createMeshQueueReader;
|
|
129489
|
+
}
|
|
129490
|
+
});
|
|
129491
|
+
Object.defineProperty(exports, "createOutboundQueueGate", {
|
|
129492
|
+
enumerable: true,
|
|
129493
|
+
get: function() {
|
|
129494
|
+
return createOutboundQueueGate;
|
|
129495
|
+
}
|
|
129496
|
+
});
|
|
128623
129497
|
Object.defineProperty(exports, "createParentUnownedCallHandler", {
|
|
128624
129498
|
enumerable: true,
|
|
128625
129499
|
get: function() {
|
|
@@ -128734,6 +129608,18 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
128734
129608
|
return formatHeapSpaces;
|
|
128735
129609
|
}
|
|
128736
129610
|
});
|
|
129611
|
+
Object.defineProperty(exports, "formatMeshQueue", {
|
|
129612
|
+
enumerable: true,
|
|
129613
|
+
get: function() {
|
|
129614
|
+
return formatMeshQueue;
|
|
129615
|
+
}
|
|
129616
|
+
});
|
|
129617
|
+
Object.defineProperty(exports, "formatOutboundQueueVerdict", {
|
|
129618
|
+
enumerable: true,
|
|
129619
|
+
get: function() {
|
|
129620
|
+
return formatOutboundQueueVerdict;
|
|
129621
|
+
}
|
|
129622
|
+
});
|
|
128737
129623
|
Object.defineProperty(exports, "formatSocketPlane", {
|
|
128738
129624
|
enumerable: true,
|
|
128739
129625
|
get: function() {
|
|
@@ -128878,6 +129764,12 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
128878
129764
|
return readMoleculerFanoutMode;
|
|
128879
129765
|
}
|
|
128880
129766
|
});
|
|
129767
|
+
Object.defineProperty(exports, "readSocketQueues", {
|
|
129768
|
+
enumerable: true,
|
|
129769
|
+
get: function() {
|
|
129770
|
+
return readSocketQueues;
|
|
129771
|
+
}
|
|
129772
|
+
});
|
|
128881
129773
|
Object.defineProperty(exports, "reclaimIntervalMs", {
|
|
128882
129774
|
enumerable: true,
|
|
128883
129775
|
get: function() {
|
|
@@ -129013,11 +129905,11 @@ var require_manifest_system_deps_Bo92lg5u = __commonJS({
|
|
|
129013
129905
|
}
|
|
129014
129906
|
});
|
|
129015
129907
|
|
|
129016
|
-
// ../system/dist/custom-action-registry-
|
|
129017
|
-
var
|
|
129018
|
-
"../system/dist/custom-action-registry-
|
|
129908
|
+
// ../system/dist/custom-action-registry-DKWhaWL1.js
|
|
129909
|
+
var require_custom_action_registry_DKWhaWL1 = __commonJS({
|
|
129910
|
+
"../system/dist/custom-action-registry-DKWhaWL1.js"(exports) {
|
|
129019
129911
|
"use strict";
|
|
129020
|
-
var require_dist10 =
|
|
129912
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
129021
129913
|
var CustomActionRegistry = class {
|
|
129022
129914
|
byAddon = /* @__PURE__ */ new Map();
|
|
129023
129915
|
registerAddon(addonId, catalog, handler) {
|
|
@@ -132831,7 +133723,7 @@ var require_dist3 = __commonJS({
|
|
|
132831
133723
|
"use strict";
|
|
132832
133724
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
132833
133725
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
132834
|
-
var require_dist10 =
|
|
133726
|
+
var require_dist10 = require_dist_B17W9ngu();
|
|
132835
133727
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
132836
133728
|
require_alerts();
|
|
132837
133729
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -132856,25 +133748,25 @@ var require_dist3 = __commonJS({
|
|
|
132856
133748
|
var require_builtins_system_config_system_config_addon = require_system_config_addon();
|
|
132857
133749
|
require_system_config();
|
|
132858
133750
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
132859
|
-
var require_event_loop_stall_monitor =
|
|
132860
|
-
var require_tls$1 =
|
|
132861
|
-
var require_manifest_system_deps =
|
|
132862
|
-
var require_resource_monitor =
|
|
132863
|
-
var require_custom_action_registry =
|
|
133751
|
+
var require_event_loop_stall_monitor = require_event_loop_stall_monitor_CAsHdMwP();
|
|
133752
|
+
var require_tls$1 = require_tls_BFs4PzoW();
|
|
133753
|
+
var require_manifest_system_deps = require_manifest_system_deps_g_nK0xsF();
|
|
133754
|
+
var require_resource_monitor = require_resource_monitor_LVE1BoLs();
|
|
133755
|
+
var require_custom_action_registry = require_custom_action_registry_DKWhaWL1();
|
|
132864
133756
|
var zod = require_zod();
|
|
132865
133757
|
var node_crypto = __require("crypto");
|
|
132866
133758
|
var _camstack_types_node = require_node();
|
|
132867
133759
|
var node_fs_promises = __require("fs/promises");
|
|
132868
133760
|
var node_path = __require("path");
|
|
132869
133761
|
node_path = require_chunk.__toESM(node_path, 1);
|
|
132870
|
-
var node_child_process = __require("child_process");
|
|
132871
|
-
var node_util = __require("util");
|
|
132872
|
-
node_util = require_chunk.__toESM(node_util);
|
|
132873
133762
|
var node_fs = __require("fs");
|
|
132874
133763
|
var node_fs$1 = require_chunk.__toESM(node_fs, 1);
|
|
132875
133764
|
node_fs = require_chunk.__toESM(node_fs);
|
|
133765
|
+
var node_child_process = __require("child_process");
|
|
132876
133766
|
var node_os = __require("os");
|
|
132877
133767
|
node_os = require_chunk.__toESM(node_os);
|
|
133768
|
+
var node_util = __require("util");
|
|
133769
|
+
node_util = require_chunk.__toESM(node_util);
|
|
132878
133770
|
var node_http = __require("http");
|
|
132879
133771
|
var node_vm = __require("vm");
|
|
132880
133772
|
node_vm = require_chunk.__toESM(node_vm);
|
|
@@ -212614,33 +213506,13 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
212614
213506
|
}
|
|
212615
213507
|
}
|
|
212616
213508
|
async function getPidStats$1(pids) {
|
|
212617
|
-
|
|
212618
|
-
|
|
212619
|
-
|
|
212620
|
-
|
|
212621
|
-
|
|
212622
|
-
"-p",
|
|
212623
|
-
pids.join(",")
|
|
212624
|
-
], { timeout: 5e3 }, (err, stdout) => {
|
|
212625
|
-
const result = /* @__PURE__ */ new Map();
|
|
212626
|
-
if (err || !stdout) {
|
|
212627
|
-
resolve(result);
|
|
212628
|
-
return;
|
|
212629
|
-
}
|
|
212630
|
-
for (const line of stdout.trim().split("\n")) {
|
|
212631
|
-
const parts = line.trim().split(/\s+/);
|
|
212632
|
-
if (parts.length < 3) continue;
|
|
212633
|
-
const pid = parseInt(parts[0], 10);
|
|
212634
|
-
const cpu = parseFloat(parts[1]);
|
|
212635
|
-
const rssKb = parseInt(parts[2], 10);
|
|
212636
|
-
if (!isNaN(pid) && !isNaN(cpu) && !isNaN(rssKb)) result.set(pid, {
|
|
212637
|
-
cpu: Math.round(cpu * 10) / 10,
|
|
212638
|
-
memoryRss: rssKb * 1024
|
|
212639
|
-
});
|
|
212640
|
-
}
|
|
212641
|
-
resolve(result);
|
|
212642
|
-
});
|
|
213509
|
+
const stats = await require_resource_monitor.getPidStats(pids);
|
|
213510
|
+
const result = /* @__PURE__ */ new Map();
|
|
213511
|
+
for (const [pid, s] of stats) result.set(pid, {
|
|
213512
|
+
cpu: s.cpu,
|
|
213513
|
+
memoryRss: s.memory
|
|
212643
213514
|
});
|
|
213515
|
+
return result;
|
|
212644
213516
|
}
|
|
212645
213517
|
var EMPTY_HEAP_DECLARATION = {
|
|
212646
213518
|
profile: void 0,
|
|
@@ -213629,6 +214501,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
213629
214501
|
exports.LokiDestination = require_builtins_loki_logging_index.LokiDestination$1;
|
|
213630
214502
|
exports.LokiLoggingAddon = require_builtins_loki_logging_index.LokiLoggingAddon$1;
|
|
213631
214503
|
exports.MAX_LEAF_VALIDITY_DAYS = require_tls$1.MAX_LEAF_VALIDITY_DAYS;
|
|
214504
|
+
exports.MESH_QUEUE_TOP_N = require_manifest_system_deps.MESH_QUEUE_TOP_N;
|
|
213632
214505
|
exports.METHOD_ACCESS_MAP = require_dist10.METHOD_ACCESS_MAP;
|
|
213633
214506
|
exports.ModelDownloadService = require_event_loop_stall_monitor.ModelDownloadService;
|
|
213634
214507
|
exports.NATIVE_PROVIDER_SERVICE_INFIX = require_manifest_system_deps.NATIVE_PROVIDER_SERVICE_INFIX;
|
|
@@ -213637,6 +214510,9 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
213637
214510
|
exports.NativeMetricsProvider = require_builtins_native_metrics_native_metrics_addon.NativeMetricsProvider;
|
|
213638
214511
|
exports.NetworkQualityTracker = NetworkQualityTracker;
|
|
213639
214512
|
exports.NotificationService = NotificationService;
|
|
214513
|
+
exports.OUTBOUND_QUEUE_COOLDOWN_MS = require_manifest_system_deps.OUTBOUND_QUEUE_COOLDOWN_MS;
|
|
214514
|
+
exports.OUTBOUND_QUEUE_SUSTAIN_MS = require_manifest_system_deps.OUTBOUND_QUEUE_SUSTAIN_MS;
|
|
214515
|
+
exports.OUTBOUND_QUEUE_THRESHOLD_BYTES = require_manifest_system_deps.OUTBOUND_QUEUE_THRESHOLD_BYTES;
|
|
213640
214516
|
exports.PARENT_ROUTED_PROVIDER_ADDON_ID = require_manifest_system_deps.PARENT_ROUTED_PROVIDER_ADDON_ID;
|
|
213641
214517
|
Object.defineProperty(exports, "PYTHON_VERSION", {
|
|
213642
214518
|
enumerable: true,
|
|
@@ -213660,6 +214536,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
213660
214536
|
exports.RingBuffer = RingBuffer;
|
|
213661
214537
|
exports.SERVER_AUTH_OID = require_tls$1.SERVER_AUTH_OID;
|
|
213662
214538
|
exports.SOCKET_PLANE_TOP_N = require_manifest_system_deps.SOCKET_PLANE_TOP_N;
|
|
214539
|
+
exports.SOCKET_QUEUE_TOP_N = require_manifest_system_deps.SOCKET_QUEUE_TOP_N;
|
|
213663
214540
|
exports.STALL_REPORT_MS = require_event_loop_stall_monitor.STALL_REPORT_MS;
|
|
213664
214541
|
exports.STALL_TICK_MS = require_event_loop_stall_monitor.STALL_TICK_MS;
|
|
213665
214542
|
exports.ScopedLogger = ScopedLogger;
|
|
@@ -213745,6 +214622,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
213745
214622
|
exports.createKernelHwAccel = require_manifest_system_deps.createKernelHwAccel;
|
|
213746
214623
|
exports.createLocalTransport = require_manifest_system_deps.createLocalTransport;
|
|
213747
214624
|
exports.createLoopDelayMeter = require_manifest_system_deps.createLoopDelayMeter;
|
|
214625
|
+
exports.createMeshQueueReader = require_manifest_system_deps.createMeshQueueReader;
|
|
214626
|
+
exports.createOutboundQueueGate = require_manifest_system_deps.createOutboundQueueGate;
|
|
213748
214627
|
exports.createParentUnownedCallHandler = require_manifest_system_deps.createParentUnownedCallHandler;
|
|
213749
214628
|
exports.createProcessService = createProcessService;
|
|
213750
214629
|
exports.createReadinessService = createReadinessService;
|
|
@@ -213815,6 +214694,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
213815
214694
|
exports.formatEventPlane = require_manifest_system_deps.formatEventPlane;
|
|
213816
214695
|
exports.formatHeapSpaces = require_manifest_system_deps.formatHeapSpaces;
|
|
213817
214696
|
exports.formatLogLine = require_formatter.formatLogLine;
|
|
214697
|
+
exports.formatMeshQueue = require_manifest_system_deps.formatMeshQueue;
|
|
214698
|
+
exports.formatOutboundQueueVerdict = require_manifest_system_deps.formatOutboundQueueVerdict;
|
|
213818
214699
|
exports.formatSocketPlane = require_manifest_system_deps.formatSocketPlane;
|
|
213819
214700
|
exports.getBrokerEventBus = require_manifest_system_deps.getBrokerEventBus;
|
|
213820
214701
|
exports.getCapUsageRegistry = require_manifest_system_deps.getCapUsageRegistry;
|
|
@@ -213892,6 +214773,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
213892
214773
|
exports.readLanHttpState = require_tls$1.readLanHttpState;
|
|
213893
214774
|
exports.readMoleculerFanoutMode = require_manifest_system_deps.readMoleculerFanoutMode;
|
|
213894
214775
|
exports.readPendingRestart = readPendingRestart;
|
|
214776
|
+
exports.readSocketQueues = require_manifest_system_deps.readSocketQueues;
|
|
213895
214777
|
exports.readTlsAccessStatus = require_tls$1.readTlsAccessStatus;
|
|
213896
214778
|
exports.readTlsMode = require_tls$1.readTlsMode;
|
|
213897
214779
|
exports.readinessKey = require_dist10.readinessKey;
|
|
@@ -235898,8 +236780,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
235898
236780
|
*
|
|
235899
236781
|
* An **empty array reads NOTHING** — `[]` is an empty page, never
|
|
235900
236782
|
* "every camera". A request for no devices is a request, not an
|
|
235901
|
-
* omission; same contract as `deviceManager.
|
|
235902
|
-
* `pipelineAnalytics.listRecentTracks`.
|
|
236783
|
+
* omission; same contract as `deviceManager.listAll`'s `deviceIds`
|
|
236784
|
+
* and `pipelineAnalytics.listRecentTracks`.
|
|
235903
236785
|
*
|
|
235904
236786
|
* Absent (`undefined`) is the omission, and keeps the cluster-wide view.
|
|
235905
236787
|
*/
|
|
@@ -416020,6 +416902,355 @@ var require_auth_whoami = __commonJS({
|
|
|
416020
416902
|
}
|
|
416021
416903
|
});
|
|
416022
416904
|
|
|
416905
|
+
// ../../server/backend/dist/api/backup-download-pump.js
|
|
416906
|
+
var require_backup_download_pump = __commonJS({
|
|
416907
|
+
"../../server/backend/dist/api/backup-download-pump.js"(exports) {
|
|
416908
|
+
"use strict";
|
|
416909
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
416910
|
+
exports.BACKUP_DOWNLOAD_DRAIN_GRACE_MS = exports.BACKUP_DOWNLOAD_CHUNK_BYTES = void 0;
|
|
416911
|
+
exports.pumpDownload = pumpDownload;
|
|
416912
|
+
exports.BACKUP_DOWNLOAD_CHUNK_BYTES = 8 * 1024 * 1024;
|
|
416913
|
+
exports.BACKUP_DOWNLOAD_DRAIN_GRACE_MS = 6e4;
|
|
416914
|
+
function waitForDrain(sink, graceMs) {
|
|
416915
|
+
return new Promise((resolve) => {
|
|
416916
|
+
const settle = (outcome) => {
|
|
416917
|
+
sink.off("drain", onDrain);
|
|
416918
|
+
sink.off("close", onClose);
|
|
416919
|
+
clearTimeout(timer);
|
|
416920
|
+
resolve(outcome);
|
|
416921
|
+
};
|
|
416922
|
+
const onDrain = () => settle("drained");
|
|
416923
|
+
const onClose = () => settle("closed");
|
|
416924
|
+
const timer = setTimeout(() => settle("timeout"), graceMs);
|
|
416925
|
+
sink.on("drain", onDrain);
|
|
416926
|
+
sink.on("close", onClose);
|
|
416927
|
+
});
|
|
416928
|
+
}
|
|
416929
|
+
function errorOf(err) {
|
|
416930
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
416931
|
+
}
|
|
416932
|
+
async function pumpDownload(options) {
|
|
416933
|
+
const { sizeBytes, read, sink } = options;
|
|
416934
|
+
const chunkBytes = options.chunkBytes ?? exports.BACKUP_DOWNLOAD_CHUNK_BYTES;
|
|
416935
|
+
const graceMs = options.graceMs ?? exports.BACKUP_DOWNLOAD_DRAIN_GRACE_MS;
|
|
416936
|
+
const now = options.now ?? (() => Date.now());
|
|
416937
|
+
const startedAt = now();
|
|
416938
|
+
let offset = 0;
|
|
416939
|
+
let drainWaits = 0;
|
|
416940
|
+
let drainWaitMaxMs = 0;
|
|
416941
|
+
const counters = () => ({
|
|
416942
|
+
bytesWritten: offset,
|
|
416943
|
+
drainWaits,
|
|
416944
|
+
drainWaitMaxMs,
|
|
416945
|
+
durationMs: now() - startedAt
|
|
416946
|
+
});
|
|
416947
|
+
while (offset < sizeBytes) {
|
|
416948
|
+
if (sink.destroyed)
|
|
416949
|
+
return { status: "peer-gone", ...counters() };
|
|
416950
|
+
const length = Math.min(chunkBytes, sizeBytes - offset);
|
|
416951
|
+
let chunk;
|
|
416952
|
+
try {
|
|
416953
|
+
chunk = await read(offset, length);
|
|
416954
|
+
} catch (err) {
|
|
416955
|
+
const error = errorOf(err);
|
|
416956
|
+
sink.destroy(error);
|
|
416957
|
+
return { status: "source-failed", error: error.message, ...counters() };
|
|
416958
|
+
}
|
|
416959
|
+
if (chunk.byteLength === 0) {
|
|
416960
|
+
const error = new Error(`backup download: empty chunk at offset ${offset}/${sizeBytes}`);
|
|
416961
|
+
sink.destroy(error);
|
|
416962
|
+
return { status: "source-failed", error: error.message, ...counters() };
|
|
416963
|
+
}
|
|
416964
|
+
if (sink.destroyed)
|
|
416965
|
+
return { status: "peer-gone", ...counters() };
|
|
416966
|
+
const accepted = sink.write(chunk);
|
|
416967
|
+
offset += chunk.byteLength;
|
|
416968
|
+
if (accepted)
|
|
416969
|
+
continue;
|
|
416970
|
+
const waitStartedAt = now();
|
|
416971
|
+
const outcome = await waitForDrain(sink, graceMs);
|
|
416972
|
+
const waitedMs = now() - waitStartedAt;
|
|
416973
|
+
drainWaits += 1;
|
|
416974
|
+
if (waitedMs > drainWaitMaxMs)
|
|
416975
|
+
drainWaitMaxMs = waitedMs;
|
|
416976
|
+
if (outcome === "closed")
|
|
416977
|
+
return { status: "peer-gone", ...counters() };
|
|
416978
|
+
if (outcome === "timeout") {
|
|
416979
|
+
const queuedBytes = sink.writableLength;
|
|
416980
|
+
sink.destroy(new Error(`backup download: client stopped reading \u2014 ${queuedBytes} bytes queued for ${waitedMs} ms`));
|
|
416981
|
+
return { status: "drain-timeout", heldForMs: waitedMs, queuedBytes, ...counters() };
|
|
416982
|
+
}
|
|
416983
|
+
}
|
|
416984
|
+
sink.end();
|
|
416985
|
+
return { status: "completed", ...counters() };
|
|
416986
|
+
}
|
|
416987
|
+
}
|
|
416988
|
+
});
|
|
416989
|
+
|
|
416990
|
+
// ../../server/backend/dist/api/trpc/client-ip.js
|
|
416991
|
+
var require_client_ip = __commonJS({
|
|
416992
|
+
"../../server/backend/dist/api/trpc/client-ip.js"(exports) {
|
|
416993
|
+
"use strict";
|
|
416994
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
416995
|
+
exports.extractClientIp = extractClientIp;
|
|
416996
|
+
exports.extractCfConnectingIp = extractCfConnectingIp;
|
|
416997
|
+
exports.extractPeerIp = extractPeerIp;
|
|
416998
|
+
exports.extractUserAgent = extractUserAgent;
|
|
416999
|
+
exports.ipClass = ipClass;
|
|
417000
|
+
exports.classifyClient = classifyClient;
|
|
417001
|
+
exports.classifyClientRequest = classifyClientRequest;
|
|
417002
|
+
exports.deriveRelayOnly = deriveRelayOnly;
|
|
417003
|
+
exports.isRemoteClientIp = isRemoteClientIp;
|
|
417004
|
+
function extractClientIp(req) {
|
|
417005
|
+
if (!req)
|
|
417006
|
+
return null;
|
|
417007
|
+
const xff = req.headers["x-forwarded-for"];
|
|
417008
|
+
const xffValue = Array.isArray(xff) ? xff[0] : xff;
|
|
417009
|
+
if (typeof xffValue === "string" && xffValue.length > 0) {
|
|
417010
|
+
const first = xffValue.split(",")[0]?.trim();
|
|
417011
|
+
if (first)
|
|
417012
|
+
return normalizeIp(first);
|
|
417013
|
+
}
|
|
417014
|
+
if ("ip" in req && typeof req.ip === "string" && req.ip.length > 0) {
|
|
417015
|
+
return normalizeIp(req.ip);
|
|
417016
|
+
}
|
|
417017
|
+
const remote = req.socket?.remoteAddress;
|
|
417018
|
+
if (typeof remote === "string" && remote.length > 0) {
|
|
417019
|
+
return normalizeIp(remote);
|
|
417020
|
+
}
|
|
417021
|
+
return null;
|
|
417022
|
+
}
|
|
417023
|
+
function extractCfConnectingIp(req) {
|
|
417024
|
+
if (!req)
|
|
417025
|
+
return null;
|
|
417026
|
+
const raw = req.headers["cf-connecting-ip"];
|
|
417027
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
417028
|
+
if (typeof value === "string" && value.length > 0)
|
|
417029
|
+
return normalizeIp(value.trim());
|
|
417030
|
+
return null;
|
|
417031
|
+
}
|
|
417032
|
+
function extractPeerIp(req) {
|
|
417033
|
+
if (!req)
|
|
417034
|
+
return null;
|
|
417035
|
+
const remote = req.socket?.remoteAddress;
|
|
417036
|
+
if (typeof remote === "string" && remote.length > 0)
|
|
417037
|
+
return normalizeIp(remote);
|
|
417038
|
+
return null;
|
|
417039
|
+
}
|
|
417040
|
+
function extractUserAgent(req) {
|
|
417041
|
+
if (!req)
|
|
417042
|
+
return null;
|
|
417043
|
+
const ua = req.headers["user-agent"];
|
|
417044
|
+
const value = Array.isArray(ua) ? ua[0] : ua;
|
|
417045
|
+
if (typeof value === "string" && value.length > 0)
|
|
417046
|
+
return value;
|
|
417047
|
+
return null;
|
|
417048
|
+
}
|
|
417049
|
+
function normalizeIp(ip) {
|
|
417050
|
+
let out = ip.trim();
|
|
417051
|
+
if (out.startsWith("::ffff:"))
|
|
417052
|
+
out = out.slice("::ffff:".length);
|
|
417053
|
+
const pct = out.indexOf("%");
|
|
417054
|
+
if (pct !== -1)
|
|
417055
|
+
out = out.slice(0, pct);
|
|
417056
|
+
return out;
|
|
417057
|
+
}
|
|
417058
|
+
function ipClass(ip) {
|
|
417059
|
+
if (!ip)
|
|
417060
|
+
return "lan";
|
|
417061
|
+
if (ip.includes(":")) {
|
|
417062
|
+
if (isTailscaleIpv6(ip))
|
|
417063
|
+
return "vpn";
|
|
417064
|
+
if (isPrivateIpv6(ip))
|
|
417065
|
+
return "lan";
|
|
417066
|
+
return "remote";
|
|
417067
|
+
}
|
|
417068
|
+
if (isIpv4(ip)) {
|
|
417069
|
+
if (isTailscaleIpv4(ip))
|
|
417070
|
+
return "vpn";
|
|
417071
|
+
if (isPrivateIpv4(ip))
|
|
417072
|
+
return "lan";
|
|
417073
|
+
return "remote";
|
|
417074
|
+
}
|
|
417075
|
+
return "lan";
|
|
417076
|
+
}
|
|
417077
|
+
function classifyClient(args) {
|
|
417078
|
+
if (args.peerIsLocal && args.cfConnectingIp)
|
|
417079
|
+
return ipClass(args.cfConnectingIp);
|
|
417080
|
+
return ipClass(args.clientIp);
|
|
417081
|
+
}
|
|
417082
|
+
function classifyClientRequest(req) {
|
|
417083
|
+
if (!req)
|
|
417084
|
+
return null;
|
|
417085
|
+
const clientIp = extractClientIp(req);
|
|
417086
|
+
const cfConnectingIp = extractCfConnectingIp(req);
|
|
417087
|
+
const peerIp = extractPeerIp(req);
|
|
417088
|
+
const peerIsLocal = peerIp !== null && ipClass(peerIp) !== "remote";
|
|
417089
|
+
return classifyClient({ clientIp, cfConnectingIp, peerIsLocal });
|
|
417090
|
+
}
|
|
417091
|
+
function deriveRelayOnly(clientClass) {
|
|
417092
|
+
return clientClass === "remote";
|
|
417093
|
+
}
|
|
417094
|
+
function isRemoteClientIp(ip) {
|
|
417095
|
+
return ipClass(ip) === "remote";
|
|
417096
|
+
}
|
|
417097
|
+
function isIpv4(ip) {
|
|
417098
|
+
const parts = ip.split(".");
|
|
417099
|
+
if (parts.length !== 4)
|
|
417100
|
+
return false;
|
|
417101
|
+
return parts.every((p) => {
|
|
417102
|
+
if (!/^\d{1,3}$/.test(p))
|
|
417103
|
+
return false;
|
|
417104
|
+
const n = Number.parseInt(p, 10);
|
|
417105
|
+
return n >= 0 && n <= 255;
|
|
417106
|
+
});
|
|
417107
|
+
}
|
|
417108
|
+
function isTailscaleIpv4(ip) {
|
|
417109
|
+
const parts = ip.split(".").map((p) => Number.parseInt(p, 10));
|
|
417110
|
+
const [a, b] = parts;
|
|
417111
|
+
if (a === void 0 || b === void 0)
|
|
417112
|
+
return false;
|
|
417113
|
+
return a === 100 && b >= 64 && b <= 127;
|
|
417114
|
+
}
|
|
417115
|
+
function isPrivateIpv4(ip) {
|
|
417116
|
+
const parts = ip.split(".").map((p) => Number.parseInt(p, 10));
|
|
417117
|
+
const [a, b] = parts;
|
|
417118
|
+
if (a === void 0 || b === void 0)
|
|
417119
|
+
return false;
|
|
417120
|
+
if (a === 10)
|
|
417121
|
+
return true;
|
|
417122
|
+
if (a === 127)
|
|
417123
|
+
return true;
|
|
417124
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
417125
|
+
return true;
|
|
417126
|
+
if (a === 192 && b === 168)
|
|
417127
|
+
return true;
|
|
417128
|
+
if (a === 169 && b === 254)
|
|
417129
|
+
return true;
|
|
417130
|
+
return false;
|
|
417131
|
+
}
|
|
417132
|
+
function isTailscaleIpv6(ip) {
|
|
417133
|
+
return ip.toLowerCase().startsWith("fd7a:115c:a1e0:");
|
|
417134
|
+
}
|
|
417135
|
+
function isPrivateIpv6(ip) {
|
|
417136
|
+
const lower = ip.toLowerCase();
|
|
417137
|
+
if (lower === "::1")
|
|
417138
|
+
return true;
|
|
417139
|
+
if (lower === "::")
|
|
417140
|
+
return true;
|
|
417141
|
+
if (lower.startsWith("fe80"))
|
|
417142
|
+
return true;
|
|
417143
|
+
if (lower.startsWith("fc") || lower.startsWith("fd"))
|
|
417144
|
+
return true;
|
|
417145
|
+
return false;
|
|
417146
|
+
}
|
|
417147
|
+
}
|
|
417148
|
+
});
|
|
417149
|
+
|
|
417150
|
+
// ../../server/backend/dist/api/backup-download.js
|
|
417151
|
+
var require_backup_download = __commonJS({
|
|
417152
|
+
"../../server/backend/dist/api/backup-download.js"(exports) {
|
|
417153
|
+
"use strict";
|
|
417154
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
417155
|
+
exports.registerBackupDownloadRoute = registerBackupDownloadRoute;
|
|
417156
|
+
var backup_download_pump_js_1 = require_backup_download_pump();
|
|
417157
|
+
var client_ip_js_1 = require_client_ip();
|
|
417158
|
+
function safeAttachmentName(name) {
|
|
417159
|
+
return name.replace(/[\r\n"]/g, "_");
|
|
417160
|
+
}
|
|
417161
|
+
function registerBackupDownloadRoute(fastify, options) {
|
|
417162
|
+
const { verifier, capabilities, logger } = options;
|
|
417163
|
+
const chunkBytes = options.chunkBytes ?? backup_download_pump_js_1.BACKUP_DOWNLOAD_CHUNK_BYTES;
|
|
417164
|
+
const graceMs = options.graceMs ?? backup_download_pump_js_1.BACKUP_DOWNLOAD_DRAIN_GRACE_MS;
|
|
417165
|
+
fastify.get("/api/backup/download/:locationId/:archiveId", async (request, reply) => {
|
|
417166
|
+
const authHeader = request.headers.authorization;
|
|
417167
|
+
if (!authHeader) {
|
|
417168
|
+
return reply.status(401).send({ error: "Unauthorized" });
|
|
417169
|
+
}
|
|
417170
|
+
try {
|
|
417171
|
+
const payload = verifier.verifyToken(authHeader.replace("Bearer ", ""));
|
|
417172
|
+
if (!payload.isAdmin) {
|
|
417173
|
+
return reply.status(403).send({ error: "Admin required" });
|
|
417174
|
+
}
|
|
417175
|
+
} catch {
|
|
417176
|
+
return reply.status(401).send({ error: "Invalid token" });
|
|
417177
|
+
}
|
|
417178
|
+
const { locationId, archiveId } = request.params;
|
|
417179
|
+
const backup = capabilities.getSingleton("backup");
|
|
417180
|
+
if (!backup?.listArchives) {
|
|
417181
|
+
return reply.status(503).send({ error: "Backup orchestrator unavailable" });
|
|
417182
|
+
}
|
|
417183
|
+
const archives = await backup.listArchives({ destinationId: locationId });
|
|
417184
|
+
const archive = archives.find((a) => a.id === archiveId);
|
|
417185
|
+
if (!archive) {
|
|
417186
|
+
return reply.status(404).send({ error: "Archive not found" });
|
|
417187
|
+
}
|
|
417188
|
+
const storage = capabilities.getSingleton("storage");
|
|
417189
|
+
if (!storage?.beginDownload) {
|
|
417190
|
+
return reply.status(503).send({ error: "Storage cap unavailable" });
|
|
417191
|
+
}
|
|
417192
|
+
const { downloadId, sizeBytes } = await storage.beginDownload({
|
|
417193
|
+
location: locationId,
|
|
417194
|
+
relativePath: archive.filename
|
|
417195
|
+
});
|
|
417196
|
+
reply.hijack();
|
|
417197
|
+
reply.raw.writeHead(200, {
|
|
417198
|
+
"content-type": "application/gzip",
|
|
417199
|
+
"content-length": String(sizeBytes),
|
|
417200
|
+
"content-disposition": `attachment; filename="${safeAttachmentName(`${archive.label ?? archive.id}.tar.gz`)}"`
|
|
417201
|
+
});
|
|
417202
|
+
const facts = {
|
|
417203
|
+
locationId,
|
|
417204
|
+
archiveId,
|
|
417205
|
+
filename: archive.filename,
|
|
417206
|
+
sizeBytes,
|
|
417207
|
+
ip: (0, client_ip_js_1.extractClientIp)(request.raw) ?? "(unidentified)",
|
|
417208
|
+
chunkBytes,
|
|
417209
|
+
graceMs
|
|
417210
|
+
};
|
|
417211
|
+
let result;
|
|
417212
|
+
try {
|
|
417213
|
+
result = await (0, backup_download_pump_js_1.pumpDownload)({
|
|
417214
|
+
sizeBytes,
|
|
417215
|
+
chunkBytes,
|
|
417216
|
+
graceMs,
|
|
417217
|
+
sink: reply.raw,
|
|
417218
|
+
read: (offset, length) => storage.readChunk({ downloadId, offset, length })
|
|
417219
|
+
});
|
|
417220
|
+
} finally {
|
|
417221
|
+
try {
|
|
417222
|
+
await storage.endDownload({ downloadId });
|
|
417223
|
+
} catch (err) {
|
|
417224
|
+
logger.warn("backup archive download: the storage cap refused to close the handle", {
|
|
417225
|
+
meta: { ...facts, error: err instanceof Error ? err.message : String(err) }
|
|
417226
|
+
});
|
|
417227
|
+
}
|
|
417228
|
+
}
|
|
417229
|
+
logOutcome(logger, facts, result);
|
|
417230
|
+
});
|
|
417231
|
+
}
|
|
417232
|
+
function logOutcome(logger, facts, result) {
|
|
417233
|
+
const meta = { ...facts, ...result };
|
|
417234
|
+
switch (result.status) {
|
|
417235
|
+
case "completed":
|
|
417236
|
+
logger.info("backup archive download completed", { meta });
|
|
417237
|
+
return;
|
|
417238
|
+
case "peer-gone":
|
|
417239
|
+
logger.info("backup archive download abandoned \u2014 the client closed the connection", { meta });
|
|
417240
|
+
return;
|
|
417241
|
+
case "drain-timeout":
|
|
417242
|
+
logger.warn("backup archive download cut \u2014 the client stopped reading and the response queue stayed unsent for the whole grace period (nothing more is read; the queue is released)", { meta });
|
|
417243
|
+
return;
|
|
417244
|
+
case "source-failed":
|
|
417245
|
+
logger.warn("backup archive download failed \u2014 the storage cap could not serve the archive", {
|
|
417246
|
+
meta
|
|
417247
|
+
});
|
|
417248
|
+
return;
|
|
417249
|
+
}
|
|
417250
|
+
}
|
|
417251
|
+
}
|
|
417252
|
+
});
|
|
417253
|
+
|
|
416023
417254
|
// ../../server/backend/dist/auth/session-cookie.js
|
|
416024
417255
|
var require_session_cookie = __commonJS({
|
|
416025
417256
|
"../../server/backend/dist/auth/session-cookie.js"(exports) {
|
|
@@ -422314,166 +423545,6 @@ var require_core_cap_bridge = __commonJS({
|
|
|
422314
423545
|
}
|
|
422315
423546
|
});
|
|
422316
423547
|
|
|
422317
|
-
// ../../server/backend/dist/api/trpc/client-ip.js
|
|
422318
|
-
var require_client_ip = __commonJS({
|
|
422319
|
-
"../../server/backend/dist/api/trpc/client-ip.js"(exports) {
|
|
422320
|
-
"use strict";
|
|
422321
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
422322
|
-
exports.extractClientIp = extractClientIp;
|
|
422323
|
-
exports.extractCfConnectingIp = extractCfConnectingIp;
|
|
422324
|
-
exports.extractPeerIp = extractPeerIp;
|
|
422325
|
-
exports.extractUserAgent = extractUserAgent;
|
|
422326
|
-
exports.ipClass = ipClass;
|
|
422327
|
-
exports.classifyClient = classifyClient;
|
|
422328
|
-
exports.classifyClientRequest = classifyClientRequest;
|
|
422329
|
-
exports.deriveRelayOnly = deriveRelayOnly;
|
|
422330
|
-
exports.isRemoteClientIp = isRemoteClientIp;
|
|
422331
|
-
function extractClientIp(req) {
|
|
422332
|
-
if (!req)
|
|
422333
|
-
return null;
|
|
422334
|
-
const xff = req.headers["x-forwarded-for"];
|
|
422335
|
-
const xffValue = Array.isArray(xff) ? xff[0] : xff;
|
|
422336
|
-
if (typeof xffValue === "string" && xffValue.length > 0) {
|
|
422337
|
-
const first = xffValue.split(",")[0]?.trim();
|
|
422338
|
-
if (first)
|
|
422339
|
-
return normalizeIp(first);
|
|
422340
|
-
}
|
|
422341
|
-
if ("ip" in req && typeof req.ip === "string" && req.ip.length > 0) {
|
|
422342
|
-
return normalizeIp(req.ip);
|
|
422343
|
-
}
|
|
422344
|
-
const remote = req.socket?.remoteAddress;
|
|
422345
|
-
if (typeof remote === "string" && remote.length > 0) {
|
|
422346
|
-
return normalizeIp(remote);
|
|
422347
|
-
}
|
|
422348
|
-
return null;
|
|
422349
|
-
}
|
|
422350
|
-
function extractCfConnectingIp(req) {
|
|
422351
|
-
if (!req)
|
|
422352
|
-
return null;
|
|
422353
|
-
const raw = req.headers["cf-connecting-ip"];
|
|
422354
|
-
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
422355
|
-
if (typeof value === "string" && value.length > 0)
|
|
422356
|
-
return normalizeIp(value.trim());
|
|
422357
|
-
return null;
|
|
422358
|
-
}
|
|
422359
|
-
function extractPeerIp(req) {
|
|
422360
|
-
if (!req)
|
|
422361
|
-
return null;
|
|
422362
|
-
const remote = req.socket?.remoteAddress;
|
|
422363
|
-
if (typeof remote === "string" && remote.length > 0)
|
|
422364
|
-
return normalizeIp(remote);
|
|
422365
|
-
return null;
|
|
422366
|
-
}
|
|
422367
|
-
function extractUserAgent(req) {
|
|
422368
|
-
if (!req)
|
|
422369
|
-
return null;
|
|
422370
|
-
const ua = req.headers["user-agent"];
|
|
422371
|
-
const value = Array.isArray(ua) ? ua[0] : ua;
|
|
422372
|
-
if (typeof value === "string" && value.length > 0)
|
|
422373
|
-
return value;
|
|
422374
|
-
return null;
|
|
422375
|
-
}
|
|
422376
|
-
function normalizeIp(ip) {
|
|
422377
|
-
let out = ip.trim();
|
|
422378
|
-
if (out.startsWith("::ffff:"))
|
|
422379
|
-
out = out.slice("::ffff:".length);
|
|
422380
|
-
const pct = out.indexOf("%");
|
|
422381
|
-
if (pct !== -1)
|
|
422382
|
-
out = out.slice(0, pct);
|
|
422383
|
-
return out;
|
|
422384
|
-
}
|
|
422385
|
-
function ipClass(ip) {
|
|
422386
|
-
if (!ip)
|
|
422387
|
-
return "lan";
|
|
422388
|
-
if (ip.includes(":")) {
|
|
422389
|
-
if (isTailscaleIpv6(ip))
|
|
422390
|
-
return "vpn";
|
|
422391
|
-
if (isPrivateIpv6(ip))
|
|
422392
|
-
return "lan";
|
|
422393
|
-
return "remote";
|
|
422394
|
-
}
|
|
422395
|
-
if (isIpv4(ip)) {
|
|
422396
|
-
if (isTailscaleIpv4(ip))
|
|
422397
|
-
return "vpn";
|
|
422398
|
-
if (isPrivateIpv4(ip))
|
|
422399
|
-
return "lan";
|
|
422400
|
-
return "remote";
|
|
422401
|
-
}
|
|
422402
|
-
return "lan";
|
|
422403
|
-
}
|
|
422404
|
-
function classifyClient(args) {
|
|
422405
|
-
if (args.peerIsLocal && args.cfConnectingIp)
|
|
422406
|
-
return ipClass(args.cfConnectingIp);
|
|
422407
|
-
return ipClass(args.clientIp);
|
|
422408
|
-
}
|
|
422409
|
-
function classifyClientRequest(req) {
|
|
422410
|
-
if (!req)
|
|
422411
|
-
return null;
|
|
422412
|
-
const clientIp = extractClientIp(req);
|
|
422413
|
-
const cfConnectingIp = extractCfConnectingIp(req);
|
|
422414
|
-
const peerIp = extractPeerIp(req);
|
|
422415
|
-
const peerIsLocal = peerIp !== null && ipClass(peerIp) !== "remote";
|
|
422416
|
-
return classifyClient({ clientIp, cfConnectingIp, peerIsLocal });
|
|
422417
|
-
}
|
|
422418
|
-
function deriveRelayOnly(clientClass) {
|
|
422419
|
-
return clientClass === "remote";
|
|
422420
|
-
}
|
|
422421
|
-
function isRemoteClientIp(ip) {
|
|
422422
|
-
return ipClass(ip) === "remote";
|
|
422423
|
-
}
|
|
422424
|
-
function isIpv4(ip) {
|
|
422425
|
-
const parts = ip.split(".");
|
|
422426
|
-
if (parts.length !== 4)
|
|
422427
|
-
return false;
|
|
422428
|
-
return parts.every((p) => {
|
|
422429
|
-
if (!/^\d{1,3}$/.test(p))
|
|
422430
|
-
return false;
|
|
422431
|
-
const n = Number.parseInt(p, 10);
|
|
422432
|
-
return n >= 0 && n <= 255;
|
|
422433
|
-
});
|
|
422434
|
-
}
|
|
422435
|
-
function isTailscaleIpv4(ip) {
|
|
422436
|
-
const parts = ip.split(".").map((p) => Number.parseInt(p, 10));
|
|
422437
|
-
const [a, b] = parts;
|
|
422438
|
-
if (a === void 0 || b === void 0)
|
|
422439
|
-
return false;
|
|
422440
|
-
return a === 100 && b >= 64 && b <= 127;
|
|
422441
|
-
}
|
|
422442
|
-
function isPrivateIpv4(ip) {
|
|
422443
|
-
const parts = ip.split(".").map((p) => Number.parseInt(p, 10));
|
|
422444
|
-
const [a, b] = parts;
|
|
422445
|
-
if (a === void 0 || b === void 0)
|
|
422446
|
-
return false;
|
|
422447
|
-
if (a === 10)
|
|
422448
|
-
return true;
|
|
422449
|
-
if (a === 127)
|
|
422450
|
-
return true;
|
|
422451
|
-
if (a === 172 && b >= 16 && b <= 31)
|
|
422452
|
-
return true;
|
|
422453
|
-
if (a === 192 && b === 168)
|
|
422454
|
-
return true;
|
|
422455
|
-
if (a === 169 && b === 254)
|
|
422456
|
-
return true;
|
|
422457
|
-
return false;
|
|
422458
|
-
}
|
|
422459
|
-
function isTailscaleIpv6(ip) {
|
|
422460
|
-
return ip.toLowerCase().startsWith("fd7a:115c:a1e0:");
|
|
422461
|
-
}
|
|
422462
|
-
function isPrivateIpv6(ip) {
|
|
422463
|
-
const lower = ip.toLowerCase();
|
|
422464
|
-
if (lower === "::1")
|
|
422465
|
-
return true;
|
|
422466
|
-
if (lower === "::")
|
|
422467
|
-
return true;
|
|
422468
|
-
if (lower.startsWith("fe80"))
|
|
422469
|
-
return true;
|
|
422470
|
-
if (lower.startsWith("fc") || lower.startsWith("fd"))
|
|
422471
|
-
return true;
|
|
422472
|
-
return false;
|
|
422473
|
-
}
|
|
422474
|
-
}
|
|
422475
|
-
});
|
|
422476
|
-
|
|
422477
423548
|
// ../../server/backend/dist/api/trpc/http-request-census-hook.js
|
|
422478
423549
|
var require_http_request_census_hook = __commonJS({
|
|
422479
423550
|
"../../server/backend/dist/api/trpc/http-request-census-hook.js"(exports) {
|
|
@@ -433254,6 +434325,7 @@ var require_main4 = __commonJS({
|
|
|
433254
434325
|
var ws_2 = require_ws();
|
|
433255
434326
|
var addon_upload_1 = require_addon_upload();
|
|
433256
434327
|
var auth_whoami_1 = require_auth_whoami();
|
|
434328
|
+
var backup_download_js_1 = require_backup_download();
|
|
433257
434329
|
var health_routes_1 = require_health_routes();
|
|
433258
434330
|
var adaptive_probe_routes_1 = require_adaptive_probe_routes();
|
|
433259
434331
|
var model_distributor_js_1 = require_model_distributor();
|
|
@@ -433401,6 +434473,12 @@ var require_main4 = __commonJS({
|
|
|
433401
434473
|
socketPlane: (0, system_1.createSocketPlaneReader)({
|
|
433402
434474
|
registry: () => moleculerForEventPlane?.childRegistry ?? null
|
|
433403
434475
|
}),
|
|
434476
|
+
// The write queue to every peer NODE, from Moleculer's own writer
|
|
434477
|
+
// sockets. Those are unref'd (`TcpWriter.connect`), so the 2026-09-10
|
|
434478
|
+
// exclusion of "every socket queue" — a sum over `_getActiveHandles()` —
|
|
434479
|
+
// never saw them. With the UDS queues above, every outbound plane this
|
|
434480
|
+
// process writes to is now on the line and judged on every probe (D446).
|
|
434481
|
+
meshQueue: (0, system_1.createMeshQueueReader)(() => moleculerForEventPlane?.broker ?? null),
|
|
433404
434482
|
// The ArrayBuffer census, armed by the probe itself. Twice on 2026-09-10
|
|
433405
434483
|
// this process's `arrayBuffers` climbed linearly for an hour (to 1.3 GB
|
|
433406
434484
|
// and to 5 GB, both LIVE across a forced compaction) and released in one
|
|
@@ -433716,70 +434794,10 @@ var require_main4 = __commonJS({
|
|
|
433716
434794
|
});
|
|
433717
434795
|
}
|
|
433718
434796
|
});
|
|
433719
|
-
|
|
433720
|
-
|
|
433721
|
-
|
|
433722
|
-
|
|
433723
|
-
}
|
|
433724
|
-
try {
|
|
433725
|
-
const token2 = authHeader.replace("Bearer ", "");
|
|
433726
|
-
const downloadAuth = app.get(auth_service_1.AuthService);
|
|
433727
|
-
const payload = downloadAuth.verifyToken(token2);
|
|
433728
|
-
if (!payload.isAdmin) {
|
|
433729
|
-
return reply.status(403).send({ error: "Admin required" });
|
|
433730
|
-
}
|
|
433731
|
-
} catch {
|
|
433732
|
-
return reply.status(401).send({ error: "Invalid token" });
|
|
433733
|
-
}
|
|
433734
|
-
const { locationId, archiveId } = request.params;
|
|
433735
|
-
const backupSingleton = capabilityRegistry.getSingleton("backup");
|
|
433736
|
-
if (!backupSingleton?.listArchives) {
|
|
433737
|
-
return reply.status(503).send({ error: "Backup orchestrator unavailable" });
|
|
433738
|
-
}
|
|
433739
|
-
const archives = await backupSingleton.listArchives({ destinationId: locationId });
|
|
433740
|
-
const archive = archives.find((a) => a.id === archiveId);
|
|
433741
|
-
if (!archive) {
|
|
433742
|
-
return reply.status(404).send({ error: "Archive not found" });
|
|
433743
|
-
}
|
|
433744
|
-
const storage = capabilityRegistry.getSingleton("storage");
|
|
433745
|
-
if (!storage?.beginDownload) {
|
|
433746
|
-
return reply.status(503).send({ error: "Storage cap unavailable" });
|
|
433747
|
-
}
|
|
433748
|
-
const downloadName = `${archive.label ?? archive.id}.tar.gz`;
|
|
433749
|
-
const safeName = downloadName.replace(/[\r\n"]/g, "_");
|
|
433750
|
-
reply.header("content-type", "application/gzip");
|
|
433751
|
-
reply.header("content-length", String(archive.sizeBytes));
|
|
433752
|
-
reply.header("content-disposition", `attachment; filename="${safeName}"`);
|
|
433753
|
-
const { downloadId, sizeBytes } = await storage.beginDownload({
|
|
433754
|
-
location: locationId,
|
|
433755
|
-
relativePath: archive.filename
|
|
433756
|
-
});
|
|
433757
|
-
const CHUNK = 8 * 1024 * 1024;
|
|
433758
|
-
try {
|
|
433759
|
-
let offset = 0;
|
|
433760
|
-
while (offset < sizeBytes) {
|
|
433761
|
-
const len = Math.min(CHUNK, sizeBytes - offset);
|
|
433762
|
-
const chunk = await storage.readChunk({ downloadId, offset, length: len });
|
|
433763
|
-
if (chunk.byteLength === 0) {
|
|
433764
|
-
throw new Error(`backup download: empty chunk at offset ${offset}/${sizeBytes}`);
|
|
433765
|
-
}
|
|
433766
|
-
reply.raw.write(chunk);
|
|
433767
|
-
offset += chunk.byteLength;
|
|
433768
|
-
}
|
|
433769
|
-
reply.raw.end();
|
|
433770
|
-
} catch (err) {
|
|
433771
|
-
console.error("[backup-download] stream failed:", err);
|
|
433772
|
-
if (!reply.raw.headersSent) {
|
|
433773
|
-
return reply.status(500).send({ error: "Download failed" });
|
|
433774
|
-
}
|
|
433775
|
-
reply.raw.destroy(err instanceof Error ? err : new Error(String(err)));
|
|
433776
|
-
} finally {
|
|
433777
|
-
try {
|
|
433778
|
-
await storage.endDownload({ downloadId });
|
|
433779
|
-
} catch {
|
|
433780
|
-
}
|
|
433781
|
-
}
|
|
433782
|
-
return reply;
|
|
434797
|
+
(0, backup_download_js_1.registerBackupDownloadRoute)(fastify, {
|
|
434798
|
+
verifier: app.get(auth_service_1.AuthService),
|
|
434799
|
+
capabilities: capabilityRegistry,
|
|
434800
|
+
logger: app.get(logging_service_1.LoggingService).createLogger("backup-download")
|
|
433783
434801
|
});
|
|
433784
434802
|
fastify.post("/api/auth/session", async (request, reply) => {
|
|
433785
434803
|
const token2 = request.body?.token;
|