@camstack/system 1.2.151 → 1.2.154
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/addon-runner.js +14 -15
- package/dist/addon-runner.mjs +14 -14
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +3 -3
- package/dist/builtins/local-network/local-network.addon.mjs +3 -3
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/cgroup-memory.d.ts +193 -0
- package/dist/builtins/native-metrics/container-memory-series.d.ts +226 -0
- package/dist/builtins/native-metrics/native-metrics.addon.d.ts +26 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js +1536 -661
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1536 -660
- package/dist/builtins/platform-probe/index.js +3 -3
- package/dist/builtins/platform-probe/index.mjs +2 -2
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +2 -2
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +2 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-CImxMt5h.js → dist-BPlfW-CG.js} +96 -10
- package/dist/{dist-CbRciAbu.mjs → dist-D_NyUV6Y.mjs} +96 -10
- package/dist/index.d.ts +6 -2
- package/dist/index.js +24 -5
- package/dist/index.mjs +5 -5
- package/dist/kernel/event-plane-report.d.ts +202 -0
- package/dist/kernel/heap-spaces.d.ts +138 -0
- package/dist/kernel/heap-watch.d.ts +142 -5
- package/dist/kernel/index.d.ts +2 -0
- package/dist/kernel/transport/local-child-registry.d.ts +22 -0
- package/dist/{manifest-python-deps-DuQ3Uqoq.mjs → manifest-python-deps-BILJm2mI.mjs} +522 -15
- package/dist/{manifest-python-deps-BqWrDjSN.js → manifest-python-deps-COeSr7el.js} +636 -15
- package/dist/{retired-settings-keys-DhFPXIRD.mjs → retired-settings-keys-Bq1Tb84I.mjs} +1 -1
- package/dist/{retired-settings-keys-C7gLUS3x.js → retired-settings-keys-DBY6ebwV.js} +1 -1
- package/package.json +1 -1
- package/dist/{tls-u8QCJCFE.js → tls-BxQlomxd.js} +1 -1
- package/dist/{tls-CQhPGSJm.mjs → tls-DOTmtLCW.mjs} +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { EventPlaneReader } from './event-plane-report.js';
|
|
2
|
+
import { HeapSpaceReader } from './heap-spaces.js';
|
|
1
3
|
/**
|
|
2
4
|
* What hub-main calls itself in a `[mem]` line.
|
|
3
5
|
*
|
|
@@ -137,12 +139,95 @@ export declare const HEAP_RECLAIM_MIN_INTERVAL_MS = 120000;
|
|
|
137
139
|
* Six is 12 minutes of back-to-back passes: long enough that a genuine burst
|
|
138
140
|
* (which subsides) never reaches it, short enough that a process which has
|
|
139
141
|
* quietly made the stop-the-world part of its steady state is named within the
|
|
140
|
-
* quarter-hour.
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
142
|
+
* quarter-hour.
|
|
143
|
+
*
|
|
144
|
+
* ## Until 2026-08-29 this counter changed nothing, and that was the bug
|
|
145
|
+
*
|
|
146
|
+
* It used to WARN and leave the cadence alone — "the pass is load-bearing and
|
|
147
|
+
* keeps running". Then hub-main's first 25 minutes of telemetry arrived and
|
|
148
|
+
* showed what that costs. See {@link HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS}:
|
|
149
|
+
* the system already knew the difference between a rescue and a steady state
|
|
150
|
+
* and simply refused to act on it.
|
|
144
151
|
*/
|
|
145
152
|
export declare const RECLAIM_STEADY_STATE_PASSES = 6;
|
|
153
|
+
/**
|
|
154
|
+
* Floor on the pass once it has PROVEN it is steady state, not a rescue.
|
|
155
|
+
*
|
|
156
|
+
* ## Why `stranded` cannot discriminate on hub-main
|
|
157
|
+
*
|
|
158
|
+
* {@link strandedMb} is `rss − heapUsed − external`: everything the process
|
|
159
|
+
* holds that those two numbers do not name. That lumps together two things with
|
|
160
|
+
* opposite fixes —
|
|
161
|
+
*
|
|
162
|
+
* - V8 pages committed at a sawtooth peak, which `gc(last-resort)` RETURNS;
|
|
163
|
+
* - glibc arena memory already freed and never handed back, which **no V8
|
|
164
|
+
* flavor can reach** (nothing in this repository calls `malloc_trim`).
|
|
165
|
+
*
|
|
166
|
+
* {@link HEAP_RECLAIM_TRIGGER_MB} was calibrated against a hub-main whose strand
|
|
167
|
+
* was mostly the first kind, and a pass then took it back under the trigger. Once
|
|
168
|
+
* the second kind grows past 1024 MB the quantity can never fall back under it,
|
|
169
|
+
* and the gate degenerates. Measured on the live hub 2026-08-29, first 25
|
|
170
|
+
* minutes of hub-main telemetry ever collected:
|
|
171
|
+
*
|
|
172
|
+
* - `stranded` sat at **1031–2313 MB for the entire boot**, i.e.
|
|
173
|
+
* {@link shouldReclaim} never once said no. **What is written as a threshold
|
|
174
|
+
* is, on this process, an unconditional 120-second timer.**
|
|
175
|
+
* - Nine minutes out of nine that contained a reclaim show `loopMax` ≈ the
|
|
176
|
+
* reclaim's own duration (555–869 ms). Every minute without one is
|
|
177
|
+
* 107–435 ms. **The largest recurring event-loop stall on the process that
|
|
178
|
+
* mediates every cross-runner call is the memory patch it applies to itself.**
|
|
179
|
+
* - Each pass freed less than the last (1193 → 462 MB) while the post-pass RSS
|
|
180
|
+
* floor ratcheted **1940 → 3510 MB in fourteen minutes**, with `heapUsed`
|
|
181
|
+
* never moving. It is compacting a heap that is not the problem.
|
|
182
|
+
*
|
|
183
|
+
* ## The fix is not a bigger trigger
|
|
184
|
+
*
|
|
185
|
+
* Raising {@link HEAP_RECLAIM_TRIGGER_MB} would move the number at which the same
|
|
186
|
+
* degeneration happens, and it would silence `hub/recorder` — whose single pass
|
|
187
|
+
* in six hours is the only cheap proof anyone has that the recorder's 1.4 GB is
|
|
188
|
+
* RETAINED (a forced compaction freed 507 MB and V8 still held 1.44 GB live).
|
|
189
|
+
* The discriminator is not the level of the strand; it is **whether the strand
|
|
190
|
+
* ever falls back under the trigger between passes**, which is precisely what
|
|
191
|
+
* {@link RECLAIM_STEADY_STATE_PASSES} already counts and used only to talk about.
|
|
192
|
+
*
|
|
193
|
+
* So the counter becomes load-bearing: once the pass has fired at the floor
|
|
194
|
+
* {@link RECLAIM_STEADY_STATE_PASSES} times running, the trigger has demonstrably
|
|
195
|
+
* stopped discriminating on this process, and the cadence falls back to a period
|
|
196
|
+
* chosen for its COST rather than to a threshold pretending to be a gate.
|
|
197
|
+
*
|
|
198
|
+
* ## Why 600_000, and why that is not a regression
|
|
199
|
+
*
|
|
200
|
+
* It is the value {@link HEAP_RECLAIM_MIN_INTERVAL_MS} held before 2026-08-17,
|
|
201
|
+
* and the reason it came down is recorded there: *"the ten-minute floor let a
|
|
202
|
+
* peak that re-formed in seconds stand for ten minutes"*. That argument is about
|
|
203
|
+
* a BURST — and a burst subsides, which resets the run and restores the 120 s
|
|
204
|
+
* floor. It never applied to a process in proven steady state. So the burst
|
|
205
|
+
* bound is untouched and the steady state gets the period the burst argument was
|
|
206
|
+
* never about.
|
|
207
|
+
*
|
|
208
|
+
* ## What each process does after this change
|
|
209
|
+
*
|
|
210
|
+
* - **hub-main**: first six passes at 120 s, unchanged. From the seventh
|
|
211
|
+
* consecutive floor-to-floor pass, every 600 s. Stop-the-world cost on the
|
|
212
|
+
* router falls from ~0.58% of wall clock to ~0.12%. The ArrayBuffer probe
|
|
213
|
+
* survives at six passes an hour — the finding it produced needed ten passes
|
|
214
|
+
* total, not ten in twenty-five minutes.
|
|
215
|
+
* - **`hub/recorder`**: zero change, by construction. `passesAtFloor` only
|
|
216
|
+
* increments when a pass fires within `minIntervalMs * 2` of the previous
|
|
217
|
+
* one; the recorder's strand takes six hours to re-form, so the counter is
|
|
218
|
+
* reset to 1 on every pass and can never reach six. The 507 MB probe is
|
|
219
|
+
* intact.
|
|
220
|
+
* - **Anything that recovers**: the run resets the moment the strand falls back
|
|
221
|
+
* under the trigger, and the 120 s floor returns with it.
|
|
222
|
+
*/
|
|
223
|
+
export declare const HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS = 600000;
|
|
224
|
+
/**
|
|
225
|
+
* The floor in force for the NEXT pass, given how many have fired at the floor.
|
|
226
|
+
*
|
|
227
|
+
* Pure, so the cadence change is testable without stranding a gigabyte to reach
|
|
228
|
+
* it — and so the one place that decides it can be read on its own.
|
|
229
|
+
*/
|
|
230
|
+
export declare function reclaimIntervalMs(passesAtFloor: number, minIntervalMs?: number, steadyStateIntervalMs?: number, steadyStatePasses?: number): number;
|
|
146
231
|
/**
|
|
147
232
|
* Event-loop delay over the window since the previous read, in milliseconds.
|
|
148
233
|
*
|
|
@@ -181,6 +266,37 @@ export interface LoopDelayMeter {
|
|
|
181
266
|
* naively would print `loopMax=9223372036854ms` and be read as a catastrophe on
|
|
182
267
|
* every boot. `count === 0` short-circuits to {@link ZERO_LOOP_DELAY}.
|
|
183
268
|
*
|
|
269
|
+
* ## `loopP50=20ms` was the SAMPLER, not the loop (fixed 2026-08-29)
|
|
270
|
+
*
|
|
271
|
+
* `monitorEventLoopDelay` records the whole INTERVAL between its own timer
|
|
272
|
+
* firings, not the excess over the interval it asked for. So on a loop with
|
|
273
|
+
* nothing wrong the histogram reads `resolution`, and every `[mem]` line this
|
|
274
|
+
* process has ever emitted said `loopP50=20ms` — which was read, repeatedly in
|
|
275
|
+
* one session, as "hub-main is chronically 20 ms behind". It is not; 20 was the
|
|
276
|
+
* default `resolutionMs` of this very function.
|
|
277
|
+
*
|
|
278
|
+
* The delay is `interval − resolution`, and that is not a fudge factor — it is
|
|
279
|
+
* the only reading the four resolutions agree on. Measured here, one 120 ms
|
|
280
|
+
* block observed by four histograms at once:
|
|
281
|
+
*
|
|
282
|
+
* | resolution | raw p50 | raw max | max − resolution |
|
|
283
|
+
* | --- | --- | --- | --- |
|
|
284
|
+
* | 20 ms | 20.40 ms | 137.63 ms | 117.6 ms |
|
|
285
|
+
* | 10 ms | 10.22 ms | 123.60 ms | 113.6 ms |
|
|
286
|
+
* | 5 ms | 5.11 ms | 123.60 ms | 118.6 ms |
|
|
287
|
+
* | 1 ms | 1.27 ms | 121.04 ms | 120.0 ms |
|
|
288
|
+
*
|
|
289
|
+
* Raw, the four disagree by 16 ms about the same event and none of them reports
|
|
290
|
+
* the block. Corrected, they agree within 7 ms and all four name it. The
|
|
291
|
+
* subtraction costs nothing and needs no faster sampler — a 1 ms resolution
|
|
292
|
+
* would be 1 000 extra timer wakeups per second on the process that already
|
|
293
|
+
* serves ~44 000 socket operations per second, to buy 2 ms of accuracy on a
|
|
294
|
+
* quantity nobody reads below 100 ms.
|
|
295
|
+
*
|
|
296
|
+
* **Readings from before this change are 20 ms high.** `loopP99=21–28ms` in the
|
|
297
|
+
* 2026-08-29 census is really 1–8 ms; `loopMax=2804ms` is really 2784 ms. Do not
|
|
298
|
+
* compare a pre-fix series with a post-fix one without shifting it.
|
|
299
|
+
*
|
|
184
300
|
* Returns undefined if the platform declines, so the caller keeps a heartbeat
|
|
185
301
|
* either way.
|
|
186
302
|
*/
|
|
@@ -396,6 +512,9 @@ export interface HeapReclaimOptions {
|
|
|
396
512
|
readonly heapLimitBytes?: number;
|
|
397
513
|
readonly triggerMb?: number;
|
|
398
514
|
readonly minIntervalMs?: number;
|
|
515
|
+
/** Floor once the pass is proven steady state. See
|
|
516
|
+
* {@link HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS}. */
|
|
517
|
+
readonly steadyStateIntervalMs?: number;
|
|
399
518
|
readonly now?: () => number;
|
|
400
519
|
/** Sampling cadence once escalated. See {@link HEAP_WATCH_FAST_INTERVAL_MS}. */
|
|
401
520
|
readonly fastIntervalMs?: number;
|
|
@@ -462,13 +581,31 @@ export interface RssBudgetOptions {
|
|
|
462
581
|
/** See {@link RSS_BUDGET_REANNOUNCE_MIN_MS}. */
|
|
463
582
|
readonly reannounceMinMs?: number;
|
|
464
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* The optional per-line probes.
|
|
586
|
+
*
|
|
587
|
+
* An OBJECT rather than two more positional parameters: `startHeapWatch` already
|
|
588
|
+
* takes eight, and a ninth and tenth `undefined` at a call site is how a caller
|
|
589
|
+
* ends up passing the loop meter into the space reader. Every field is optional,
|
|
590
|
+
* so a caller that wants neither passes nothing.
|
|
591
|
+
*/
|
|
592
|
+
export interface HeapWatchProbes {
|
|
593
|
+
/** Per-V8-space breakdown. Defaults to the real reader. */
|
|
594
|
+
readonly readSpaces?: HeapSpaceReader;
|
|
595
|
+
/**
|
|
596
|
+
* UDS + cross-node event fan-out. No default: a forked runner has no child
|
|
597
|
+
* registry, and printing zeros for a plane that does not exist is worse than
|
|
598
|
+
* printing nothing. Only hub-main and an agent's main pass one.
|
|
599
|
+
*/
|
|
600
|
+
readonly eventPlane?: EventPlaneReader;
|
|
601
|
+
}
|
|
465
602
|
/**
|
|
466
603
|
* Start the heartbeat. Returns a stop function.
|
|
467
604
|
*
|
|
468
605
|
* `unref`ed so it can never hold the process open, and every read is wrapped:
|
|
469
606
|
* a diagnostic that can crash the process it watches is worse than none.
|
|
470
607
|
*/
|
|
471
|
-
export declare function startHeapWatch(label?: string, sink?: HeapWatchSink, intervalMs?: number, reclaimOptions?: HeapReclaimOptions, loopDelay?: LoopDelayMeter | undefined, execArgv?: readonly string[], announceCeilingOrigin?: boolean, rssBudget?: RssBudgetOptions): () => void;
|
|
608
|
+
export declare function startHeapWatch(label?: string, sink?: HeapWatchSink, intervalMs?: number, reclaimOptions?: HeapReclaimOptions, loopDelay?: LoopDelayMeter | undefined, execArgv?: readonly string[], announceCeilingOrigin?: boolean, rssBudget?: RssBudgetOptions, probes?: HeapWatchProbes): () => void;
|
|
472
609
|
/**
|
|
473
610
|
* Steady heartbeat period for a HEAVY addon runner.
|
|
474
611
|
*
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export { createCoreCapService, CORE_CAP_SERVICE_NAME } from './moleculer/core-ca
|
|
|
40
40
|
export type { CoreCapAction, CoreCapCallOrigin, CoreCapServiceOptions, } from './moleculer/core-cap-service.js';
|
|
41
41
|
export { createAddonContext, createUdsAddonContext, setHubConnected, adaptBrokerToCluster, registerEventBusService, setNodeEventInterest, getMoleculerEventStats, subscribePassthrough, getBrokerEventBus, clusterEventTopic, EVENT_TOPIC_PREFIX, } from './moleculer/addon-context-factory.js';
|
|
42
42
|
export type { MoleculerEventStats } from './moleculer/addon-context-factory.js';
|
|
43
|
+
export type { MoleculerEventFanoutMode } from './moleculer/event-bus-core.js';
|
|
44
|
+
export { readMoleculerFanoutMode } from './moleculer/event-bus-core.js';
|
|
43
45
|
export { HubLogForwarder } from './moleculer/hub-log-forwarder.js';
|
|
44
46
|
export type { AddonContextOptions } from './moleculer/addon-context-factory.js';
|
|
45
47
|
export { createHubService } from './moleculer/hub-service.js';
|
|
@@ -183,6 +183,28 @@ export declare class LocalChildRegistry {
|
|
|
183
183
|
* surface (shadow burn-in + operator debug).
|
|
184
184
|
*/
|
|
185
185
|
getChildEventStats(childId: string): ChildEventStats | null;
|
|
186
|
+
/**
|
|
187
|
+
* The regime the counters above were produced under, read once from
|
|
188
|
+
* `CAMSTACK_UDS_EVENT_FANOUT` at construction.
|
|
189
|
+
*
|
|
190
|
+
* A suppressed count means "nothing WAS dropped" under `filter` and "nothing
|
|
191
|
+
* WOULD have been dropped" under `shadow`. Those are different claims, and
|
|
192
|
+
* until this getter existed the mode was invisible at runtime — the counters
|
|
193
|
+
* were readable and the regime that produced them was not.
|
|
194
|
+
*/
|
|
195
|
+
get eventFanoutMode(): UdsEventFanoutMode;
|
|
196
|
+
/**
|
|
197
|
+
* Connected children that never declared a subscription pattern set.
|
|
198
|
+
*
|
|
199
|
+
* Each one is a fail-open on BOTH planes: `childWantsEvent` returns true for
|
|
200
|
+
* an undeclared child ({@link ChildEntry.eventPatterns} `=== null`), and
|
|
201
|
+
* `aggregateEventInterest` returns `null` — accept everything — if ANY
|
|
202
|
+
* connected child is undeclared, which disables the node's inbound cross-node
|
|
203
|
+
* gate as well. **One legacy runner silently turns off the filtering for the
|
|
204
|
+
* whole node**, and nothing reported it, so a zero here is as load-bearing as
|
|
205
|
+
* a non-zero one.
|
|
206
|
+
*/
|
|
207
|
+
undeclaredChildCount(): number;
|
|
186
208
|
/**
|
|
187
209
|
* Does `entry` want to receive an event in `category`? Honours the fan-out
|
|
188
210
|
* mode: `broadcast` → always; undeclared patterns (`null`) → always
|