@camstack/system 1.2.80 → 1.2.81

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.
@@ -42,8 +42,13 @@ export declare const SWR_COLD_WAIT_MS = 10000;
42
42
  * Max simultaneous ffmpeg keyframe grabs — the WRAPPER path, the common case for
43
43
  * cameras with no vendor snapshot URL. A 20-cam grid mount spawns at most this
44
44
  * many ffmpeg processes; the rest serve cached frames (SWR) or queue.
45
+ *
46
+ * Raised 3 → 6 on 2026-08-12 (operator): a 17-camera cold start serialised
47
+ * into 6 waves and the client-side "image displayed" clustering matched the
48
+ * pool exactly (p90 10.8 s). Measured client-side after the raise — if the
49
+ * hub shows decode pressure, this is the first knob to lower.
45
50
  */
46
- export declare const MAX_CONCURRENT_GRABS = 3;
51
+ export declare const MAX_CONCURRENT_GRABS = 6;
47
52
  /**
48
53
  * Max simultaneous cheap native snapshot fetches (vendor HTTP/ONVIF). Higher than
49
54
  * the ffmpeg bound because a native fetch is a lightweight HTTP round-trip, not a
@@ -217,6 +217,16 @@ export declare class SnapshotAddon extends BaseAddon<SnapshotAddonConfig> {
217
217
  * and no cache propagates.
218
218
  */
219
219
  private resolveOutcome;
220
+ /**
221
+ * Reconcile backstop for a stale hit: is the frame we are about to serve the
222
+ * property of a device that no longer exists?
223
+ *
224
+ * Asked ONLY past `staleTtlMs`, which is already the "something is wrong"
225
+ * threshold — so the common path costs nothing. A `true` answer evicts and
226
+ * the caller returns null; anything else leaves the existing
227
+ * keep-the-UI-from-going-blank contract untouched.
228
+ */
229
+ private staleHitBelongsToRemovedDevice;
220
230
  /**
221
231
  * Run the capture ladder ONCE for a device: native provider first, then the
222
232
  * stream-broker ffmpeg fallback. Never rejects — resolves a {@link
@@ -289,6 +299,25 @@ export declare class SnapshotAddon extends BaseAddon<SnapshotAddonConfig> {
289
299
  */
290
300
  private runGrabWithResumeRetry;
291
301
  private invalidateCache;
302
+ /** Forget every cached artefact of one device: frames, derived variants and
303
+ * any settled single-flight result that would answer the next request. */
304
+ private dropDeviceCaches;
305
+ /**
306
+ * The device is GONE — drop its cached frames and say so.
307
+ *
308
+ * Distinct from `invalidateCache` (a refresh, expected and silent): this is
309
+ * the terminal case, and a deleted camera that keeps answering with its last
310
+ * JPEG looks to an operator exactly like a camera that was never deleted.
311
+ */
312
+ private evictRemovedDevice;
313
+ /**
314
+ * Does device-manager still know this id?
315
+ *
316
+ * `null` means the question could not be answered — a transport hiccup is
317
+ * not a deletion (D49), and the caller keeps serving what it has. Only an
318
+ * explicit "no such device" evicts.
319
+ */
320
+ private deviceStillExists;
292
321
  /**
293
322
  * Sleep state from the device-state MIRROR, not from a cap round-trip.
294
323
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.80",
3
+ "version": "1.2.81",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",