@camstack/system 1.2.238 → 1.2.240
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 +1 -1
- package/dist/addon-runner.mjs +1 -1
- 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 +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- 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 +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- 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-D5hpgLSL.mjs → dist-CDDG1zn3.mjs} +133 -1
- package/dist/{dist-CHclfj0J.js → dist-Dze0l7UM.js} +133 -1
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/kernel/moleculer/device-event-ring.d.ts +113 -0
- package/dist/kernel/moleculer/event-bus-core.d.ts +18 -0
- package/dist/{manifest-system-deps-BEj9Dpu1.mjs → manifest-system-deps-CfR7Z90J.mjs} +136 -2
- package/dist/{manifest-system-deps-CrSP0Kkp.js → manifest-system-deps-CzyjTMcO.js} +136 -2
- package/dist/{retired-settings-keys-DRKmYztE.js → retired-settings-keys-1GWw9mup.js} +1 -1
- package/dist/{retired-settings-keys-bJE3qjAT.mjs → retired-settings-keys-Cbt4-K_M.mjs} +1 -1
- package/package.json +2 -2
|
@@ -6974,6 +6974,137 @@ function getCapUsageRegistry() {
|
|
|
6974
6974
|
function __resetCapUsageRegistryForTests() {
|
|
6975
6975
|
singleton = null;
|
|
6976
6976
|
}
|
|
6977
|
+
var MIRROR_REASON_BY_CATEGORY = new Map([
|
|
6978
|
+
{
|
|
6979
|
+
category: "device.state-changed",
|
|
6980
|
+
reason: "Device runtime-state mirror, 69.1 % of fleet traffic. Each event is a snapshot of the slice AFTER the change; the superseded snapshot describes a state the device is no longer in, and every consumer (SystemMirror, DeviceStateHandle) reads the latest one only."
|
|
6981
|
+
},
|
|
6982
|
+
{
|
|
6983
|
+
category: "camera-streams.onCamStreamsChanged",
|
|
6984
|
+
reason: "Full stream-list snapshot per camera, 20.1 % of fleet traffic. The payload is the complete current list, not a delta, so an older list is strictly less true than the newer one."
|
|
6985
|
+
},
|
|
6986
|
+
{
|
|
6987
|
+
category: "system.ready-state",
|
|
6988
|
+
reason: "Readiness is a LEVEL, not an edge: the event reports whether a capability is ready right now. Declared for the case where it carries a deviceId; when it does not it stays in the global ring like any other unattributed event."
|
|
6989
|
+
}
|
|
6990
|
+
].map((m) => [m.category, m.reason]));
|
|
6991
|
+
/**
|
|
6992
|
+
* Is this category declared a mirror? An unclassified category is NOT a mirror
|
|
6993
|
+
* — the safe default is to keep its history.
|
|
6994
|
+
*/
|
|
6995
|
+
function isMirrorCategory(category) {
|
|
6996
|
+
return MIRROR_REASON_BY_CATEGORY.has(category);
|
|
6997
|
+
}
|
|
6998
|
+
/**
|
|
6999
|
+
* Non-mirror events retained per device. ~1.1 events/s fleet-wide after
|
|
7000
|
+
* coalescing ⇒ ~3 000/day/camera ⇒ 2 000 ≈ 16 h.
|
|
7001
|
+
*/
|
|
7002
|
+
var MAX_DEVICE_RING_EVENTS = 2e3;
|
|
7003
|
+
function serializePayload(data) {
|
|
7004
|
+
try {
|
|
7005
|
+
const json = JSON.stringify(data);
|
|
7006
|
+
if (typeof json !== "string") return null;
|
|
7007
|
+
return {
|
|
7008
|
+
json,
|
|
7009
|
+
bytes: Buffer.byteLength(json, "utf8")
|
|
7010
|
+
};
|
|
7011
|
+
} catch {
|
|
7012
|
+
return null;
|
|
7013
|
+
}
|
|
7014
|
+
}
|
|
7015
|
+
/**
|
|
7016
|
+
* The event as it should be RETAINED: unchanged when its payload is within the
|
|
7017
|
+
* cap, otherwise a NEW event whose `data` is the marked replacement. The
|
|
7018
|
+
* argument is never mutated — the same object is still live on the fan-out path
|
|
7019
|
+
* and in the global ring.
|
|
7020
|
+
*/
|
|
7021
|
+
function capEventData(event) {
|
|
7022
|
+
const serialized = serializePayload(event.data);
|
|
7023
|
+
if (serialized !== null && serialized.bytes <= 256) return event;
|
|
7024
|
+
const truncated = {
|
|
7025
|
+
__truncated: true,
|
|
7026
|
+
__originalBytes: serialized?.bytes ?? null,
|
|
7027
|
+
__preview: serialized === null ? "" : serialized.json.slice(0, 160)
|
|
7028
|
+
};
|
|
7029
|
+
return {
|
|
7030
|
+
...event,
|
|
7031
|
+
data: truncated
|
|
7032
|
+
};
|
|
7033
|
+
}
|
|
7034
|
+
/**
|
|
7035
|
+
* The device this event is about, or `undefined` when it is about no device.
|
|
7036
|
+
*
|
|
7037
|
+
* Same rule as `matchesEventFilter` — `source.deviceId`, or `source.id` when
|
|
7038
|
+
* the source IS a device — so a read filtered by `deviceId` and a read served
|
|
7039
|
+
* from that device's ring agree on which events belong to it. A non-numeric
|
|
7040
|
+
* device source id yields `undefined` rather than `NaN`: an unattributable
|
|
7041
|
+
* event must never become a bucket of its own.
|
|
7042
|
+
*/
|
|
7043
|
+
function eventDeviceId(event) {
|
|
7044
|
+
const explicit = event.source.deviceId;
|
|
7045
|
+
if (explicit !== void 0) return Number.isFinite(explicit) ? explicit : void 0;
|
|
7046
|
+
if (event.source.type !== "device") return void 0;
|
|
7047
|
+
const asNumber = Number(event.source.id);
|
|
7048
|
+
return Number.isFinite(asNumber) ? asNumber : void 0;
|
|
7049
|
+
}
|
|
7050
|
+
function createDeviceEventRings() {
|
|
7051
|
+
return { byDevice: /* @__PURE__ */ new Map() };
|
|
7052
|
+
}
|
|
7053
|
+
function ringFor(rings, deviceId) {
|
|
7054
|
+
const existing = rings.byDevice.get(deviceId);
|
|
7055
|
+
if (existing !== void 0) {
|
|
7056
|
+
rings.byDevice.delete(deviceId);
|
|
7057
|
+
rings.byDevice.set(deviceId, existing);
|
|
7058
|
+
return existing;
|
|
7059
|
+
}
|
|
7060
|
+
const created = {
|
|
7061
|
+
history: [],
|
|
7062
|
+
mirrors: /* @__PURE__ */ new Map()
|
|
7063
|
+
};
|
|
7064
|
+
rings.byDevice.set(deviceId, created);
|
|
7065
|
+
while (rings.byDevice.size > 512) {
|
|
7066
|
+
const oldest = rings.byDevice.keys().next();
|
|
7067
|
+
if (oldest.done === true) break;
|
|
7068
|
+
rings.byDevice.delete(oldest.value);
|
|
7069
|
+
}
|
|
7070
|
+
return created;
|
|
7071
|
+
}
|
|
7072
|
+
/**
|
|
7073
|
+
* Retain `event` in its device's ring, with its payload capped.
|
|
7074
|
+
*
|
|
7075
|
+
* Returns the device it was filed under, or `undefined` when the event names no
|
|
7076
|
+
* device — the caller has already retained it in the global ring and nothing
|
|
7077
|
+
* more happens here. No device is fabricated.
|
|
7078
|
+
*/
|
|
7079
|
+
function recordDeviceEvent(rings, event) {
|
|
7080
|
+
const deviceId = eventDeviceId(event);
|
|
7081
|
+
if (deviceId === void 0) return void 0;
|
|
7082
|
+
const ring = ringFor(rings, deviceId);
|
|
7083
|
+
const retained = capEventData(event);
|
|
7084
|
+
if (isMirrorCategory(event.category)) {
|
|
7085
|
+
ring.mirrors.set(event.category, retained);
|
|
7086
|
+
return deviceId;
|
|
7087
|
+
}
|
|
7088
|
+
ring.history.push(retained);
|
|
7089
|
+
if (ring.history.length > 2e3) ring.history.splice(0, ring.history.length - MAX_DEVICE_RING_EVENTS);
|
|
7090
|
+
return deviceId;
|
|
7091
|
+
}
|
|
7092
|
+
/**
|
|
7093
|
+
* Everything retained for one device, oldest first — history merged with the
|
|
7094
|
+
* current value of each mirror, ordered by timestamp so the caller's `-limit`
|
|
7095
|
+
* slice means the same thing it means on the global ring.
|
|
7096
|
+
*
|
|
7097
|
+
* An unknown device yields `[]`: unknown is the truth about a camera that has
|
|
7098
|
+
* emitted nothing since this process started.
|
|
7099
|
+
*/
|
|
7100
|
+
function getDeviceRecent(rings, deviceId) {
|
|
7101
|
+
const ring = rings.byDevice.get(deviceId);
|
|
7102
|
+
if (ring === void 0) return [];
|
|
7103
|
+
if (ring.mirrors.size === 0) return ring.history;
|
|
7104
|
+
const merged = [...ring.history, ...ring.mirrors.values()];
|
|
7105
|
+
merged.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
7106
|
+
return merged;
|
|
7107
|
+
}
|
|
6977
7108
|
//#endregion
|
|
6978
7109
|
//#region src/kernel/moleculer/event-bus-core.ts
|
|
6979
7110
|
/**
|
|
@@ -6985,6 +7116,7 @@ function createSharedBusState(retainRecent = false) {
|
|
|
6985
7116
|
return {
|
|
6986
7117
|
handlers: /* @__PURE__ */ new Map(),
|
|
6987
7118
|
recent: [],
|
|
7119
|
+
deviceRings: createDeviceEventRings(),
|
|
6988
7120
|
retainRecent
|
|
6989
7121
|
};
|
|
6990
7122
|
}
|
|
@@ -7168,6 +7300,7 @@ function deliverShared(state, event) {
|
|
|
7168
7300
|
if (state.retainRecent && !isHighFrequencyCategory(event.category)) {
|
|
7169
7301
|
state.recent.push(event);
|
|
7170
7302
|
if (state.recent.length > 1e3) state.recent.splice(0, state.recent.length - MAX_RECENT_EVENTS);
|
|
7303
|
+
recordDeviceEvent(state.deviceRings, event);
|
|
7171
7304
|
}
|
|
7172
7305
|
const delivered = /* @__PURE__ */ new Set();
|
|
7173
7306
|
for (const [pattern, set] of state.handlers) {
|
|
@@ -10133,14 +10266,15 @@ function getBrokerEventBus(broker, options) {
|
|
|
10133
10266
|
});
|
|
10134
10267
|
},
|
|
10135
10268
|
getRecent(filter, limit) {
|
|
10136
|
-
const
|
|
10269
|
+
const source = filter?.deviceId !== void 0 ? getDeviceRecent(state.deviceRings, filter.deviceId) : state.recent;
|
|
10270
|
+
const filtered = filter ? source.filter((e) => {
|
|
10137
10271
|
const cat = filter.category;
|
|
10138
10272
|
if (cat) {
|
|
10139
10273
|
const categories = typeof cat === "string" ? [cat] : Array.isArray(cat) ? cat : [];
|
|
10140
10274
|
if (categories.length > 0 && !categories.some((c) => matchesPattern(String(c), e.category))) return false;
|
|
10141
10275
|
}
|
|
10142
10276
|
return matchesEventFilter(e, filter);
|
|
10143
|
-
}) :
|
|
10277
|
+
}) : source;
|
|
10144
10278
|
return limit !== void 0 ? filtered.slice(-limit) : filtered;
|
|
10145
10279
|
}
|
|
10146
10280
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/system",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.240",
|
|
4
4
|
"description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -352,7 +352,7 @@
|
|
|
352
352
|
"typecheck": "tsc --noEmit",
|
|
353
353
|
"test": "vitest run",
|
|
354
354
|
"test:watch": "vitest",
|
|
355
|
-
"publish": "npm publish --access public"
|
|
355
|
+
"publish:npm": "npm publish --access public"
|
|
356
356
|
},
|
|
357
357
|
"dependencies": {
|
|
358
358
|
"@camstack/sdk": "*",
|