@camstack/addon-post-analysis 1.2.92 → 1.2.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{dist-BfrtqGyh.js → dist-BdojoP7i.js} +346 -2
- package/dist/{dist-VnaTfwAL.mjs → dist-C-_TL-I1.mjs} +329 -3
- package/dist/embedding-encoder/index.js +171 -4
- package/dist/embedding-encoder/index.mjs +171 -4
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BIDGLXRs.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CeFPqm3h.mjs} +3 -3
- package/dist/pipeline-analytics/{hostInit-CpWvyhen.mjs → hostInit-BExsGl4h.mjs} +3 -3
- package/dist/pipeline-analytics/index.js +51 -2
- package/dist/pipeline-analytics/index.mjs +51 -2
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +3 -2
|
@@ -29,7 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
enumerable: true
|
|
30
30
|
}) : target, mod));
|
|
31
31
|
//#endregion
|
|
32
|
-
//#region ../types/dist/event-category-
|
|
32
|
+
//#region ../types/dist/event-category-XfKNtfCc.mjs
|
|
33
33
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
34
34
|
EventCategory["SystemBoot"] = "system.boot";
|
|
35
35
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -68,6 +68,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
68
68
|
EventCategory["AddonInstalled"] = "addon.installed";
|
|
69
69
|
EventCategory["AddonUninstalled"] = "addon.uninstalled";
|
|
70
70
|
EventCategory["AddonCrashed"] = "addon.crashed";
|
|
71
|
+
/**
|
|
72
|
+
* A RUNNER the D6 crash circuit-breaker gave up on — terminal.
|
|
73
|
+
*
|
|
74
|
+
* `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
|
|
75
|
+
* respawned"); this is the one that never resolves itself. Emitted exactly
|
|
76
|
+
* once per trip, by `process-service.ts`, carrying the node, the runner, the
|
|
77
|
+
* addons it hosted and the crash count that tripped the breaker.
|
|
78
|
+
*
|
|
79
|
+
* It exists because a runner marked terminally `failed` used to be SILENT:
|
|
80
|
+
* on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
|
|
81
|
+
* errors, the breaker stopped respawning it (correctly), `/health` kept
|
|
82
|
+
* returning 200, and fleet-wide recording was gone for 3h15 before the
|
|
83
|
+
* operator's phone told him. The Notification Center's system-event intake
|
|
84
|
+
* consumes this category and maps it to the `addon-crash-loop` kind.
|
|
85
|
+
*/
|
|
86
|
+
EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
|
|
71
87
|
EventCategory["AddonError"] = "addon.error";
|
|
72
88
|
EventCategory["AddonPageReady"] = "addon.page-ready";
|
|
73
89
|
EventCategory["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -14845,6 +14861,7 @@ var NcSystemEventKindSchema = _enum([
|
|
|
14845
14861
|
"node-offline",
|
|
14846
14862
|
"node-inference-unavailable",
|
|
14847
14863
|
"detection-blind",
|
|
14864
|
+
"addon-crash-loop",
|
|
14848
14865
|
"addon-update-available",
|
|
14849
14866
|
"server-update-available",
|
|
14850
14867
|
"alarm-triggered",
|
|
@@ -15970,6 +15987,10 @@ var NC_CONDITION_CATALOG = [
|
|
|
15970
15987
|
value: "detection-blind",
|
|
15971
15988
|
label: "Camera detecting nothing"
|
|
15972
15989
|
},
|
|
15990
|
+
{
|
|
15991
|
+
value: "addon-crash-loop",
|
|
15992
|
+
label: "Addon stopped after repeated crashes"
|
|
15993
|
+
},
|
|
15973
15994
|
{
|
|
15974
15995
|
value: "addon-update-available",
|
|
15975
15996
|
label: "Addon update available"
|
|
@@ -21504,6 +21525,14 @@ var ClipSchema = object({
|
|
|
21504
21525
|
endMs: number()
|
|
21505
21526
|
}),
|
|
21506
21527
|
/**
|
|
21528
|
+
* Distinct object classes attached to this visit (`person`, `car`, …),
|
|
21529
|
+
* dominant first, capped at {@link MAX_CLIP_LABELS}. The ribbon renders these
|
|
21530
|
+
* instead of the bare kind — "Object" tells the operator nothing a colour bar
|
|
21531
|
+
* did not. Absent (never empty) when the visit attached no classified object
|
|
21532
|
+
* event, so a motion/audio-only visit keeps its kind label.
|
|
21533
|
+
*/
|
|
21534
|
+
labels: array(string()).max(3).optional(),
|
|
21535
|
+
/**
|
|
21507
21536
|
* Lazy thumbnail URL, never inlined.
|
|
21508
21537
|
*
|
|
21509
21538
|
* Recording-derived clips (events-mode keep-window, and the prepared
|
|
@@ -38568,7 +38597,7 @@ function systemEventFilterApplies(kind, filter) {
|
|
|
38568
38597
|
switch (filter) {
|
|
38569
38598
|
case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind === "alarm-triggered" || kind === "export-completed";
|
|
38570
38599
|
case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
|
|
38571
|
-
case "nodeIds": return kind.startsWith("node-") || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
|
|
38600
|
+
case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
|
|
38572
38601
|
case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
|
|
38573
38602
|
}
|
|
38574
38603
|
}
|
|
@@ -39025,6 +39054,303 @@ function cosineSimilarity(a, b) {
|
|
|
39025
39054
|
function hfModelUrl(repo, path) {
|
|
39026
39055
|
return `https://huggingface.co/${repo}/resolve/main/${path}`;
|
|
39027
39056
|
}
|
|
39057
|
+
var MB = 1024 * 1024;
|
|
39058
|
+
var DEFAULT_POOL_MEMORY_POLICY = {
|
|
39059
|
+
sampleIntervalMs: 6e4,
|
|
39060
|
+
baselineSettleSamples: 5,
|
|
39061
|
+
baselineSampleCount: 3,
|
|
39062
|
+
restartMultiple: 4,
|
|
39063
|
+
floorBytes: 1024 * MB,
|
|
39064
|
+
ceilingBytes: 3072 * MB,
|
|
39065
|
+
cooldownMs: 30 * 6e4,
|
|
39066
|
+
maxRestartsPerWindow: 6,
|
|
39067
|
+
restartWindowMs: 1440 * 6e4
|
|
39068
|
+
};
|
|
39069
|
+
/**
|
|
39070
|
+
* Resolve the policy from env overrides (`CAMSTACK_POOL_MEM_*`). Garbage or
|
|
39071
|
+
* absent values keep the default — an operator typo must never disable the
|
|
39072
|
+
* bound or set it to zero.
|
|
39073
|
+
*/
|
|
39074
|
+
function resolvePoolMemoryPolicy(env) {
|
|
39075
|
+
const num = (key, fallback, min) => {
|
|
39076
|
+
const raw = env[key];
|
|
39077
|
+
if (raw === void 0) return fallback;
|
|
39078
|
+
const parsed = Number(raw);
|
|
39079
|
+
return Number.isFinite(parsed) && parsed >= min ? parsed : fallback;
|
|
39080
|
+
};
|
|
39081
|
+
const d = DEFAULT_POOL_MEMORY_POLICY;
|
|
39082
|
+
return {
|
|
39083
|
+
sampleIntervalMs: num("CAMSTACK_POOL_MEM_INTERVAL_MS", d.sampleIntervalMs, 5e3),
|
|
39084
|
+
baselineSettleSamples: d.baselineSettleSamples,
|
|
39085
|
+
baselineSampleCount: d.baselineSampleCount,
|
|
39086
|
+
restartMultiple: num("CAMSTACK_POOL_MEM_MULTIPLE", d.restartMultiple, 1.5),
|
|
39087
|
+
floorBytes: num("CAMSTACK_POOL_MEM_FLOOR_MB", d.floorBytes / MB, 128) * MB,
|
|
39088
|
+
ceilingBytes: num("CAMSTACK_POOL_MEM_CEILING_MB", d.ceilingBytes / MB, 256) * MB,
|
|
39089
|
+
cooldownMs: num("CAMSTACK_POOL_MEM_COOLDOWN_MS", d.cooldownMs, 6e4),
|
|
39090
|
+
maxRestartsPerWindow: num("CAMSTACK_POOL_MEM_MAX_RESTARTS", d.maxRestartsPerWindow, 1),
|
|
39091
|
+
restartWindowMs: num("CAMSTACK_POOL_MEM_RESTART_WINDOW_MS", d.restartWindowMs, 6e4)
|
|
39092
|
+
};
|
|
39093
|
+
}
|
|
39094
|
+
/** Parse the fields this watchdog needs out of `/proc/<pid>/status` text.
|
|
39095
|
+
* Returns null when VmRSS is missing (dead pid, kernel thread, bad read). */
|
|
39096
|
+
function parseProcStatus(text) {
|
|
39097
|
+
const kb = (label) => {
|
|
39098
|
+
const match = text.match(new RegExp(`^${label}:\\s+(\\d+)\\s*kB`, "m"));
|
|
39099
|
+
return match ? Number(match[1]) * 1024 : null;
|
|
39100
|
+
};
|
|
39101
|
+
const rssBytes = kb("VmRSS");
|
|
39102
|
+
if (rssBytes === null) return null;
|
|
39103
|
+
const threadsMatch = text.match(/^Threads:\s+(\d+)/m);
|
|
39104
|
+
return {
|
|
39105
|
+
rssBytes,
|
|
39106
|
+
vmBytes: kb("VmSize") ?? 0,
|
|
39107
|
+
hwmBytes: kb("VmHWM") ?? 0,
|
|
39108
|
+
swapBytes: kb("VmSwap") ?? 0,
|
|
39109
|
+
threads: threadsMatch ? Number(threadsMatch[1]) : 0
|
|
39110
|
+
};
|
|
39111
|
+
}
|
|
39112
|
+
function initialPoolMemoryState() {
|
|
39113
|
+
return {
|
|
39114
|
+
settleSeen: 0,
|
|
39115
|
+
baselineWindow: [],
|
|
39116
|
+
baselineBytes: null,
|
|
39117
|
+
restartsAt: [],
|
|
39118
|
+
lastRestartAt: null
|
|
39119
|
+
};
|
|
39120
|
+
}
|
|
39121
|
+
function median(values) {
|
|
39122
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
39123
|
+
return sorted[Math.floor(sorted.length / 2)];
|
|
39124
|
+
}
|
|
39125
|
+
function advanceBaseline(state, rssBytes, policy) {
|
|
39126
|
+
if (state.baselineBytes !== null) return state;
|
|
39127
|
+
if (state.settleSeen < policy.baselineSettleSamples) return {
|
|
39128
|
+
...state,
|
|
39129
|
+
settleSeen: state.settleSeen + 1
|
|
39130
|
+
};
|
|
39131
|
+
const window = [...state.baselineWindow, rssBytes];
|
|
39132
|
+
if (window.length < policy.baselineSampleCount) return {
|
|
39133
|
+
...state,
|
|
39134
|
+
baselineWindow: window
|
|
39135
|
+
};
|
|
39136
|
+
return {
|
|
39137
|
+
...state,
|
|
39138
|
+
baselineWindow: window,
|
|
39139
|
+
baselineBytes: median(window)
|
|
39140
|
+
};
|
|
39141
|
+
}
|
|
39142
|
+
/** The one place a pool's restart threshold is computed. */
|
|
39143
|
+
function poolMemoryThreshold(baselineBytes, policy) {
|
|
39144
|
+
if (baselineBytes === null) return policy.ceilingBytes;
|
|
39145
|
+
return Math.min(policy.ceilingBytes, Math.max(policy.floorBytes, policy.restartMultiple * baselineBytes));
|
|
39146
|
+
}
|
|
39147
|
+
function pruneRestarts(restartsAt, nowMs, policy) {
|
|
39148
|
+
return restartsAt.filter((t) => nowMs - t < policy.restartWindowMs);
|
|
39149
|
+
}
|
|
39150
|
+
/**
|
|
39151
|
+
* Evaluate one RSS sample. Pure: returns the successor state plus the verdict.
|
|
39152
|
+
* The caller performs (and logs) the restart, then commits it via
|
|
39153
|
+
* {@link commitWatchdogRestart}.
|
|
39154
|
+
*/
|
|
39155
|
+
function evaluatePoolMemory(state, rssBytes, nowMs, policy) {
|
|
39156
|
+
const next = advanceBaseline(state, rssBytes, policy);
|
|
39157
|
+
const thresholdBytes = poolMemoryThreshold(next.baselineBytes, policy);
|
|
39158
|
+
if (rssBytes <= thresholdBytes) return {
|
|
39159
|
+
state: next,
|
|
39160
|
+
action: next.baselineBytes === null ? "baseline-pending" : "ok",
|
|
39161
|
+
baselineBytes: next.baselineBytes,
|
|
39162
|
+
thresholdBytes
|
|
39163
|
+
};
|
|
39164
|
+
const inWindow = pruneRestarts(next.restartsAt, nowMs, policy);
|
|
39165
|
+
const pruned = {
|
|
39166
|
+
...next,
|
|
39167
|
+
restartsAt: inWindow
|
|
39168
|
+
};
|
|
39169
|
+
if (inWindow.length >= policy.maxRestartsPerWindow) return {
|
|
39170
|
+
state: pruned,
|
|
39171
|
+
action: "exhausted",
|
|
39172
|
+
baselineBytes: next.baselineBytes,
|
|
39173
|
+
thresholdBytes
|
|
39174
|
+
};
|
|
39175
|
+
if (pruned.lastRestartAt !== null && nowMs - pruned.lastRestartAt < policy.cooldownMs) return {
|
|
39176
|
+
state: pruned,
|
|
39177
|
+
action: "cooldown",
|
|
39178
|
+
baselineBytes: next.baselineBytes,
|
|
39179
|
+
thresholdBytes
|
|
39180
|
+
};
|
|
39181
|
+
return {
|
|
39182
|
+
state: pruned,
|
|
39183
|
+
action: "restart",
|
|
39184
|
+
baselineBytes: next.baselineBytes,
|
|
39185
|
+
thresholdBytes
|
|
39186
|
+
};
|
|
39187
|
+
}
|
|
39188
|
+
/** Record a performed watchdog restart: budget consumed, baseline reset —
|
|
39189
|
+
* the recreated pool is a NEW process and gets a fresh settle window. */
|
|
39190
|
+
function commitWatchdogRestart(state, nowMs) {
|
|
39191
|
+
return {
|
|
39192
|
+
...initialPoolMemoryState(),
|
|
39193
|
+
restartsAt: [...state.restartsAt, nowMs],
|
|
39194
|
+
lastRestartAt: nowMs
|
|
39195
|
+
};
|
|
39196
|
+
}
|
|
39197
|
+
/** Reset baseline tracking (pool process replaced OUTSIDE the watchdog —
|
|
39198
|
+
* kernel OOM kill + respawn, idle-reaper eviction, tuning respawn). The
|
|
39199
|
+
* restart budget is kept: it bounds the WATCHDOG, not the pool. */
|
|
39200
|
+
function resetPoolBaseline(state) {
|
|
39201
|
+
return {
|
|
39202
|
+
...initialPoolMemoryState(),
|
|
39203
|
+
restartsAt: state.restartsAt,
|
|
39204
|
+
lastRestartAt: state.lastRestartAt
|
|
39205
|
+
};
|
|
39206
|
+
}
|
|
39207
|
+
/**
|
|
39208
|
+
* Pick ONE pool to restart this sweep — the worst overage ratio. Restarting
|
|
39209
|
+
* several pools at once (e.g. after a model rollout grew every baseline)
|
|
39210
|
+
* would take detection down on every camera simultaneously; one per sweep
|
|
39211
|
+
* means the survivors keep serving while the worst offender reloads, and the
|
|
39212
|
+
* next sweep (one interval later) takes the next one.
|
|
39213
|
+
*/
|
|
39214
|
+
function pickRestartCandidate(candidates) {
|
|
39215
|
+
if (candidates.length === 0) return null;
|
|
39216
|
+
let worst = candidates[0];
|
|
39217
|
+
for (const c of candidates) if (c.rssBytes / c.thresholdBytes > worst.rssBytes / worst.thresholdBytes) worst = c;
|
|
39218
|
+
return worst.key;
|
|
39219
|
+
}
|
|
39220
|
+
var PoolMemoryWatchdog = class {
|
|
39221
|
+
pools = /* @__PURE__ */ new Map();
|
|
39222
|
+
timer = null;
|
|
39223
|
+
sweeping = false;
|
|
39224
|
+
stopped = false;
|
|
39225
|
+
opts;
|
|
39226
|
+
now;
|
|
39227
|
+
setTimer;
|
|
39228
|
+
clearTimer;
|
|
39229
|
+
constructor(opts) {
|
|
39230
|
+
this.opts = opts;
|
|
39231
|
+
this.now = opts.now ?? (() => Date.now());
|
|
39232
|
+
this.setTimer = opts.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
|
|
39233
|
+
this.clearTimer = opts.clearTimer ?? ((t) => clearTimeout(t));
|
|
39234
|
+
}
|
|
39235
|
+
start() {
|
|
39236
|
+
if (this.timer || this.stopped) return;
|
|
39237
|
+
this.arm();
|
|
39238
|
+
}
|
|
39239
|
+
stop() {
|
|
39240
|
+
this.stopped = true;
|
|
39241
|
+
if (this.timer) {
|
|
39242
|
+
this.clearTimer(this.timer);
|
|
39243
|
+
this.timer = null;
|
|
39244
|
+
}
|
|
39245
|
+
}
|
|
39246
|
+
arm() {
|
|
39247
|
+
const timer = this.setTimer(() => {
|
|
39248
|
+
this.sweep().finally(() => {
|
|
39249
|
+
if (!this.stopped) this.arm();
|
|
39250
|
+
});
|
|
39251
|
+
}, this.opts.policy.sampleIntervalMs);
|
|
39252
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
39253
|
+
this.timer = timer;
|
|
39254
|
+
}
|
|
39255
|
+
/** One sweep: sample → log every pool → restart at most one. Public so the
|
|
39256
|
+
* loop is testable without fake global timers. */
|
|
39257
|
+
async sweep() {
|
|
39258
|
+
if (this.sweeping) return;
|
|
39259
|
+
this.sweeping = true;
|
|
39260
|
+
try {
|
|
39261
|
+
await this.doSweep();
|
|
39262
|
+
} catch (err) {
|
|
39263
|
+
this.opts.log.warn("pool memory sweep failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
39264
|
+
} finally {
|
|
39265
|
+
this.sweeping = false;
|
|
39266
|
+
}
|
|
39267
|
+
}
|
|
39268
|
+
async doSweep() {
|
|
39269
|
+
const nowMs = this.now();
|
|
39270
|
+
const samples = await this.opts.sample();
|
|
39271
|
+
const candidates = [];
|
|
39272
|
+
const verdictByKey = /* @__PURE__ */ new Map();
|
|
39273
|
+
for (const t of samples) {
|
|
39274
|
+
const tracked = this.pools.get(t.key);
|
|
39275
|
+
let state = tracked?.state ?? initialPoolMemoryState();
|
|
39276
|
+
if (tracked && tracked.pids.length > 0 && !samePids(tracked.pids, t.pids)) {
|
|
39277
|
+
this.opts.log.warn("pool process changed outside the watchdog — re-baselining", { meta: {
|
|
39278
|
+
poolKey: t.key,
|
|
39279
|
+
previousPids: tracked.pids,
|
|
39280
|
+
pids: t.pids
|
|
39281
|
+
} });
|
|
39282
|
+
state = resetPoolBaseline(state);
|
|
39283
|
+
}
|
|
39284
|
+
const verdict = evaluatePoolMemory(state, t.rssBytes, nowMs, this.opts.policy);
|
|
39285
|
+
this.pools.set(t.key, {
|
|
39286
|
+
state: verdict.state,
|
|
39287
|
+
pids: t.pids
|
|
39288
|
+
});
|
|
39289
|
+
verdictByKey.set(t.key, verdict);
|
|
39290
|
+
this.opts.log.info("pool memory", { meta: {
|
|
39291
|
+
poolKey: t.key,
|
|
39292
|
+
pids: t.pids,
|
|
39293
|
+
rssMb: Math.round(t.rssBytes / MB),
|
|
39294
|
+
baselineMb: verdict.baselineBytes === null ? null : Math.round(verdict.baselineBytes / MB),
|
|
39295
|
+
thresholdMb: Math.round(verdict.thresholdBytes / MB),
|
|
39296
|
+
action: verdict.action,
|
|
39297
|
+
...t.meta
|
|
39298
|
+
} });
|
|
39299
|
+
if (verdict.action === "restart") candidates.push({
|
|
39300
|
+
key: t.key,
|
|
39301
|
+
rssBytes: t.rssBytes,
|
|
39302
|
+
thresholdBytes: verdict.thresholdBytes
|
|
39303
|
+
});
|
|
39304
|
+
else if (verdict.action === "cooldown") this.opts.log.warn("pool over memory threshold but inside restart cooldown", { meta: {
|
|
39305
|
+
poolKey: t.key,
|
|
39306
|
+
rssMb: Math.round(t.rssBytes / MB),
|
|
39307
|
+
thresholdMb: Math.round(verdict.thresholdBytes / MB),
|
|
39308
|
+
cooldownMs: this.opts.policy.cooldownMs
|
|
39309
|
+
} });
|
|
39310
|
+
else if (verdict.action === "exhausted") this.opts.log.error("pool memory watchdog gave up — restart budget exhausted, pool leaks faster than restarts can pay for; needs a heap profile (py-spy / tracemalloc)", { meta: {
|
|
39311
|
+
poolKey: t.key,
|
|
39312
|
+
rssMb: Math.round(t.rssBytes / MB),
|
|
39313
|
+
thresholdMb: Math.round(verdict.thresholdBytes / MB),
|
|
39314
|
+
maxRestartsPerWindow: this.opts.policy.maxRestartsPerWindow,
|
|
39315
|
+
restartWindowMs: this.opts.policy.restartWindowMs
|
|
39316
|
+
} });
|
|
39317
|
+
}
|
|
39318
|
+
for (const key of [...this.pools.keys()]) if (!samples.some((t) => t.key === key)) this.pools.delete(key);
|
|
39319
|
+
const pickedKey = pickRestartCandidate(candidates);
|
|
39320
|
+
if (pickedKey === null) return;
|
|
39321
|
+
const picked = candidates.find((c) => c.key === pickedKey);
|
|
39322
|
+
const verdict = verdictByKey.get(pickedKey);
|
|
39323
|
+
const tracked = this.pools.get(pickedKey);
|
|
39324
|
+
const restartsInWindow = tracked.state.restartsAt.length + 1;
|
|
39325
|
+
this.opts.log.warn("pool memory watchdog restarting pool — RSS over threshold", { meta: {
|
|
39326
|
+
poolKey: pickedKey,
|
|
39327
|
+
pids: tracked.pids,
|
|
39328
|
+
rssMb: Math.round(picked.rssBytes / MB),
|
|
39329
|
+
thresholdMb: Math.round(picked.thresholdBytes / MB),
|
|
39330
|
+
baselineMb: verdict.baselineBytes === null ? null : Math.round(verdict.baselineBytes / MB),
|
|
39331
|
+
restartsInWindow,
|
|
39332
|
+
deferredCandidates: candidates.filter((c) => c.key !== pickedKey).map((c) => c.key)
|
|
39333
|
+
} });
|
|
39334
|
+
try {
|
|
39335
|
+
await this.opts.restart(pickedKey);
|
|
39336
|
+
this.pools.set(pickedKey, {
|
|
39337
|
+
state: commitWatchdogRestart(tracked.state, this.now()),
|
|
39338
|
+
pids: []
|
|
39339
|
+
});
|
|
39340
|
+
} catch (err) {
|
|
39341
|
+
this.opts.log.error("pool memory watchdog restart failed", { meta: {
|
|
39342
|
+
poolKey: pickedKey,
|
|
39343
|
+
error: err instanceof Error ? err.message : String(err)
|
|
39344
|
+
} });
|
|
39345
|
+
}
|
|
39346
|
+
}
|
|
39347
|
+
};
|
|
39348
|
+
function samePids(a, b) {
|
|
39349
|
+
if (a.length !== b.length) return false;
|
|
39350
|
+
const sortedA = [...a].sort((x, y) => x - y);
|
|
39351
|
+
const sortedB = [...b].sort((x, y) => x - y);
|
|
39352
|
+
return sortedA.every((v, i) => v === sortedB[i]);
|
|
39353
|
+
}
|
|
39028
39354
|
/**
|
|
39029
39355
|
* Vector wire codec — base64 of little-endian Float32.
|
|
39030
39356
|
*
|
|
@@ -39234,6 +39560,12 @@ Object.defineProperty(exports, "OpsLogEntrySchema", {
|
|
|
39234
39560
|
return OpsLogEntrySchema;
|
|
39235
39561
|
}
|
|
39236
39562
|
});
|
|
39563
|
+
Object.defineProperty(exports, "PoolMemoryWatchdog", {
|
|
39564
|
+
enumerable: true,
|
|
39565
|
+
get: function() {
|
|
39566
|
+
return PoolMemoryWatchdog;
|
|
39567
|
+
}
|
|
39568
|
+
});
|
|
39237
39569
|
Object.defineProperty(exports, "RECORDING_EXPORT_MAX_READ_BYTES", {
|
|
39238
39570
|
enumerable: true,
|
|
39239
39571
|
get: function() {
|
|
@@ -39504,6 +39836,12 @@ Object.defineProperty(exports, "object", {
|
|
|
39504
39836
|
return object;
|
|
39505
39837
|
}
|
|
39506
39838
|
});
|
|
39839
|
+
Object.defineProperty(exports, "parseProcStatus", {
|
|
39840
|
+
enumerable: true,
|
|
39841
|
+
get: function() {
|
|
39842
|
+
return parseProcStatus;
|
|
39843
|
+
}
|
|
39844
|
+
});
|
|
39507
39845
|
Object.defineProperty(exports, "partialRecord", {
|
|
39508
39846
|
enumerable: true,
|
|
39509
39847
|
get: function() {
|
|
@@ -39540,6 +39878,12 @@ Object.defineProperty(exports, "record", {
|
|
|
39540
39878
|
return record;
|
|
39541
39879
|
}
|
|
39542
39880
|
});
|
|
39881
|
+
Object.defineProperty(exports, "resolvePoolMemoryPolicy", {
|
|
39882
|
+
enumerable: true,
|
|
39883
|
+
get: function() {
|
|
39884
|
+
return resolvePoolMemoryPolicy;
|
|
39885
|
+
}
|
|
39886
|
+
});
|
|
39543
39887
|
Object.defineProperty(exports, "sceneMonitorCapability", {
|
|
39544
39888
|
enumerable: true,
|
|
39545
39889
|
get: function() {
|