@camstack/addon-pipeline 1.2.100 → 1.2.101

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.
@@ -1,6 +1,7 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "../chunk-DnnnRqeS.mjs";
2
2
  import { A as cameraStreamsCapability, At as boolean, B as egressTransportFromRequest, Ct as nodePin, E as addonWidgetsSourceCapability, F as deriveBatteryPresence, Ft as object, G as maskUrlCredentials, It as record, Lt as string, Nt as literal, Ot as _enum, Pt as number, Rt as union, St as makeSourceBrokerId, Tt as parseProfileBrokerId, _t as DeviceType, at as streamBrokerCapability, b as RATE_CONTROL_RELAXED, bt as isEvent, ct as errMsg, dt as buildFfmpegArgs$1, et as resolveEgressDecodeHwAccel, ft as invocationFromEncodeProfile, gt as DeviceFeature, ht as CAM_PROFILE_ORDER, i as BatteryStatusSchema, j as createHwAccelCache, jt as discriminatedUnion, k as batteryCapability, kt as array, lt as AUDIO_PRESETS, mt as BaseAddon, p as EncodeProfileSchema, pt as isSoftwareDecode, st as webrtcSessionCapability, ut as Fmp4BoxSplitter, vt as createEvent, w as RingBuffer, x as RATE_CONTROL_TIGHT, xt as makeProfileBrokerId, z as egressTranscodeSharingKey, zt as EventCategory } from "../dist-gXdWP96z.mjs";
3
3
  import { n as profileForStreamId, r as parseRestreamPath } from "../remote-restream-Ci7RXNGb.mjs";
4
+ import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DMolfhsP.mjs";
4
5
  import { createRequire } from "node:module";
5
6
  import * as crypto$1 from "node:crypto";
6
7
  import crypto, { createHash, randomBytes, randomUUID } from "node:crypto";
@@ -112,8 +113,9 @@ function createClientLogIngest(onEntries) {
112
113
  */
113
114
  /**
114
115
  * Last-observed runtime probe (present only after the stream was pulled once).
115
- * Zod-backed because it is persisted durably (per-broker) so the field stays
116
- * populated across a hub restart — the schema is the single source of truth.
116
+ * Zod-backed because it is persisted durably (ONE ROW per broker in
117
+ * `stream-broker:probe-snapshots`) so the field stays populated across a hub
118
+ * restart — the schema is the single source of truth, applied per row.
117
119
  */
118
120
  var ProbedSnapshotSchema = object({
119
121
  /** Detected video codec — preferred over the declared one when present. */
@@ -129,8 +131,7 @@ var ProbedSnapshotSchema = object({
129
131
  /** Epoch ms the snapshot was captured. */
130
132
  at: number()
131
133
  });
132
- /** Durable map keyed by `brokerIdFor(deviceId, camStreamId)`. */
133
- var ProbedSnapshotMapSchema = record(string(), ProbedSnapshotSchema);
134
+ record(string(), ProbedSnapshotSchema);
134
135
  var SEP = " · ";
135
136
  function formatCodec(codec) {
136
137
  const lower = codec.toLowerCase();
@@ -179,6 +180,208 @@ function formatProbedSummary(declared, snapshot, opts) {
179
180
  return parts.join(SEP);
180
181
  }
181
182
  //#endregion
183
+ //#region src/stream-broker/broker-row-stores.ts
184
+ /**
185
+ * The stream-broker's flattened settings maps — one row per entry.
186
+ *
187
+ * ## What this replaced
188
+ *
189
+ * `stream-broker:addon-settings` / `root` was 33 155 bytes on the reference
190
+ * hub, and three keys were 32 735 of it: `probeSnapshots` (17 282 B, 109
191
+ * streams), `rtspTokens` (13 147 B, 243 streams) and `profileMap` (2 306 B, 29
192
+ * cameras — a per-DEVICE map, so it grows with the fleet). Every read of that
193
+ * row parsed all of it, including `BaseAddon.resolveConfig`, and every write
194
+ * rewrote all of it — a probe flush every few seconds while streams are live.
195
+ *
196
+ * Two keys deliberately STAY blob keys on that row, and the reasons are not
197
+ * "they are small":
198
+ *
199
+ * - `rtspEnabled` — brokerId → boolean, EMPTY on the reference hub. Its
200
+ * persister replaces the whole map from the set of registered restreamers,
201
+ * and reproducing that on rows means an authoritative prune. A prune driven
202
+ * by a map that shrinks whenever a broker unregisters is exactly the shape
203
+ * that turns an unbind into a wipe (D130, D49), and the twin key
204
+ * `rtspTokens` carries a comment about precisely that loss. Nothing is
205
+ * bought by moving 0 bytes at that risk.
206
+ * - `deviceOverrides` — 354 B, two cameras, same replace-the-whole-map
207
+ * persister, written only when an operator edits an override.
208
+ *
209
+ * The row survives either way: it is also where `BaseAddon.resolveConfig` reads
210
+ * the operator's config fields from. The problem was a 33 KB row, not a blob.
211
+ */
212
+ /**
213
+ * The addon id — the settings-store namespace whose `root` row the flattened
214
+ * keys are being retired from. Matches `packages/addon-pipeline/package.json`
215
+ * (`camstack.addons[].id`).
216
+ */
217
+ var STREAM_BROKER_ADDON_ID = "stream-broker";
218
+ /**
219
+ * Every one of these collections is keyed by the BROKER ID
220
+ * (`<deviceId>/<camStreamId>`) or by the numeric deviceId. `brokerDeviceId`
221
+ * recovers the numeric device from either, for the projected column that makes
222
+ * a per-camera question an indexed query — and for `tags: { deviceId }` on
223
+ * every line these stores log.
224
+ *
225
+ * Returns `null` rather than guessing: a key whose head is not a number is a
226
+ * key this addon did not write, and inventing a device for it would put a row
227
+ * on a camera at random.
228
+ */
229
+ function brokerDeviceId(key) {
230
+ const head = key.includes("/") ? key.slice(0, key.indexOf("/")) : key;
231
+ const id = Number(head);
232
+ return Number.isInteger(id) && id > 0 ? id : null;
233
+ }
234
+ /**
235
+ * Bound for a whole-map read. `settings-store.query` silently caps an unbounded
236
+ * read at 2 000 rows and answers as if that were everything; at 974 devices ×
237
+ * up to 5 streams the default is HALF the margin, so every read here names its
238
+ * own ceiling and a truncation is reported rather than shrunk.
239
+ */
240
+ var BROKER_ROWS_LIMIT = 2e4;
241
+ /**
242
+ * @durable class=mirror owner=stream-broker
243
+ * write="one row per broker (`<deviceId>/<camStreamId>`), replaced wholesale from the
244
+ * manager's live probe map by the throttled metrics flush and once on shutdown"
245
+ * retention="the flush is authoritative: a broker the manager no longer holds loses its
246
+ * row. Losing the whole collection costs the settings 'Probed' field showing 'not yet
247
+ * probed' until the stream is pulled again — it is re-derived from the next probe."
248
+ */
249
+ var BROKER_PROBE_SNAPSHOTS_COLLECTION = "stream-broker:probe-snapshots";
250
+ var BROKER_PROBE_SNAPSHOTS_SPEC = {
251
+ collection: BROKER_PROBE_SNAPSHOTS_COLLECTION,
252
+ schema: ProbedSnapshotSchema,
253
+ columns: [{
254
+ name: "deviceId",
255
+ type: "INTEGER"
256
+ }, {
257
+ name: "at",
258
+ type: "INTEGER",
259
+ notNull: true
260
+ }],
261
+ indexes: [{
262
+ name: "idx_stream_broker_probe_device",
263
+ columns: ["deviceId"]
264
+ }],
265
+ project: (key, value) => ({
266
+ deviceId: brokerDeviceId(key),
267
+ at: value.at
268
+ }),
269
+ deviceIdColumn: "deviceId",
270
+ loadLimit: BROKER_ROWS_LIMIT
271
+ };
272
+ function probeSnapshotsStore(store, logger) {
273
+ return new RowMapStore({
274
+ spec: BROKER_PROBE_SNAPSHOTS_SPEC,
275
+ store,
276
+ logger
277
+ });
278
+ }
279
+ /**
280
+ * The token, wrapped in an object rather than stored bare.
281
+ *
282
+ * A bare string in a `JSON` column round-trips only because the engine's
283
+ * decoder JSON-parses a stored string ONLY when it starts with `{` or `[`. That
284
+ * is a heuristic, not a contract; a token is opaque hex today and a future
285
+ * format that starts with a brace would come back as an object. One field costs
286
+ * nothing and makes the row self-describing.
287
+ */
288
+ var RtspTokenRowSchema = object({ token: string().min(1) });
289
+ /**
290
+ * @durable class=ledger owner=stream-broker
291
+ * write="one row per broker (`<deviceId>/<camStreamId>`), upserted when the restream
292
+ * server mints a token. MERGE only — a token is stable forever per stream unless it
293
+ * is explicitly regenerated"
294
+ * retention="nothing deletes a row. The persister receives only the CURRENTLY registered
295
+ * restreamers, so a replace would erase the token of an unregistered broker and turn
296
+ * an external NVR URL into a dead 404 at the next idle or reboot."
297
+ */
298
+ var BROKER_RTSP_TOKENS_COLLECTION = "stream-broker:rtsp-tokens";
299
+ var BROKER_RTSP_TOKENS_SPEC = {
300
+ collection: BROKER_RTSP_TOKENS_COLLECTION,
301
+ schema: RtspTokenRowSchema,
302
+ columns: [{
303
+ name: "deviceId",
304
+ type: "INTEGER"
305
+ }],
306
+ indexes: [{
307
+ name: "idx_stream_broker_rtsp_tokens_device",
308
+ columns: ["deviceId"]
309
+ }],
310
+ project: (key) => ({ deviceId: brokerDeviceId(key) }),
311
+ deviceIdColumn: "deviceId",
312
+ loadLimit: BROKER_ROWS_LIMIT
313
+ };
314
+ function rtspTokensStore(store, logger) {
315
+ return new RowMapStore({
316
+ spec: BROKER_RTSP_TOKENS_SPEC,
317
+ store,
318
+ logger
319
+ });
320
+ }
321
+ /** One camera's profile → camStreamId assignment, plus whether it is automatic. */
322
+ var ProfileAssignmentSchema = object({
323
+ map: record(string(), string()),
324
+ auto: boolean()
325
+ });
326
+ /**
327
+ * @durable class=config owner=stream-broker
328
+ * write="one row per camera, replaced wholesale from the manager's assignment map on
329
+ * every profile mutation — the map is authoritative and its boot pass PRUNES cameras
330
+ * the device registry no longer knows, which is why the write is a replace and not
331
+ * an upsert"
332
+ * retention="the replace is the retention: a camera dropped from the manager's map loses
333
+ * its row. Losing a row costs one automatic re-assignment on the next catalog pull."
334
+ */
335
+ var BROKER_PROFILE_MAP_COLLECTION = "stream-broker:profile-map";
336
+ var BROKER_PROFILE_MAP_SPEC = {
337
+ collection: BROKER_PROFILE_MAP_COLLECTION,
338
+ schema: ProfileAssignmentSchema,
339
+ columns: [{
340
+ name: "deviceId",
341
+ type: "INTEGER",
342
+ notNull: true
343
+ }, {
344
+ name: "auto",
345
+ type: "BOOLEAN",
346
+ notNull: true
347
+ }],
348
+ project: (key, value) => ({
349
+ deviceId: Number(key),
350
+ auto: value.auto
351
+ }),
352
+ deviceIdColumn: "deviceId",
353
+ loadLimit: BROKER_ROWS_LIMIT
354
+ };
355
+ function profileMapStore(store, logger) {
356
+ return new RowMapStore({
357
+ spec: BROKER_PROFILE_MAP_SPEC,
358
+ store,
359
+ logger
360
+ });
361
+ }
362
+ /**
363
+ * The dead `addon-settings` / `root` keys. A CLAIM that each key is dead,
364
+ * enforced by nothing else — the migration script names the same three, keep
365
+ * the two in lockstep.
366
+ */
367
+ var STREAM_BROKER_RETIRED_ROOT_KEYS = [
368
+ {
369
+ key: "probeSnapshots",
370
+ successor: BROKER_PROBE_SNAPSHOTS_COLLECTION,
371
+ reason: "one row per broker since the flatten; as a blob it was 17 KB of the 33 KB root row, rewritten whole by the throttled metrics flush"
372
+ },
373
+ {
374
+ key: "rtspTokens",
375
+ successor: BROKER_RTSP_TOKENS_COLLECTION,
376
+ reason: "one row per broker since the flatten; as a blob a single minted token rewrote 33 KB"
377
+ },
378
+ {
379
+ key: "profileMap",
380
+ successor: BROKER_PROFILE_MAP_COLLECTION,
381
+ reason: "one row per camera since the flatten; a per-DEVICE map, so as a blob it grew with the fleet — 2.3 KB at 29 cameras, ~77 KB at 974"
382
+ }
383
+ ];
384
+ //#endregion
182
385
  //#region src/stream-broker/battery-wake-on-play.ts
183
386
  /**
184
387
  * Wake-on-play — pressing play on a sleeping battery camera wakes it, and the
@@ -14190,15 +14393,18 @@ function readDeclaredAudioEnabled(v) {
14190
14393
  /** Whole-blob schema for the persisted `deviceOverrides` store key:
14191
14394
  * numeric-string deviceId → DeviceOverride (includes `derivedStreams`). */
14192
14395
  var DeviceOverridesMapSchema = record(string(), DeviceOverrideSchema);
14193
- /** Persisted store-key schemas for the broker's other durable blobs.
14194
- * `rtspTokens`: camStreamKey token hex. `rtspEnabled`: brokerId →
14195
- * enabled. `profileMap`: numeric-string deviceId {map, auto}. */
14196
- var RtspTokensSchema = record(string(), string());
14396
+ /**
14397
+ * The one persisted store KEY the broker still keeps as a blob: `rtspEnabled`,
14398
+ * brokerIdenabled.
14399
+ *
14400
+ * `rtspTokens` and `profileMap` moved to their own collections in the
14401
+ * 2026-08-19 flatten and their whole-blob schemas are gone with them — the row
14402
+ * shapes live in `broker-row-stores.ts`. `rtspEnabled` stayed, and why is
14403
+ * argued in that file's header: its persister replaces the map from the set of
14404
+ * CURRENTLY registered restreamers, and reproducing that on rows would mean a
14405
+ * prune driven by a map that shrinks on every unregister.
14406
+ */
14197
14407
  var RtspEnabledSchema = record(string(), boolean());
14198
- var ProfileMapSchema = record(string(), object({
14199
- map: record(string(), string()),
14200
- auto: boolean()
14201
- }));
14202
14408
  var PUSH_KINDS = new Set(["push-annexb"]);
14203
14409
  /** Walk a profile map and return the slot that points at `camStreamId`, or null. */
14204
14410
  function findProfileForStream(map, camStreamId) {
@@ -34944,14 +35150,16 @@ var EventLoopStallMonitor = class {
34944
35150
  //#endregion
34945
35151
  //#region src/stream-broker/addon.ts
34946
35152
  /**
34947
- * Hydrate the persisted RTSP restream state (`rtspTokens` / `rtspEnabled`)
34948
- * through the durable `state()` handles the sanctioned settings accessor
34949
- * instead of a raw `readAddonStore()`. Same store keys, same persisted
34950
- * shapes; a corrupt blob falls back to empty (durable-state semantics) and
34951
- * absent keys keep first-boot silence (no loader call, no log).
35153
+ * Hydrate the persisted RTSP restream state. Tokens come from their own
35154
+ * collection (one row per broker); `rtspEnabled` is still a key of the settings
35155
+ * row. An unparseable token row is skipped by the store — one dead token, not
35156
+ * every token and an empty set keeps first-boot silence (no loader call, no
35157
+ * log).
34952
35158
  */
34953
35159
  async function hydratePersistedRtspState(deps) {
34954
- const tokens = new Map(Object.entries(await deps.tokensState.get()));
35160
+ const rows = await deps.tokensStore.readAll();
35161
+ const tokens = /* @__PURE__ */ new Map();
35162
+ for (const [brokerId, row] of rows) tokens.set(brokerId, row.token);
34955
35163
  if (tokens.size > 0) {
34956
35164
  deps.loadTokens(tokens);
34957
35165
  deps.logger.info("Loaded persisted RTSP tokens", { meta: { tokenCount: tokens.size } });
@@ -35053,7 +35261,7 @@ var StreamBrokerAddon = class extends BaseAddon {
35053
35261
  /** Durable per-stream probe map (powers the settings "Probed" field across
35054
35262
  * restarts). Loaded on activate, flushed throttled from the metrics loop and
35055
35263
  * once on shutdown. */
35056
- probeSnapshotsState = null;
35264
+ probeSnapshots = null;
35057
35265
  lastProbePersistAt = 0;
35058
35266
  constructor() {
35059
35267
  super({
@@ -35129,13 +35337,15 @@ var StreamBrokerAddon = class extends BaseAddon {
35129
35337
  const localNodeId = localNode ? localNode.includes("/") ? localNode.split("/")[0] : localNode : void 0;
35130
35338
  this.brokerManager.setApiAccess(this.ctx.api, localNodeId, this.ctx.kernel.hwaccel);
35131
35339
  await this.loadFfmpegConfig();
35340
+ await this.declareRowCollections();
35341
+ await this.purgeFlattenedSettingsKeys();
35132
35342
  const rtspProvider = this.brokerManager.getRtspRestreamProvider();
35133
35343
  const brokerManager = this.brokerManager;
35134
- const rtspTokensState = this.state("rtspTokens", RtspTokensSchema, {});
35344
+ const rtspTokens = rtspTokensStore(this.ctx.api.settingsStore, this.ctx.logger);
35135
35345
  const rtspEnabledState = this.state("rtspEnabled", RtspEnabledSchema, {});
35136
35346
  try {
35137
35347
  await hydratePersistedRtspState({
35138
- tokensState: rtspTokensState,
35348
+ tokensStore: rtspTokens,
35139
35349
  enabledState: rtspEnabledState,
35140
35350
  loadTokens: (tokens) => brokerManager.loadPersistedTokens(tokens),
35141
35351
  loadEnabled: (states) => rtspProvider.loadPersistedEnabled(states),
@@ -35144,11 +35354,7 @@ var StreamBrokerAddon = class extends BaseAddon {
35144
35354
  } catch {}
35145
35355
  rtspProvider.setTokenPersister(async (tokens) => {
35146
35356
  try {
35147
- await rtspTokensState.update((prev) => {
35148
- const merged = { ...prev };
35149
- for (const [k, v] of tokens) merged[k] = v;
35150
- return merged;
35151
- });
35357
+ for (const [brokerId, token] of tokens) await rtspTokens.write(brokerId, { token });
35152
35358
  this.ctx.logger.info("Persisted RTSP tokens", { meta: { current: tokens.size } });
35153
35359
  } catch (err) {
35154
35360
  this.ctx.logger.warn("Failed to persist RTSP tokens", { meta: { error: errMsg(err) } });
@@ -35181,22 +35387,22 @@ var StreamBrokerAddon = class extends BaseAddon {
35181
35387
  this.ctx.logger.warn("Failed to persist device overrides", { meta: { error: errMsg(err) } });
35182
35388
  });
35183
35389
  });
35184
- const profileMapState = this.state("profileMap", ProfileMapSchema, {});
35390
+ const profileMap = profileMapStore(this.ctx.api.settingsStore, this.ctx.logger);
35185
35391
  const profileMapPersister = (assignments) => {
35186
- const obj = {};
35187
- for (const [deviceId, assignment] of assignments) obj[`${deviceId}`] = {
35392
+ const next = /* @__PURE__ */ new Map();
35393
+ for (const [deviceId, assignment] of assignments) next.set(`${deviceId}`, {
35188
35394
  map: { ...assignment.map },
35189
35395
  auto: assignment.auto
35190
- };
35191
- profileMapState.set(obj).catch((err) => {
35396
+ });
35397
+ profileMap.replaceAll(next).catch((err) => {
35192
35398
  this.ctx.logger.warn("Failed to persist profile map", { meta: { error: errMsg(err) } });
35193
35399
  });
35194
35400
  };
35195
35401
  this.brokerManager.setProfileMapPersister(profileMapPersister);
35196
35402
  try {
35197
- const obj = await profileMapState.get();
35403
+ const rows = await profileMap.readAll();
35198
35404
  const loaded = /* @__PURE__ */ new Map();
35199
- for (const [rawKey, val] of Object.entries(obj)) {
35405
+ for (const [rawKey, val] of rows) {
35200
35406
  const deviceId = Number(rawKey);
35201
35407
  if (!Number.isInteger(deviceId)) continue;
35202
35408
  const map = {};
@@ -35214,12 +35420,13 @@ var StreamBrokerAddon = class extends BaseAddon {
35214
35420
  } catch (err) {
35215
35421
  this.ctx.logger.warn("Failed to load profile map", { meta: { error: errMsg(err) } });
35216
35422
  }
35217
- const probeSnapshotsState = this.state("probeSnapshots", ProbedSnapshotMapSchema, {});
35218
- this.probeSnapshotsState = probeSnapshotsState;
35423
+ const probeSnapshots = probeSnapshotsStore(this.ctx.api.settingsStore, this.ctx.logger);
35424
+ this.probeSnapshots = probeSnapshots;
35219
35425
  try {
35220
- const blob = await probeSnapshotsState.get();
35426
+ const rows = await probeSnapshots.readAll();
35427
+ const blob = Object.fromEntries(rows);
35221
35428
  this.brokerManager.loadProbeSnapshots(blob);
35222
- this.ctx.logger.info("Loaded persisted probe snapshots", { meta: { streamCount: Object.keys(blob).length } });
35429
+ this.ctx.logger.info("Loaded persisted probe snapshots", { meta: { streamCount: rows.size } });
35223
35430
  } catch (err) {
35224
35431
  this.ctx.logger.warn("Failed to load probe snapshots", { meta: { error: errMsg(err) } });
35225
35432
  }
@@ -35576,17 +35783,54 @@ var StreamBrokerAddon = class extends BaseAddon {
35576
35783
  this.flushProbeSnapshots(timestamp, false);
35577
35784
  }
35578
35785
  /**
35786
+ * Declare the three row collections that replaced the `probeSnapshots`,
35787
+ * `rtspTokens` and `profileMap` blob keys. Idempotent — a re-declaration of
35788
+ * the same shape is a no-op in the engine.
35789
+ *
35790
+ * Not swallowed: a broker whose `stream-broker:rtsp-tokens` is undeclared
35791
+ * mints a new token for every stream and every external NVR URL in the
35792
+ * installation goes dead. Crashing loudly is bounded by `CrashSupervisor`
35793
+ * (D6); silently reissuing tokens is not.
35794
+ */
35795
+ async declareRowCollections() {
35796
+ const store = this.ctx.api.settingsStore;
35797
+ const logger = this.ctx.logger;
35798
+ await probeSnapshotsStore(store, logger).declare();
35799
+ await rtspTokensStore(store, logger).declare();
35800
+ await profileMapStore(store, logger).declare();
35801
+ }
35802
+ /**
35803
+ * Drop the flattened keys from `stream-broker:addon-settings` / `root`, each
35804
+ * gated on its own successor collection being non-empty. `rtspEnabled` and
35805
+ * `deviceOverrides` stay — see `broker-row-stores.ts` for why.
35806
+ *
35807
+ * Best-effort: a purge that throws must not take the broker down. The keys
35808
+ * are dead weight, not a fault.
35809
+ */
35810
+ async purgeFlattenedSettingsKeys() {
35811
+ try {
35812
+ await retireRootKeys({
35813
+ store: this.ctx.api.settingsStore,
35814
+ addonId: STREAM_BROKER_ADDON_ID,
35815
+ logger: this.ctx.logger,
35816
+ specs: STREAM_BROKER_RETIRED_ROOT_KEYS
35817
+ });
35818
+ } catch (err) {
35819
+ this.ctx.logger.warn("stream-broker: retiring the flattened settings keys failed", { meta: { error: errMsg(err) } });
35820
+ }
35821
+ }
35822
+ /**
35579
35823
  * Persist the manager's probe map to the durable handle. Throttled to
35580
35824
  * PROBE_SNAPSHOTS_PERSIST_INTERVAL_MS (or `force` on shutdown) so a busy
35581
35825
  * streaming fleet doesn't drive a write per metrics tick.
35582
35826
  */
35583
35827
  flushProbeSnapshots(now, force) {
35584
- const state = this.probeSnapshotsState;
35828
+ const store = this.probeSnapshots;
35585
35829
  const manager = this.brokerManager;
35586
- if (!state || !manager) return;
35830
+ if (!store || !manager) return;
35587
35831
  if (!force && now - this.lastProbePersistAt < PROBE_SNAPSHOTS_PERSIST_INTERVAL_MS) return;
35588
35832
  this.lastProbePersistAt = now;
35589
- state.set(manager.getProbeSnapshots()).catch((err) => {
35833
+ store.replaceAll(new Map(Object.entries(manager.getProbeSnapshots()))).catch((err) => {
35590
35834
  this.ctx.logger.warn("Failed to persist probe snapshots", { meta: { error: errMsg(err) } });
35591
35835
  });
35592
35836
  }
@@ -30,7 +30,7 @@ async function d(e) {
30
30
  }
31
31
  }
32
32
  async function f() {
33
- return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B7ERJocD.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C4fRkYcj.mjs")).catch((e) => {
34
34
  throw l = void 0, e;
35
35
  }), l;
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-pipeline",
3
- "version": "1.2.100",
3
+ "version": "1.2.101",
4
4
  "description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
5
5
  "keywords": [
6
6
  "camstack",