@camstack/addon-pipeline 1.2.198 → 1.2.200
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/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/{default-detection-model-B5v8qEI0.js → default-detection-model-BsmxtyZx.js} +1 -1
- package/dist/{default-detection-model-CASpAESz.mjs → default-detection-model-c1LY6thP.mjs} +1 -1
- package/dist/detection-pipeline/index.js +5 -5
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-BxP0SvPz.js → dist-D2YTTkRf.js} +436 -419
- package/dist/{dist-oFIHnD88.mjs → dist-mEsrAAc3.mjs} +436 -419
- package/dist/{lazy-sharp-VKOG3WW4.js → lazy-sharp-B5bW34uC.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-B4zETsJ9.mjs → node-CUxep5tc.mjs} +1 -1
- package/dist/{node-BIKrNEtS.js → node-x3YokJkD.js} +1 -1
- package/dist/pipeline-runner/index.js +8 -7
- package/dist/pipeline-runner/index.mjs +7 -6
- package/dist/{process-memory-D9xYwm6L.mjs → process-memory-BCqpTruN.mjs} +1 -1
- package/dist/{process-memory-CMHOmj75.js → process-memory-CFc4D9A2.js} +1 -1
- package/dist/recorder/index.js +169 -334
- package/dist/recorder/index.mjs +164 -329
- package/dist/restream-intent-B1Difcnq.js +313 -0
- package/dist/restream-intent-DWe2kInY.mjs +248 -0
- package/dist/{prebuffer-DmBYRQWg.mjs → retire-root-keys-Csb8z2f3.js} +12 -64
- package/dist/{prebuffer-DqdeLSsk.js → retire-root-keys-DZvlso2l.mjs} +1 -99
- package/dist/{segment-demux-js-DLwL1vmq.js → segment-demux-js-DUZVURQd.js} +1 -1
- package/dist/{segment-demux-js-DZysrgdC.mjs → segment-demux-js-xHtB450F.mjs} +1 -1
- package/dist/session-decode/decode-worker-child.js +25 -5
- package/dist/session-decode/decode-worker-child.mjs +24 -4
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C2eTdxvd.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CLXImQ3R.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-NqqfpkYF.mjs +26 -0
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dj_qoc1e.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-D62O5bRa.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-C8tu7NS4.mjs → hostInit-D_cZQhBA.mjs} +3 -3
- package/dist/stream-broker/index.js +181 -48
- package/dist/stream-broker/index.mjs +172 -39
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-D2mMjUXv.js → worker-protocol-CRDaBlJl.js} +1 -1
- package/dist/{worker-protocol-DFlZm_wr.mjs → worker-protocol-oUamwZSn.mjs} +1 -1
- package/package.json +1 -1
- package/dist/restream-intent-B4BXZra7.mjs +0 -72
- package/dist/restream-intent-Cv9x3jmu.js +0 -89
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BcjLrxhF.mjs +0 -26
package/dist/recorder/index.js
CHANGED
|
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_node = require("../node-
|
|
5
|
+
const require_dist = require("../dist-D2YTTkRf.js");
|
|
6
|
+
const require_node = require("../node-x3YokJkD.js");
|
|
7
7
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
8
|
-
const require_restream_intent = require("../restream-intent-
|
|
8
|
+
const require_restream_intent = require("../restream-intent-B1Difcnq.js");
|
|
9
9
|
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
|
|
10
|
-
const
|
|
10
|
+
const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
|
|
11
11
|
let node_crypto = require("node:crypto");
|
|
12
12
|
let node_fs = require("node:fs");
|
|
13
13
|
let node_path = require("node:path");
|
|
@@ -3950,7 +3950,7 @@ var DEFAULT_DEVICE_CONFIG = {
|
|
|
3950
3950
|
};
|
|
3951
3951
|
/** Build the handle. `declare()` MUST run once at boot before any read/write. */
|
|
3952
3952
|
function recordingConfigsState(store, logger) {
|
|
3953
|
-
return new
|
|
3953
|
+
return new require_retire_root_keys.RowMapStore({
|
|
3954
3954
|
spec: RECORDING_CONFIGS_SPEC,
|
|
3955
3955
|
store,
|
|
3956
3956
|
logger
|
|
@@ -5241,7 +5241,7 @@ var RECORDING_EXPORTS_SPEC = {
|
|
|
5241
5241
|
};
|
|
5242
5242
|
/** Build the handle. `declare()` MUST run once at boot before any read/write. */
|
|
5243
5243
|
function recordingExportsState(store, logger) {
|
|
5244
|
-
return new
|
|
5244
|
+
return new require_retire_root_keys.RowMapStore({
|
|
5245
5245
|
spec: RECORDING_EXPORTS_SPEC,
|
|
5246
5246
|
store,
|
|
5247
5247
|
logger
|
|
@@ -7733,96 +7733,59 @@ function runFfmpeg(renderDeps, args, ext) {
|
|
|
7733
7733
|
});
|
|
7734
7734
|
});
|
|
7735
7735
|
}
|
|
7736
|
-
|
|
7737
|
-
//#region src/recorder/addon/roots.ts
|
|
7738
|
-
/**
|
|
7739
|
-
* Storage-root resolution + boot hydrate for the recorder addon.
|
|
7740
|
-
*
|
|
7741
|
-
* Recordings live in the managed `recordings` / `recordingsLow` storage
|
|
7742
|
-
* locations (operator-configurable, multi-disk-ready), resolved through the
|
|
7743
|
-
* `storage` cap. The v2 `RecordingIndex` is hydrated by walking each location
|
|
7744
|
-
* root's `<deviceId>/` subtree on disk — segment paths encode start/dur/bytes,
|
|
7745
|
-
* so the in-memory index can never drift from disk. (We walk the filesystem
|
|
7746
|
-
* directly instead of `storage.list` because that cap lists only a directory's
|
|
7747
|
-
* IMMEDIATE children, not the `<deviceId>/<profile>/Y/M/D/H/*.m4s` tree — using
|
|
7748
|
-
* it dropped the entire index to ~empty on every restart/rescan; the recorder
|
|
7749
|
-
* already does local fs I/O for stat/move on these same roots.)
|
|
7750
|
-
*/
|
|
7751
|
-
/** The two recordings location types the recorder addon writes/reads. */
|
|
7752
|
-
var PLACEMENT_LOCATION_TYPES = ["recordings", "recordingsLow"];
|
|
7753
|
-
var RECORDING_LOCATION_TYPES = new Set(PLACEMENT_LOCATION_TYPES);
|
|
7736
|
+
var RECORDING_LOCATION_TYPES = new Set(["recordings", "recordingsLow"]);
|
|
7754
7737
|
/**
|
|
7755
7738
|
* The recordings CLASS a profile belongs to. The one place this rule is
|
|
7756
|
-
* written: `resolvePlacement`, the planner's demand type and the
|
|
7757
|
-
* must agree on it, and three copies of `profile === 'low' ? … : …` is
|
|
7758
|
-
* stop agreeing.
|
|
7739
|
+
* written: `resolvePlacement`, the planner's demand type and the placement
|
|
7740
|
+
* census must agree on it, and three copies of `profile === 'low' ? … : …` is
|
|
7741
|
+
* how they stop agreeing.
|
|
7759
7742
|
*/
|
|
7760
7743
|
function placementTypeForProfile(profile) {
|
|
7761
7744
|
return profile === "low" ? "recordingsLow" : "recordings";
|
|
7762
7745
|
}
|
|
7763
|
-
/** The profile that routes to each class — the probe `authorityLocations` asks
|
|
7764
|
-
* `resolvePlacement` with, so the answer is derived from the same function the
|
|
7765
|
-
* unassigned path uses rather than from a second reading of `isDefault`. */
|
|
7766
|
-
var CLASS_PROBE_PROFILE = {
|
|
7767
|
-
recordings: "high",
|
|
7768
|
-
recordingsLow: "low"
|
|
7769
|
-
};
|
|
7770
|
-
/**
|
|
7771
|
-
* Where each recordings class writes when NOTHING has planned it — the location
|
|
7772
|
-
* `resolvePlacement` picks, which is the type default unless the default is
|
|
7773
|
-
* gone, read-only, or absent from the pool.
|
|
7774
|
-
*
|
|
7775
|
-
* This is the AUTHORITY a stored assignment is measured against (D298). A
|
|
7776
|
-
* repoint (`storage.setDefaultLocations`, an operator making another disk the
|
|
7777
|
-
* default, a default deleted) changes exactly this map, and a stored assignment
|
|
7778
|
-
* that survives that change is a plan that outlived the pool it was planned
|
|
7779
|
-
* for.
|
|
7780
|
-
*
|
|
7781
|
-
* A class with nothing writable is ABSENT from the map, not guessed at: `place`
|
|
7782
|
-
* already throws loudly on that path, and an authority nobody can compute must
|
|
7783
|
-
* invalidate nothing.
|
|
7784
|
-
*/
|
|
7785
|
-
function authorityLocations(pool) {
|
|
7786
|
-
const out = /* @__PURE__ */ new Map();
|
|
7787
|
-
for (const type of PLACEMENT_LOCATION_TYPES) try {
|
|
7788
|
-
out.set(type, resolvePlacement(pool, CLASS_PROBE_PROFILE[type]).id);
|
|
7789
|
-
} catch {}
|
|
7790
|
-
return out;
|
|
7791
|
-
}
|
|
7792
7746
|
/**
|
|
7793
7747
|
* Narrow a resolved location list to the ones placement may write to: the
|
|
7794
|
-
*
|
|
7795
|
-
* (`enabled === false`) is still READ, age-swept and drained — it is simply
|
|
7748
|
+
* enabled ones — ALL of them, together. A location the operator has not opted
|
|
7749
|
+
* in (`enabled === false`) is still READ, age-swept and drained — it is simply
|
|
7796
7750
|
* never a write target, exactly like a read-only one.
|
|
7797
7751
|
*
|
|
7798
|
-
* When no enabled location is writable
|
|
7799
|
-
*
|
|
7800
|
-
* only
|
|
7801
|
-
* is worse than one that writes
|
|
7752
|
+
* When no enabled location is writable EVERY location serves instead, loudly.
|
|
7753
|
+
* The orchestrator refuses to leave a recordings class without an enabled
|
|
7754
|
+
* location, so this is reachable only through a hand-edited store — and a
|
|
7755
|
+
* recorder that writes nowhere is worse than one that writes under protest.
|
|
7802
7756
|
*/
|
|
7803
7757
|
function placementPool(locations) {
|
|
7804
7758
|
const enabled = locations.filter((l) => l.enabled !== false);
|
|
7805
7759
|
if (enabled.some((l) => !l.readOnly)) return {
|
|
7806
7760
|
locations: enabled,
|
|
7807
|
-
|
|
7808
|
-
};
|
|
7809
|
-
const defaults = locations.filter((l) => l.isDefault === true);
|
|
7810
|
-
if (defaults.some((l) => !l.readOnly)) return {
|
|
7811
|
-
locations: defaults,
|
|
7812
|
-
fellBackToDefault: true
|
|
7761
|
+
fellBackToDisabled: false
|
|
7813
7762
|
};
|
|
7814
7763
|
return {
|
|
7815
7764
|
locations,
|
|
7816
|
-
|
|
7765
|
+
fellBackToDisabled: true
|
|
7817
7766
|
};
|
|
7818
7767
|
}
|
|
7819
7768
|
/**
|
|
7820
|
-
* Route a recording profile to
|
|
7821
|
-
*
|
|
7822
|
-
*
|
|
7823
|
-
*
|
|
7824
|
-
*
|
|
7825
|
-
*
|
|
7769
|
+
* Route a recording profile to a storage location, for a (camera, profile) the
|
|
7770
|
+
* PLANNER has not placed yet — the first attach of a new camera, before the
|
|
7771
|
+
* 30 s pass runs.
|
|
7772
|
+
*
|
|
7773
|
+
* The rule, in order:
|
|
7774
|
+
* 1. the location's declared `type` — `low` prefers `recordingsLow`, every
|
|
7775
|
+
* other profile prefers `recordings`; when the preferred type has only
|
|
7776
|
+
* read-only instances, any writable recordings-type location serves;
|
|
7777
|
+
* 2. among those, the one with the most MEASURED headroom
|
|
7778
|
+
* (`min(free − minFree floor, maxUsedGb − used)`) — the same signal the
|
|
7779
|
+
* planner balances on, so the bootstrap pick and the plan agree instead of
|
|
7780
|
+
* the plan having to undo the pick at the next tick;
|
|
7781
|
+
* 3. ties, and a pool where nothing was measured, fall to the
|
|
7782
|
+
* lexicographically first id — deterministic, never "whichever came back
|
|
7783
|
+
* first from the cap".
|
|
7784
|
+
*
|
|
7785
|
+
* There is no preferred instance any more (D383): every enabled location of a
|
|
7786
|
+
* class is a write target, and which one a camera gets is a capacity question,
|
|
7787
|
+
* not a flag. Throws when NO writable location exists — recording cannot start,
|
|
7788
|
+
* and that must be loud.
|
|
7826
7789
|
*/
|
|
7827
7790
|
function resolvePlacement(locations, profile) {
|
|
7828
7791
|
if (locations.length === 0) throw new Error("recorder controller: no recordings storage locations resolved");
|
|
@@ -7830,7 +7793,15 @@ function resolvePlacement(locations, profile) {
|
|
|
7830
7793
|
if (writable.length === 0) throw new Error("recorder controller: every recordings location is read-only — nowhere to write");
|
|
7831
7794
|
const preferType = profile === "low" ? "recordingsLow" : "recordings";
|
|
7832
7795
|
const preferred = writable.filter((l) => l.type === preferType);
|
|
7833
|
-
return preferred.
|
|
7796
|
+
return emptiestOf(preferred.length > 0 ? preferred : writable);
|
|
7797
|
+
}
|
|
7798
|
+
/** The candidate with the most measured headroom; ties (and an unmeasured
|
|
7799
|
+
* pool, where every headroom is absent) by lexicographic id. */
|
|
7800
|
+
function emptiestOf(candidates) {
|
|
7801
|
+
return candidates.toSorted((a, b) => {
|
|
7802
|
+
const byHeadroom = (b.headroomBytes ?? 0) - (a.headroomBytes ?? 0);
|
|
7803
|
+
return byHeadroom !== 0 ? byHeadroom : a.id.localeCompare(b.id);
|
|
7804
|
+
})[0];
|
|
7834
7805
|
}
|
|
7835
7806
|
/**
|
|
7836
7807
|
* Attribute a discovered segment on an aliased physical root by its profile,
|
|
@@ -7880,7 +7851,6 @@ async function resolveRecordingsLocations(api, logger) {
|
|
|
7880
7851
|
relativePath: ""
|
|
7881
7852
|
}),
|
|
7882
7853
|
readOnly: l.config["readOnly"] === true,
|
|
7883
|
-
isDefault: l.isDefault,
|
|
7884
7854
|
...l.enabled === false ? { enabled: false } : {},
|
|
7885
7855
|
...numericConfig(l.config, "minFreePercent", "minFreePercent"),
|
|
7886
7856
|
...numericConfig(l.config, "maxUsedGb", "maxUsedGb")
|
|
@@ -10438,47 +10408,17 @@ Object.freeze({
|
|
|
10438
10408
|
},
|
|
10439
10409
|
"setDeviceConfig": { "config": { "__nested__": { "bands": [] } } }
|
|
10440
10410
|
},
|
|
10441
|
-
"storage": { "upsertLocation": {
|
|
10442
|
-
"isDefault": false,
|
|
10443
|
-
"isSystem": false
|
|
10444
|
-
} },
|
|
10411
|
+
"storage": { "upsertLocation": { "isSystem": false } },
|
|
10445
10412
|
"storage-provider": {
|
|
10446
|
-
"beginDownload": { "location": { "__nested__": {
|
|
10447
|
-
|
|
10448
|
-
|
|
10449
|
-
} } },
|
|
10450
|
-
"
|
|
10451
|
-
|
|
10452
|
-
|
|
10453
|
-
} } },
|
|
10454
|
-
"
|
|
10455
|
-
"isDefault": false,
|
|
10456
|
-
"isSystem": false
|
|
10457
|
-
} } },
|
|
10458
|
-
"exists": { "location": { "__nested__": {
|
|
10459
|
-
"isDefault": false,
|
|
10460
|
-
"isSystem": false
|
|
10461
|
-
} } },
|
|
10462
|
-
"getAvailableSpace": { "location": { "__nested__": {
|
|
10463
|
-
"isDefault": false,
|
|
10464
|
-
"isSystem": false
|
|
10465
|
-
} } },
|
|
10466
|
-
"list": { "location": { "__nested__": {
|
|
10467
|
-
"isDefault": false,
|
|
10468
|
-
"isSystem": false
|
|
10469
|
-
} } },
|
|
10470
|
-
"read": { "location": { "__nested__": {
|
|
10471
|
-
"isDefault": false,
|
|
10472
|
-
"isSystem": false
|
|
10473
|
-
} } },
|
|
10474
|
-
"resolve": { "location": { "__nested__": {
|
|
10475
|
-
"isDefault": false,
|
|
10476
|
-
"isSystem": false
|
|
10477
|
-
} } },
|
|
10478
|
-
"write": { "location": { "__nested__": {
|
|
10479
|
-
"isDefault": false,
|
|
10480
|
-
"isSystem": false
|
|
10481
|
-
} } }
|
|
10413
|
+
"beginDownload": { "location": { "__nested__": { "isSystem": false } } },
|
|
10414
|
+
"beginUpload": { "location": { "__nested__": { "isSystem": false } } },
|
|
10415
|
+
"delete": { "location": { "__nested__": { "isSystem": false } } },
|
|
10416
|
+
"exists": { "location": { "__nested__": { "isSystem": false } } },
|
|
10417
|
+
"getAvailableSpace": { "location": { "__nested__": { "isSystem": false } } },
|
|
10418
|
+
"list": { "location": { "__nested__": { "isSystem": false } } },
|
|
10419
|
+
"read": { "location": { "__nested__": { "isSystem": false } } },
|
|
10420
|
+
"resolve": { "location": { "__nested__": { "isSystem": false } } },
|
|
10421
|
+
"write": { "location": { "__nested__": { "isSystem": false } } }
|
|
10482
10422
|
},
|
|
10483
10423
|
"stream-broker": {
|
|
10484
10424
|
"produceEventMedia": {
|
|
@@ -11084,7 +11024,7 @@ var RECORDING_OPS_LOG_SPEC = {
|
|
|
11084
11024
|
};
|
|
11085
11025
|
/** Build the handle. `declare()` MUST run once at boot before any read/write. */
|
|
11086
11026
|
function recordingOpsLogState(store, logger) {
|
|
11087
|
-
return new
|
|
11027
|
+
return new require_retire_root_keys.RowMapStore({
|
|
11088
11028
|
spec: RECORDING_OPS_LOG_SPEC,
|
|
11089
11029
|
store,
|
|
11090
11030
|
logger
|
|
@@ -11496,19 +11436,16 @@ var RecordingPlacementBlobSchema = require_dist.object({
|
|
|
11496
11436
|
/** locationId → the volume id last verified at that location's root. */
|
|
11497
11437
|
volumeIds: require_dist.record(require_dist.string(), require_dist.string()).default({}),
|
|
11498
11438
|
/**
|
|
11499
|
-
*
|
|
11500
|
-
*
|
|
11501
|
-
*
|
|
11502
|
-
*
|
|
11503
|
-
* as a repoint: shipping this field must not invalidate assignments that were
|
|
11504
|
-
* made under an authority nothing wrote down. The first pass stamps it and
|
|
11505
|
-
* invalidates nothing; every later change of it is a repoint.
|
|
11439
|
+
* DEAD KEY (D383) — the class authority a pass planned against, back when a
|
|
11440
|
+
* class had a default distinct from its pool. Declared so an existing blob
|
|
11441
|
+
* round-trips unchanged and so its removal is a decision on the record rather
|
|
11442
|
+
* than a silent strip. Never read, never written.
|
|
11506
11443
|
*/
|
|
11507
11444
|
defaultLocations: require_dist.record(require_dist.string(), require_dist.string()).default({}),
|
|
11508
11445
|
/** When the blob was last written (operator-facing debugging only). */
|
|
11509
11446
|
updatedAt: require_dist.number().optional()
|
|
11510
11447
|
});
|
|
11511
|
-
/** Cold-start value: nothing assigned, nothing claimed
|
|
11448
|
+
/** Cold-start value: nothing assigned, nothing claimed. */
|
|
11512
11449
|
var EMPTY_PLACEMENT = {
|
|
11513
11450
|
assignments: {},
|
|
11514
11451
|
pins: {},
|
|
@@ -11557,31 +11494,27 @@ async function replaceAssignments(state, base, assignments) {
|
|
|
11557
11494
|
});
|
|
11558
11495
|
}
|
|
11559
11496
|
/**
|
|
11560
|
-
* The assignment record a pass leaves behind: the stored one
|
|
11561
|
-
*
|
|
11562
|
-
*
|
|
11497
|
+
* The assignment record a pass leaves behind: the stored one with the plan
|
|
11498
|
+
* merged over it. **Nothing is ever removed** — a pass that plans a subset
|
|
11499
|
+
* cannot delete a key it did not mention.
|
|
11563
11500
|
*
|
|
11564
|
-
* PURE, and shared by the write and the
|
|
11501
|
+
* PURE, and shared by the write and the placement census — a report computed
|
|
11565
11502
|
* from a second reading of the same rule is a report that can describe a record
|
|
11566
11503
|
* the write did not produce.
|
|
11567
11504
|
*/
|
|
11568
11505
|
function applyPlacementPass(base, pass) {
|
|
11569
11506
|
const next = new Map(Object.entries(base));
|
|
11570
|
-
for (const [key, locationId] of pass.repointed) next.set(key, locationId);
|
|
11571
11507
|
for (const [key, locationId] of pass.planned) next.set(key, locationId);
|
|
11572
11508
|
return next;
|
|
11573
11509
|
}
|
|
11574
|
-
/** Persist one work-scoped pass:
|
|
11575
|
-
*
|
|
11510
|
+
/** Persist one work-scoped pass: merge its plan over the stored record. One
|
|
11511
|
+
* write. */
|
|
11576
11512
|
async function writePlacementPass(state, base, pass) {
|
|
11577
11513
|
const assignments = {};
|
|
11578
11514
|
for (const [key, locationId] of applyPlacementPass(base.assignments, pass)) assignments[key] = locationId;
|
|
11579
|
-
const defaultLocations = {};
|
|
11580
|
-
for (const [type, locationId] of pass.defaultLocations) defaultLocations[type] = locationId;
|
|
11581
11515
|
await state.set({
|
|
11582
11516
|
...base,
|
|
11583
11517
|
assignments,
|
|
11584
|
-
defaultLocations,
|
|
11585
11518
|
updatedAt: Date.now()
|
|
11586
11519
|
});
|
|
11587
11520
|
}
|
|
@@ -11830,14 +11763,6 @@ var NO_PLAN = {
|
|
|
11830
11763
|
assignments: /* @__PURE__ */ new Map(),
|
|
11831
11764
|
changes: []
|
|
11832
11765
|
};
|
|
11833
|
-
/** Is the authority already stamped, exactly? A pass that would change the
|
|
11834
|
-
* stamp always writes, even when it moved nothing: an unstamped authority is
|
|
11835
|
-
* an undetectable repoint. */
|
|
11836
|
-
function sameStamp(stamped, authority) {
|
|
11837
|
-
if (stamped.size !== authority.size) return false;
|
|
11838
|
-
for (const [type, locationId] of authority) if (stamped.get(type) !== locationId) return false;
|
|
11839
|
-
return true;
|
|
11840
|
-
}
|
|
11841
11766
|
/** Operator pins win over the planner for high/mid of the pinned camera. */
|
|
11842
11767
|
function overlayPins(planned, pins) {
|
|
11843
11768
|
const next = new Map(planned);
|
|
@@ -11865,14 +11790,11 @@ var PlacementService = class {
|
|
|
11865
11790
|
/** The fair tie-break the PURE planner defers to (D37). Advisory state, and
|
|
11866
11791
|
* consulted only for a tie the capacity signal cannot separate. */
|
|
11867
11792
|
rotation = new PlacementRotation();
|
|
11868
|
-
/** The
|
|
11869
|
-
* announced yet
|
|
11870
|
-
|
|
11871
|
-
/** When the
|
|
11872
|
-
|
|
11873
|
-
/** Repoint episodes already announced (`type:from->to`). Cleared the moment a
|
|
11874
|
-
* pass sees no repoint at all — the next one is a NEW episode. */
|
|
11875
|
-
repointAnnounced = /* @__PURE__ */ new Set();
|
|
11793
|
+
/** The census last announced, as a stable signature. `null` ⇒ nothing
|
|
11794
|
+
* announced yet. */
|
|
11795
|
+
censusSignature = null;
|
|
11796
|
+
/** When the census was last announced. */
|
|
11797
|
+
censusReportedAt = null;
|
|
11876
11798
|
constructor(deps) {
|
|
11877
11799
|
this.deps = deps;
|
|
11878
11800
|
}
|
|
@@ -11907,15 +11829,14 @@ var PlacementService = class {
|
|
|
11907
11829
|
async place(deviceId, profile) {
|
|
11908
11830
|
const pool = this.pool();
|
|
11909
11831
|
this.reprobeAfterBackoff(pool);
|
|
11910
|
-
const
|
|
11911
|
-
const resolved = await this.assignedLocation(deviceId, profile, pool, authority) ?? resolvePlacement(pool, profile);
|
|
11832
|
+
const resolved = await this.assignedLocation(deviceId, profile, pool) ?? resolvePlacement(await this.withHeadroom(pool), profile);
|
|
11912
11833
|
const usable = await this.ensureUsable(resolved, pool, profile, deviceId);
|
|
11913
11834
|
if (this.everyLocationUnusable(pool)) {
|
|
11914
11835
|
this.reportEveryLocationUnusable(deviceId, profile, resolved, pool);
|
|
11915
11836
|
return resolved;
|
|
11916
11837
|
}
|
|
11917
11838
|
this.allUnusableReported.delete(deviceId);
|
|
11918
|
-
await this.recordDecision(deviceId, profile, usable, resolved.id === usable.id
|
|
11839
|
+
await this.recordDecision(deviceId, profile, usable, resolved.id === usable.id);
|
|
11919
11840
|
return usable;
|
|
11920
11841
|
}
|
|
11921
11842
|
/**
|
|
@@ -11999,35 +11920,30 @@ var PlacementService = class {
|
|
|
11999
11920
|
* to it, so an unknown flag is the only thing that counts as opted in.
|
|
12000
11921
|
*/
|
|
12001
11922
|
pool() {
|
|
12002
|
-
const { locations,
|
|
12003
|
-
if (
|
|
11923
|
+
const { locations, fellBackToDisabled } = placementPool(this.deps.locations());
|
|
11924
|
+
if (fellBackToDisabled) this.deps.logger.warn("recorder placement: NO recordings location is enabled for writing — writing to a DISABLED location under protest. Enable one in Storage.", { meta: { locationIds: locations.map((l) => l.id) } });
|
|
12004
11925
|
return locations;
|
|
12005
11926
|
}
|
|
12006
11927
|
/**
|
|
12007
11928
|
* The stored assignment for one (camera, profile), when it is still valid.
|
|
12008
11929
|
*
|
|
12009
|
-
*
|
|
12010
|
-
*
|
|
12011
|
-
* 1. the location is absent from the current pool (deleted, opted out);
|
|
12012
|
-
* 2. the location is read-only (an operator drain);
|
|
12013
|
-
* 3. **the class was REPOINTED under it** — the authority stamped in the
|
|
12014
|
-
* blob is not the authority now, and the assignment names neither.
|
|
11930
|
+
* Two things invalidate it, and under the operator's model (D383) there is
|
|
11931
|
+
* nothing else that can:
|
|
12015
11932
|
*
|
|
12016
|
-
*
|
|
12017
|
-
*
|
|
12018
|
-
*
|
|
12019
|
-
*
|
|
12020
|
-
*
|
|
12021
|
-
* returning the new default changed nothing — it is the fallback, not the
|
|
12022
|
-
* authority. On 2026-08-29 that left two of thirteen cameras writing to the
|
|
12023
|
-
* disk the fleet was migrating off, silently (D298).
|
|
11933
|
+
* 1. the location is absent from the current POOL — deleted, or the
|
|
11934
|
+
* operator disabled it. The pool is the single write authority, so an
|
|
11935
|
+
* assignment naming a location outside it is not a divergence to report,
|
|
11936
|
+
* it is unrepresentable;
|
|
11937
|
+
* 2. the location is read-only (an operator drain).
|
|
12024
11938
|
*
|
|
12025
|
-
*
|
|
12026
|
-
*
|
|
12027
|
-
*
|
|
12028
|
-
*
|
|
11939
|
+
* There used to be a third — "the class was REPOINTED under it", measured
|
|
11940
|
+
* against the class default stamped in the blob (D301). It existed only
|
|
11941
|
+
* because the default was a SECOND write authority layered over the pool and
|
|
11942
|
+
* the two could disagree. With the default deleted the disagreement cannot be
|
|
11943
|
+
* expressed: a location leaving the pool already invalidates every assignment
|
|
11944
|
+
* naming it, and the planner then moves those keys with `reason: 'gone'`.
|
|
12029
11945
|
*/
|
|
12030
|
-
async assignedLocation(deviceId, profile, pool
|
|
11946
|
+
async assignedLocation(deviceId, profile, pool) {
|
|
12031
11947
|
let blob;
|
|
12032
11948
|
try {
|
|
12033
11949
|
blob = await readPlacementState(this.deps.state);
|
|
@@ -12049,23 +11965,28 @@ var PlacementService = class {
|
|
|
12049
11965
|
}
|
|
12050
11966
|
if (assignedId === void 0) return null;
|
|
12051
11967
|
const location = pool.find((l) => l.id === assignedId && !l.readOnly) ?? null;
|
|
12052
|
-
if (location === null)
|
|
12053
|
-
const type = placementTypeForProfile(profile);
|
|
12054
|
-
const target = authority.get(type);
|
|
12055
|
-
const stamped = blob.defaultLocations[type];
|
|
12056
|
-
if (target === void 0 || stamped === void 0) return location;
|
|
12057
|
-
if (stamped === target || location.id === target) return location;
|
|
12058
|
-
this.deps.logger.warn("recorder placement: stored assignment INVALIDATED — this recordings class was repointed and the assignment still names the location it was repointed away from", {
|
|
11968
|
+
if (location === null) this.deps.logger.info("recorder placement: stored assignment INVALIDATED — its location is not a write target any more (disabled, read-only, or gone). Resolving fresh from the pool.", {
|
|
12059
11969
|
tags: { deviceId },
|
|
12060
11970
|
meta: {
|
|
12061
11971
|
profile,
|
|
12062
|
-
assignedLocationId:
|
|
12063
|
-
|
|
12064
|
-
repointedTo: target,
|
|
12065
|
-
locationType: type
|
|
11972
|
+
assignedLocationId: assignedId,
|
|
11973
|
+
poolLocationIds: pool.filter((l) => !l.readOnly).map((l) => l.id)
|
|
12066
11974
|
}
|
|
12067
11975
|
});
|
|
12068
|
-
return
|
|
11976
|
+
return location;
|
|
11977
|
+
}
|
|
11978
|
+
/** The pool, with each member's measured headroom attached. One capacity read
|
|
11979
|
+
* per location; used only on the bootstrap path, never per segment. */
|
|
11980
|
+
async withHeadroom(pool) {
|
|
11981
|
+
const candidates = await this.candidatesFor(pool);
|
|
11982
|
+
const byId = new Map(candidates.map((c) => [c.locationId, c.headroomBytes]));
|
|
11983
|
+
return pool.map((location) => {
|
|
11984
|
+
const headroomBytes = byId.get(location.id);
|
|
11985
|
+
return headroomBytes === void 0 ? location : {
|
|
11986
|
+
...location,
|
|
11987
|
+
headroomBytes
|
|
11988
|
+
};
|
|
11989
|
+
});
|
|
12069
11990
|
}
|
|
12070
11991
|
/**
|
|
12071
11992
|
* Re-plan the (camera, profile) pairs in `work` over the current locations.
|
|
@@ -12087,7 +12008,6 @@ var PlacementService = class {
|
|
|
12087
12008
|
*/
|
|
12088
12009
|
async recompute(work) {
|
|
12089
12010
|
const pool = this.pool();
|
|
12090
|
-
const authority = authorityLocations(pool);
|
|
12091
12011
|
const candidates = await this.candidatesFor(pool);
|
|
12092
12012
|
const demands = work.map((item) => ({
|
|
12093
12013
|
key: assignmentKey(item.deviceId, item.profile),
|
|
@@ -12104,17 +12024,7 @@ var PlacementService = class {
|
|
|
12104
12024
|
} });
|
|
12105
12025
|
return NO_PLAN;
|
|
12106
12026
|
}
|
|
12107
|
-
const
|
|
12108
|
-
const repoints = this.detectRepoints(blob.assignments, stamped, authority, blob.pins);
|
|
12109
|
-
if (repoints.length === 0) this.repointAnnounced.clear();
|
|
12110
|
-
for (const repoint of repoints) this.announceRepoint(repoint);
|
|
12111
|
-
const repointed = /* @__PURE__ */ new Map();
|
|
12112
|
-
for (const repoint of repoints) for (const key of repoint.keys) repointed.set(key, repoint.to);
|
|
12113
|
-
const current = applyPlacementPass(blob.assignments, {
|
|
12114
|
-
repointed,
|
|
12115
|
-
planned: /* @__PURE__ */ new Map(),
|
|
12116
|
-
defaultLocations: authority
|
|
12117
|
-
});
|
|
12027
|
+
const current = new Map(Object.entries(blob.assignments));
|
|
12118
12028
|
const evacuate = new Set(candidates.filter((c) => c.headroomBytes <= 0).map((c) => c.locationId));
|
|
12119
12029
|
for (const location of pool) if (location.readOnly) evacuate.add(location.id);
|
|
12120
12030
|
const plan = planPlacement({
|
|
@@ -12124,13 +12034,9 @@ var PlacementService = class {
|
|
|
12124
12034
|
evacuate,
|
|
12125
12035
|
breakTie: (tied) => this.rotation.next(tied)
|
|
12126
12036
|
});
|
|
12127
|
-
const pass = {
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
defaultLocations: authority
|
|
12131
|
-
};
|
|
12132
|
-
this.reportDivergence(applyPlacementPass(blob.assignments, pass), authority);
|
|
12133
|
-
if (plan.changes.length === 0 && repointed.size === 0 && sameStamp(stamped, authority)) return plan;
|
|
12037
|
+
const pass = { planned: overlayPins(plan.assignments, blob.pins) };
|
|
12038
|
+
this.reportCensus(applyPlacementPass(blob.assignments, pass), pool);
|
|
12039
|
+
if (plan.changes.length === 0) return plan;
|
|
12134
12040
|
for (const change of plan.changes) {
|
|
12135
12041
|
const deviceId = Number(change.key.split(":")[0]);
|
|
12136
12042
|
this.deps.logger.info("recorder placement: plan moves a profile to another location", {
|
|
@@ -12154,129 +12060,60 @@ var PlacementService = class {
|
|
|
12154
12060
|
return plan;
|
|
12155
12061
|
}
|
|
12156
12062
|
/**
|
|
12157
|
-
*
|
|
12158
|
-
*
|
|
12159
|
-
*
|
|
12160
|
-
* PURE. A class is repointed when the blob stamped an authority for it and
|
|
12161
|
-
* the authority now is a different location. A class with NO stamp is not a
|
|
12162
|
-
* repoint — it is the first pass after this shipped, and inferring a repoint
|
|
12163
|
-
* from an absent stamp would throw away every deliberate assignment on the
|
|
12164
|
-
* first tick after a deploy.
|
|
12165
|
-
*/
|
|
12166
|
-
detectRepoints(stored, stamped, authority, pins) {
|
|
12167
|
-
const out = [];
|
|
12168
|
-
for (const [type, to] of authority) {
|
|
12169
|
-
const from = stamped.get(type);
|
|
12170
|
-
if (from === void 0 || from === to) continue;
|
|
12171
|
-
const keys = [];
|
|
12172
|
-
for (const [key, locationId] of Object.entries(stored)) {
|
|
12173
|
-
const [devicePart, profilePart] = key.split(":");
|
|
12174
|
-
if (placementTypeForProfile(profilePart ?? "") !== type) continue;
|
|
12175
|
-
if (locationId === to) continue;
|
|
12176
|
-
if (type === "recordings" && devicePart !== void 0 && pins[devicePart] !== void 0) continue;
|
|
12177
|
-
keys.push(key);
|
|
12178
|
-
}
|
|
12179
|
-
out.push({
|
|
12180
|
-
type,
|
|
12181
|
-
from,
|
|
12182
|
-
to,
|
|
12183
|
-
keys
|
|
12184
|
-
});
|
|
12185
|
-
}
|
|
12186
|
-
return out;
|
|
12187
|
-
}
|
|
12188
|
-
/**
|
|
12189
|
-
* One line PER CAMERA (a repoint is asked per-camera: "did 3839 move?"), plus
|
|
12190
|
-
* one audit row per class. A repoint is a rare operator event, so the volume
|
|
12191
|
-
* is one burst of fleet-size, not a stream.
|
|
12063
|
+
* WHERE THE FLEET WRITES — one line per (class, location), always with its
|
|
12064
|
+
* denominator (D277).
|
|
12192
12065
|
*
|
|
12193
|
-
*
|
|
12194
|
-
*
|
|
12195
|
-
*
|
|
12196
|
-
*
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
if (this.repointAnnounced.has(episode)) return;
|
|
12201
|
-
this.repointAnnounced.add(episode);
|
|
12202
|
-
for (const key of repoint.keys) {
|
|
12203
|
-
const deviceId = Number(key.split(":")[0]);
|
|
12204
|
-
this.deps.logger.warn("recorder placement: recordings class REPOINTED — moving this assignment onto the class`s new authority location", {
|
|
12205
|
-
...Number.isFinite(deviceId) ? { tags: { deviceId } } : {},
|
|
12206
|
-
meta: {
|
|
12207
|
-
key,
|
|
12208
|
-
locationType: repoint.type,
|
|
12209
|
-
repointedFrom: repoint.from,
|
|
12210
|
-
repointedTo: repoint.to
|
|
12211
|
-
}
|
|
12212
|
-
});
|
|
12213
|
-
}
|
|
12214
|
-
this.deps.opsLog.append({
|
|
12215
|
-
op: "relocate",
|
|
12216
|
-
reason: "operator",
|
|
12217
|
-
deviceId: null,
|
|
12218
|
-
itemsAffected: repoint.keys.length,
|
|
12219
|
-
bytesReclaimed: 0,
|
|
12220
|
-
actor: "system",
|
|
12221
|
-
detail: `placement: ${repoint.type} repointed ${repoint.from} → ${repoint.to}; ${repoint.keys.length.toString()} assignment(s) moved (${repoint.keys.join(", ")})`
|
|
12222
|
-
});
|
|
12223
|
-
}
|
|
12224
|
-
/**
|
|
12225
|
-
* Say which (camera, profile) the plan writes somewhere other than its class
|
|
12226
|
-
* authority — per camera, WITH its denominator (D277).
|
|
12227
|
-
*
|
|
12228
|
-
* This is not an error path. The planner spreads a class across its pool on
|
|
12229
|
-
* purpose, and a location with headroom is a legitimate target. What was
|
|
12230
|
-
* wrong is that a deliberate spread and a leftover from a repoint nobody
|
|
12231
|
-
* noticed produced the *same* absence of output: `recordDecision` audits only
|
|
12232
|
-
* a CHANGE, so a camera that keeps using its old assignment writes no row and
|
|
12233
|
-
* no line, forever. An operator read "migration done" while two cameras were
|
|
12234
|
-
* still filling the disk they were migrating off.
|
|
12066
|
+
* This replaced the class-authority divergence report (D301) when the default
|
|
12067
|
+
* was deleted: with every enabled location of a class a legitimate target,
|
|
12068
|
+
* "this camera does not write to THE location" is not a fact any more, while
|
|
12069
|
+
* "recordings: 9 of 13 on recordings:default, 4 on recordings:hgst" is
|
|
12070
|
+
* exactly the question an operator asks after enabling a second disk. A pool
|
|
12071
|
+
* member holding ZERO assignments is listed too — an enabled disk nothing
|
|
12072
|
+
* lands on is the failure this whole model exists to make visible.
|
|
12235
12073
|
*
|
|
12236
|
-
* Fires on a CHANGE of the
|
|
12237
|
-
* {@link
|
|
12238
|
-
* until it stops being all-aligned, and again when it recovers.
|
|
12074
|
+
* Fires on a CHANGE of the distribution, and otherwise at most once per
|
|
12075
|
+
* {@link PLACEMENT_CENSUS_REPORT_MS}.
|
|
12239
12076
|
*/
|
|
12240
|
-
|
|
12241
|
-
const
|
|
12077
|
+
reportCensus(assignments, pool) {
|
|
12078
|
+
const counts = /* @__PURE__ */ new Map();
|
|
12079
|
+
const perClass = /* @__PURE__ */ new Map();
|
|
12080
|
+
for (const location of pool) if (!location.readOnly) counts.set(location.id, 0);
|
|
12242
12081
|
for (const [key, locationId] of assignments) {
|
|
12243
|
-
|
|
12244
|
-
const
|
|
12245
|
-
|
|
12246
|
-
divergent.push({
|
|
12247
|
-
key,
|
|
12248
|
-
deviceId: Number(key.split(":")[0]),
|
|
12249
|
-
profile,
|
|
12250
|
-
locationId,
|
|
12251
|
-
authorityLocationId
|
|
12252
|
-
});
|
|
12082
|
+
counts.set(locationId, (counts.get(locationId) ?? 0) + 1);
|
|
12083
|
+
const type = placementTypeForProfile(key.split(":")[1] ?? "");
|
|
12084
|
+
perClass.set(type, (perClass.get(type) ?? 0) + 1);
|
|
12253
12085
|
}
|
|
12254
|
-
const
|
|
12255
|
-
const
|
|
12086
|
+
const typeOf = new Map(pool.map((location) => [location.id, location.type]));
|
|
12087
|
+
const lines = [...counts.entries()].toSorted(([a], [b]) => a.localeCompare(b)).map(([locationId, count]) => {
|
|
12088
|
+
const type = typeOf.get(locationId) ?? locationId.split(":")[0] ?? locationId;
|
|
12089
|
+
return {
|
|
12090
|
+
locationId,
|
|
12091
|
+
type,
|
|
12092
|
+
assignments: count,
|
|
12093
|
+
ofClass: perClass.get(type) ?? 0
|
|
12094
|
+
};
|
|
12095
|
+
});
|
|
12096
|
+
const signature = lines.map((line) => `${line.locationId}=${String(line.assignments)}`).join(",");
|
|
12256
12097
|
const now = this.now;
|
|
12257
|
-
const due = this.
|
|
12258
|
-
if (signature ===
|
|
12259
|
-
this.
|
|
12260
|
-
this.
|
|
12261
|
-
if (
|
|
12262
|
-
|
|
12263
|
-
|
|
12098
|
+
const due = this.censusReportedAt === null || now - this.censusReportedAt >= 36e5;
|
|
12099
|
+
if (signature === this.censusSignature && !due) return;
|
|
12100
|
+
this.censusSignature = signature;
|
|
12101
|
+
this.censusReportedAt = now;
|
|
12102
|
+
if (lines.length === 0) return;
|
|
12103
|
+
this.deps.logger.info("recorder placement: census — which locations the fleet writes to", { meta: { locations: lines.map((line) => ({
|
|
12104
|
+
locationId: line.locationId,
|
|
12105
|
+
type: line.type,
|
|
12106
|
+
assignments: line.assignments,
|
|
12107
|
+
ofClass: line.ofClass
|
|
12108
|
+
})) } });
|
|
12109
|
+
for (const line of lines) {
|
|
12110
|
+
if (line.assignments > 0) continue;
|
|
12111
|
+
this.deps.logger.warn("recorder placement: this location is ENABLED but holds no assignment — nothing writes to it", { meta: {
|
|
12112
|
+
locationId: line.locationId,
|
|
12113
|
+
type: line.type,
|
|
12114
|
+
ofClass: line.ofClass
|
|
12115
|
+
} });
|
|
12264
12116
|
}
|
|
12265
|
-
this.deps.logger.warn("recorder placement: assignments write somewhere other than their class authority location", { meta: {
|
|
12266
|
-
divergent: divergent.length,
|
|
12267
|
-
assignments: assignments.size,
|
|
12268
|
-
authority: Object.fromEntries(authority)
|
|
12269
|
-
} });
|
|
12270
|
-
for (const entry of divergent) this.deps.logger.warn("recorder placement: this profile does NOT write to its class authority location", {
|
|
12271
|
-
...Number.isFinite(entry.deviceId) ? { tags: { deviceId: entry.deviceId } } : {},
|
|
12272
|
-
meta: {
|
|
12273
|
-
profile: entry.profile,
|
|
12274
|
-
locationId: entry.locationId,
|
|
12275
|
-
authorityLocationId: entry.authorityLocationId,
|
|
12276
|
-
divergent: divergent.length,
|
|
12277
|
-
assignments: assignments.size
|
|
12278
|
-
}
|
|
12279
|
-
});
|
|
12280
12117
|
}
|
|
12281
12118
|
/** Bound one addon-store round trip. See {@link PLACEMENT_STORE_TIMEOUT_MS}. */
|
|
12282
12119
|
bounded(promise, label) {
|
|
@@ -12457,13 +12294,13 @@ var PlacementService = class {
|
|
|
12457
12294
|
* Persist the assignment and audit it — but only when it actually changed.
|
|
12458
12295
|
* The steady state (every attach after the first) writes nothing.
|
|
12459
12296
|
*
|
|
12460
|
-
* The per-attach line carries
|
|
12461
|
-
*
|
|
12462
|
-
*
|
|
12463
|
-
*
|
|
12464
|
-
*
|
|
12297
|
+
* The per-attach line carries the camera's location and the one it replaced,
|
|
12298
|
+
* tagged with `deviceId`, so "where does 3839 write, and did it move?" is
|
|
12299
|
+
* answerable per camera. Which locations the FLEET is spread over is the
|
|
12300
|
+
* census's job (D383) — there is no class authority for a single line to be
|
|
12301
|
+
* measured against any more.
|
|
12465
12302
|
*/
|
|
12466
|
-
async recordDecision(deviceId, profile, location, verbatim
|
|
12303
|
+
async recordDecision(deviceId, profile, location, verbatim) {
|
|
12467
12304
|
const key = assignmentKey(deviceId, profile);
|
|
12468
12305
|
let previous;
|
|
12469
12306
|
try {
|
|
@@ -12484,8 +12321,6 @@ var PlacementService = class {
|
|
|
12484
12321
|
locationId: location.id,
|
|
12485
12322
|
root: location.root,
|
|
12486
12323
|
previousLocationId: previous ?? null,
|
|
12487
|
-
authorityLocationId,
|
|
12488
|
-
divergent: authorityLocationId !== null && authorityLocationId !== location.id,
|
|
12489
12324
|
reason: verbatim ? "resolved" : "failover"
|
|
12490
12325
|
}
|
|
12491
12326
|
});
|
|
@@ -12613,7 +12448,7 @@ function effectiveBands(config) {
|
|
|
12613
12448
|
*/
|
|
12614
12449
|
function resolveBandBufferMs(band) {
|
|
12615
12450
|
return {
|
|
12616
|
-
preMs:
|
|
12451
|
+
preMs: require_restream_intent.PREBUFFER_MAX_MS,
|
|
12617
12452
|
postMs: (band.postBufferSec ?? require_dist.DEFAULT_EVENTS_BAND_BUFFER_SEC.postBufferSec) * 1e3
|
|
12618
12453
|
};
|
|
12619
12454
|
}
|
|
@@ -15383,7 +15218,7 @@ var RecordingController = class {
|
|
|
15383
15218
|
tag: `recorder:${deviceId}/${profile}`
|
|
15384
15219
|
}, require_dist.nodePin(this.deps.ownerNodeId)), ATTACH_RPC_TIMEOUT_MS, "getStreamWithCodec"));
|
|
15385
15220
|
const streamAcquiredMs = this.now();
|
|
15386
|
-
const rtspUrl = require_restream_intent.withRecordingIntent(source.url);
|
|
15221
|
+
const rtspUrl = require_restream_intent.withRecordingIntent(source.url, require_restream_intent.RECORDING_PRE_ROLL_REQUEST_MS);
|
|
15387
15222
|
this.attachSeq++;
|
|
15388
15223
|
const consumerTag = `recorder/${deviceId}/${profile}/${this.attachSeq}`;
|
|
15389
15224
|
if (rtspUrl === source.url) this.deps.logger.info("recorder: dial carries no recording intent — no pre-roll", {
|
|
@@ -18410,7 +18245,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
18410
18245
|
*/
|
|
18411
18246
|
async purgeFlattenedSettingsKeys() {
|
|
18412
18247
|
try {
|
|
18413
|
-
await
|
|
18248
|
+
await require_retire_root_keys.retireRootKeys({
|
|
18414
18249
|
store: this.ctx.api.settingsStore,
|
|
18415
18250
|
addonId: RECORDER_ADDON_ID,
|
|
18416
18251
|
logger: this.ctx.logger,
|