@camstack/addon-pipeline 1.2.601 → 1.2.603
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 +3 -3
- package/dist/audio-analyzer/index.mjs +3 -3
- package/dist/{custom-model-catalog-DgyafyuW.js → custom-model-catalog-BAnOZBOf.js} +2 -2
- package/dist/{custom-model-catalog-CK9GK3N5.mjs → custom-model-catalog-Dv09Pvq_.mjs} +2 -2
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-BaHsDOWa.mjs → dist-CsCflIM1.mjs} +558 -16
- package/dist/{dist-BqI10eLV.js → dist-DvXRw_dM.js} +563 -15
- package/dist/{model-catalogs-DhGVt_sH.js → model-catalogs-B95QZeYt.js} +1 -1
- package/dist/{model-catalogs-DM5sVj1T.mjs → model-catalogs-aTwF92Re.mjs} +1 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-B0a0dXhg.mjs → node-DAp5MmRJ.mjs} +1 -1
- package/dist/{node-CgwqjGz0.js → node-DxAtLKEn.js} +1 -1
- package/dist/pipeline-runner/index.js +3 -3
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-sfdcLVkW.mjs → process-memory-1_2L6U3Q.mjs} +1 -1
- package/dist/{process-memory-C0zbWvwD.js → process-memory-CmWDOMmE.js} +1 -1
- package/dist/recorder/index.js +352 -51
- package/dist/recorder/index.mjs +352 -51
- package/dist/{segment-demux-js-BB4CUAB5.mjs → segment-demux-js-DQo9qSHm.mjs} +1 -1
- package/dist/{segment-demux-js-B9lL2VCC.js → segment-demux-js-HagdockZ.js} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CbN9DjoK.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DoBB8xYv.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DkA9R3eo.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-RrTYeVaZ.mjs +26 -0
- 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-BSYHAfPt.mjs → hostInit-DaZYQhX4.mjs} +3 -3
- package/dist/stream-broker/index.js +3 -3
- package/dist/stream-broker/index.mjs +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Boq8JqyD.mjs +0 -26
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B25q1OKG.mjs +0 -26
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-DvXRw_dM.js");
|
|
6
6
|
const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { An as DeviceType, Gn as hydrateSchema, Nn as BaseAddon, St as evaluateZoneRules, Wt as motionDetectionCapability } from "../dist-CsCflIM1.mjs";
|
|
2
2
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { On as isSoftwareDecode, Tn as buildFfmpegArgs, jn as errMsg, wn as Fmp4BoxSplitter } from "./dist-CsCflIM1.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
8
|
-
const require_custom_model_catalog = require("../custom-model-catalog-
|
|
6
|
+
const require_dist = require("../dist-DvXRw_dM.js");
|
|
7
|
+
const require_node = require("../node-DxAtLKEn.js");
|
|
8
|
+
const require_custom_model_catalog = require("../custom-model-catalog-BAnOZBOf.js");
|
|
9
9
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
10
10
|
const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
|
|
11
11
|
const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as NativeLeaseAdmissionSchema,
|
|
2
|
-
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-
|
|
3
|
-
import { a as stepsForElectedPool, b as getStepDefinition, d as rootObjectGate, f as localFrameRegistry, h as resolveFrameViewGeometry, i as placeDetailStep, l as resolveDefaultDetectionModel, m as createSessionDecodeCoordinator, p as isSessionDecodeReadGone, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, y as getStep } from "../custom-model-catalog-
|
|
1
|
+
import { A as NativeLeaseAdmissionSchema, Bn as customAction, E as FailureCounters, Et as failureContributionCapability, Ft as loadContributionCapability, Jt as pickDetailCropConvention, Ln as MODEL_FORMATS, M as NodeBenchRunnerInputSchema, Nn as BaseAddon, P as PIPELINE_RAMP, Pt as linkedStepOf, V as ROOT_SUPPLIABLE_STEP_IDS, Vn as defineCustomActions, Y as allowedSuppliedEffect, Yt as pickNativeLeaseOverride, Zn as nodePin, Zt as pipelineRunnerCapability, _ as DEFAULT_DETAIL_CROP_CONVENTION, a as BackgroundRunRegistry, cr as number, dn as rootSuppliesOf, fr as string, gt as deriveRootFaceRefineRect, ir as boolean, j as NativeLeaseSettingsSchema, jn as errMsg, lr as object, m as CROP_SUPPLY_SOURCES, mr as EventCategory, mt as deriveDetailCropRect, nr as _enum, nt as buildBenchStepTree, or as lazy, rr as array, rt as cameraOwnsMotionViaSensor, sn as resolveModelBoundSetting, sr as literal, un as resolveRootSupply, x as DEVICE_RAMP, y as DEFAULT_NATIVE_LEASE_SETTINGS, zn as createEvent } from "../dist-CsCflIM1.mjs";
|
|
2
|
+
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-DAp5MmRJ.mjs";
|
|
3
|
+
import { a as stepsForElectedPool, b as getStepDefinition, d as rootObjectGate, f as localFrameRegistry, h as resolveFrameViewGeometry, i as placeDetailStep, l as resolveDefaultDetectionModel, m as createSessionDecodeCoordinator, p as isSessionDecodeReadGone, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, y as getStep } from "../custom-model-catalog-Dv09Pvq_.mjs";
|
|
4
4
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
6
6
|
import { c as withDetectionIntent, o as preRollRequestOf, t as DETECTION_PRE_ROLL_REQUEST_MS } from "../restream-intent-DyGmLAU9.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-emK7D4bc.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-DvXRw_dM.js");
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
node_fs = require_chunk.__toESM(node_fs);
|
|
5
5
|
let node_child_process = require("node:child_process");
|
package/dist/recorder/index.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
6
|
+
const require_dist = require("../dist-DvXRw_dM.js");
|
|
7
|
+
const require_node = require("../node-DxAtLKEn.js");
|
|
8
8
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
9
9
|
const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
|
|
10
10
|
let node_crypto = require("node:crypto");
|
|
@@ -6736,6 +6736,142 @@ Object.freeze({
|
|
|
6736
6736
|
"path": "online",
|
|
6737
6737
|
"valueType": "boolean"
|
|
6738
6738
|
}],
|
|
6739
|
+
"dishwasher": [
|
|
6740
|
+
{
|
|
6741
|
+
"path": "availability",
|
|
6742
|
+
"valueType": "enum",
|
|
6743
|
+
"enumValues": [
|
|
6744
|
+
"available",
|
|
6745
|
+
"offline",
|
|
6746
|
+
"description-missing"
|
|
6747
|
+
]
|
|
6748
|
+
},
|
|
6749
|
+
{
|
|
6750
|
+
"path": "state",
|
|
6751
|
+
"valueType": "enum",
|
|
6752
|
+
"enumValues": [
|
|
6753
|
+
"idle",
|
|
6754
|
+
"running",
|
|
6755
|
+
"paused",
|
|
6756
|
+
"finished",
|
|
6757
|
+
"error",
|
|
6758
|
+
"unavailable"
|
|
6759
|
+
]
|
|
6760
|
+
},
|
|
6761
|
+
{
|
|
6762
|
+
"path": "operationState",
|
|
6763
|
+
"valueType": "enum",
|
|
6764
|
+
"enumValues": [
|
|
6765
|
+
"Inactive",
|
|
6766
|
+
"Ready",
|
|
6767
|
+
"DelayedStart",
|
|
6768
|
+
"Run",
|
|
6769
|
+
"Pause",
|
|
6770
|
+
"ActionRequired",
|
|
6771
|
+
"Finished",
|
|
6772
|
+
"Error",
|
|
6773
|
+
"Aborting"
|
|
6774
|
+
]
|
|
6775
|
+
},
|
|
6776
|
+
{
|
|
6777
|
+
"path": "program",
|
|
6778
|
+
"valueType": "string"
|
|
6779
|
+
},
|
|
6780
|
+
{
|
|
6781
|
+
"path": "selectedProgram",
|
|
6782
|
+
"valueType": "string"
|
|
6783
|
+
},
|
|
6784
|
+
{
|
|
6785
|
+
"path": "remainingSeconds",
|
|
6786
|
+
"valueType": "number"
|
|
6787
|
+
},
|
|
6788
|
+
{
|
|
6789
|
+
"path": "delayedStartSeconds",
|
|
6790
|
+
"valueType": "number"
|
|
6791
|
+
},
|
|
6792
|
+
{
|
|
6793
|
+
"path": "progressPercent",
|
|
6794
|
+
"valueType": "number"
|
|
6795
|
+
},
|
|
6796
|
+
{
|
|
6797
|
+
"path": "doorOpen",
|
|
6798
|
+
"valueType": "boolean"
|
|
6799
|
+
},
|
|
6800
|
+
{
|
|
6801
|
+
"path": "doorLocked",
|
|
6802
|
+
"valueType": "boolean"
|
|
6803
|
+
},
|
|
6804
|
+
{
|
|
6805
|
+
"path": "remoteStartAllowed",
|
|
6806
|
+
"valueType": "boolean"
|
|
6807
|
+
},
|
|
6808
|
+
{
|
|
6809
|
+
"path": "remoteControlActive",
|
|
6810
|
+
"valueType": "boolean"
|
|
6811
|
+
},
|
|
6812
|
+
{
|
|
6813
|
+
"path": "localControlActive",
|
|
6814
|
+
"valueType": "boolean"
|
|
6815
|
+
},
|
|
6816
|
+
{
|
|
6817
|
+
"path": "powerOn",
|
|
6818
|
+
"valueType": "boolean"
|
|
6819
|
+
},
|
|
6820
|
+
{
|
|
6821
|
+
"path": "powerState",
|
|
6822
|
+
"valueType": "string"
|
|
6823
|
+
},
|
|
6824
|
+
{
|
|
6825
|
+
"path": "saltLevel",
|
|
6826
|
+
"valueType": "enum",
|
|
6827
|
+
"enumValues": [
|
|
6828
|
+
"ok",
|
|
6829
|
+
"low",
|
|
6830
|
+
"empty"
|
|
6831
|
+
]
|
|
6832
|
+
},
|
|
6833
|
+
{
|
|
6834
|
+
"path": "rinseAidLevel",
|
|
6835
|
+
"valueType": "enum",
|
|
6836
|
+
"enumValues": [
|
|
6837
|
+
"ok",
|
|
6838
|
+
"low",
|
|
6839
|
+
"empty"
|
|
6840
|
+
]
|
|
6841
|
+
},
|
|
6842
|
+
{
|
|
6843
|
+
"path": "halfLoad",
|
|
6844
|
+
"valueType": "boolean"
|
|
6845
|
+
},
|
|
6846
|
+
{
|
|
6847
|
+
"path": "hygienePlus",
|
|
6848
|
+
"valueType": "boolean"
|
|
6849
|
+
},
|
|
6850
|
+
{
|
|
6851
|
+
"path": "extraDry",
|
|
6852
|
+
"valueType": "boolean"
|
|
6853
|
+
},
|
|
6854
|
+
{
|
|
6855
|
+
"path": "intensiveZone",
|
|
6856
|
+
"valueType": "boolean"
|
|
6857
|
+
},
|
|
6858
|
+
{
|
|
6859
|
+
"path": "varioSpeedPlus",
|
|
6860
|
+
"valueType": "boolean"
|
|
6861
|
+
},
|
|
6862
|
+
{
|
|
6863
|
+
"path": "childLock",
|
|
6864
|
+
"valueType": "boolean"
|
|
6865
|
+
},
|
|
6866
|
+
{
|
|
6867
|
+
"path": "errorCode",
|
|
6868
|
+
"valueType": "number"
|
|
6869
|
+
},
|
|
6870
|
+
{
|
|
6871
|
+
"path": "errorLabel",
|
|
6872
|
+
"valueType": "string"
|
|
6873
|
+
}
|
|
6874
|
+
],
|
|
6739
6875
|
"doorbell": [{
|
|
6740
6876
|
"path": "lastPressedAt",
|
|
6741
6877
|
"valueType": "number"
|
|
@@ -6826,6 +6962,10 @@ Object.freeze({
|
|
|
6826
6962
|
"path": "detected",
|
|
6827
6963
|
"valueType": "boolean"
|
|
6828
6964
|
}],
|
|
6965
|
+
"heating-valve": [{
|
|
6966
|
+
"path": "position",
|
|
6967
|
+
"valueType": "number"
|
|
6968
|
+
}],
|
|
6829
6969
|
"humidifier": [
|
|
6830
6970
|
{
|
|
6831
6971
|
"path": "on",
|
|
@@ -10330,6 +10470,22 @@ var LOCATE_HYDRATE_MARGIN_MS = 6e4;
|
|
|
10330
10470
|
*/
|
|
10331
10471
|
var WINDOW_READ_MAX_BYTES = 2e7;
|
|
10332
10472
|
/** Empty "no playback" manifest. */
|
|
10473
|
+
/**
|
|
10474
|
+
* Start a footage move only while no single-location repoint holds an
|
|
10475
|
+
* overlapping physical root (the storage orchestrator owns that claim).
|
|
10476
|
+
*/
|
|
10477
|
+
function startFootageMover(deps, engine, input) {
|
|
10478
|
+
const ask = deps.moverClearance;
|
|
10479
|
+
if (ask === void 0) return Promise.resolve(engine.start(input));
|
|
10480
|
+
return require_dist.startMoverUnderClearance({
|
|
10481
|
+
clearance: ask,
|
|
10482
|
+
start: () => engine.start(input),
|
|
10483
|
+
cancel: (jobId) => {
|
|
10484
|
+
engine.cancel(jobId);
|
|
10485
|
+
},
|
|
10486
|
+
locationIds: [input.fromLocationId, input.toLocationId]
|
|
10487
|
+
});
|
|
10488
|
+
}
|
|
10333
10489
|
function noPlayback(deviceId) {
|
|
10334
10490
|
return {
|
|
10335
10491
|
deviceId,
|
|
@@ -11132,13 +11288,13 @@ function buildRecordingProvider(deps) {
|
|
|
11132
11288
|
startStorageMigrationMove: async (input) => {
|
|
11133
11289
|
if (!deps.relocate) throw new Error("relocation unavailable on this node");
|
|
11134
11290
|
deps.assertStorageMigrationLease?.(input.leaseId);
|
|
11135
|
-
return { jobId: deps.relocate
|
|
11291
|
+
return { jobId: await startFootageMover(deps, deps.relocate, input) };
|
|
11136
11292
|
},
|
|
11137
11293
|
getStorageMigrationMoveStatus: async ({ jobId }) => deps.relocate?.list().find((job) => job.jobId === jobId) ?? null,
|
|
11138
11294
|
cancelStorageMigrationMove: async ({ jobId }) => ({ cancelled: deps.relocate?.cancel(jobId) ?? false }),
|
|
11139
11295
|
relocateFootage: async (input) => {
|
|
11140
11296
|
if (!deps.relocate) throw new Error("relocation unavailable on this node");
|
|
11141
|
-
const jobId = deps.relocate
|
|
11297
|
+
const jobId = await startFootageMover(deps, deps.relocate, input);
|
|
11142
11298
|
deps.logger.info("recorder: relocate job enqueued", {
|
|
11143
11299
|
...input.deviceId !== void 0 ? { tags: { deviceId: input.deviceId } } : {},
|
|
11144
11300
|
meta: {
|
|
@@ -11755,13 +11911,10 @@ var DurableLedger = class {
|
|
|
11755
11911
|
const body = this.spec.toValue(row);
|
|
11756
11912
|
if (this.spec.writeMode === "write-behind") {
|
|
11757
11913
|
this.mirror.set(key, row);
|
|
11758
|
-
await this.persistRow(key, body);
|
|
11914
|
+
await this.persistRow(key, body, row);
|
|
11759
11915
|
return;
|
|
11760
11916
|
}
|
|
11761
|
-
await this.kind.put(
|
|
11762
|
-
id: key,
|
|
11763
|
-
data: body
|
|
11764
|
-
});
|
|
11917
|
+
await this.kind.put(this.buildPut(key, body, row));
|
|
11765
11918
|
this.mirror.set(key, row);
|
|
11766
11919
|
}
|
|
11767
11920
|
/**
|
|
@@ -11862,15 +12015,27 @@ var DurableLedger = class {
|
|
|
11862
12015
|
*/
|
|
11863
12016
|
persist(row) {
|
|
11864
12017
|
const key = this.spec.keyOf(row);
|
|
11865
|
-
this.persistRow(key, this.spec.toValue(row));
|
|
12018
|
+
this.persistRow(key, this.spec.toValue(row), row);
|
|
11866
12019
|
}
|
|
11867
|
-
|
|
11868
|
-
const deviceId = this.
|
|
12020
|
+
buildPut(key, body, row) {
|
|
12021
|
+
const deviceId = this.resolveRecordDeviceId(row, body);
|
|
12022
|
+
return {
|
|
12023
|
+
id: key,
|
|
12024
|
+
data: body,
|
|
12025
|
+
...deviceId !== void 0 ? { deviceId } : {}
|
|
12026
|
+
};
|
|
12027
|
+
}
|
|
12028
|
+
resolveRecordDeviceId(row, body) {
|
|
12029
|
+
if (row !== void 0) {
|
|
12030
|
+
const fromSpec = this.spec.deviceIdOf?.(row);
|
|
12031
|
+
if (fromSpec !== void 0 && Number.isFinite(fromSpec)) return fromSpec;
|
|
12032
|
+
}
|
|
12033
|
+
return this.deviceIdFromBody(body);
|
|
12034
|
+
}
|
|
12035
|
+
async persistRow(key, body, row) {
|
|
12036
|
+
const deviceId = this.resolveRecordDeviceId(row, body);
|
|
11869
12037
|
try {
|
|
11870
|
-
await this.kind.put(
|
|
11871
|
-
id: key,
|
|
11872
|
-
data: body
|
|
11873
|
-
});
|
|
12038
|
+
await this.kind.put(this.buildPut(key, body, row));
|
|
11874
12039
|
} catch (err) {
|
|
11875
12040
|
this.logger.warn("durable persist failed — this key may re-seed on boot", {
|
|
11876
12041
|
...deviceId !== void 0 ? { tags: { deviceId } } : {},
|
|
@@ -15105,6 +15270,135 @@ function startPeriodicPass(deps) {
|
|
|
15105
15270
|
};
|
|
15106
15271
|
}
|
|
15107
15272
|
//#endregion
|
|
15273
|
+
//#region src/recorder/addon/placement-alerts.ts
|
|
15274
|
+
var SEVERITY = {
|
|
15275
|
+
unusable: "critical",
|
|
15276
|
+
"shared-root": "error",
|
|
15277
|
+
"writer-restart": "warning"
|
|
15278
|
+
};
|
|
15279
|
+
var TITLE = {
|
|
15280
|
+
unusable: "Recordings storage location unusable",
|
|
15281
|
+
"shared-root": "Recordings storage locations share one disk",
|
|
15282
|
+
"writer-restart": "Recording placement waiting on a writer restart"
|
|
15283
|
+
};
|
|
15284
|
+
/** Stable identity of one fault: the alert id AND its episode key. */
|
|
15285
|
+
function placementAlertId(locationId, reason) {
|
|
15286
|
+
return `recorder-placement:${locationId}:${reason}`;
|
|
15287
|
+
}
|
|
15288
|
+
var PlacementAlertPublisher = class {
|
|
15289
|
+
deps;
|
|
15290
|
+
episodes = /* @__PURE__ */ new Map();
|
|
15291
|
+
constructor(deps) {
|
|
15292
|
+
this.deps = deps;
|
|
15293
|
+
}
|
|
15294
|
+
/** Raise (or refresh) the alert of one fault. Advisory: never throws. */
|
|
15295
|
+
raise(input) {
|
|
15296
|
+
const id = placementAlertId(input.locationId, input.reason);
|
|
15297
|
+
const now = this.deps.now();
|
|
15298
|
+
const episode = this.episodes.get(id) ?? {
|
|
15299
|
+
createdAt: now,
|
|
15300
|
+
count: 0
|
|
15301
|
+
};
|
|
15302
|
+
episode.count += 1;
|
|
15303
|
+
this.episodes.set(id, episode);
|
|
15304
|
+
const alert = {
|
|
15305
|
+
id,
|
|
15306
|
+
category: "storage",
|
|
15307
|
+
severity: SEVERITY[input.reason],
|
|
15308
|
+
title: TITLE[input.reason],
|
|
15309
|
+
message: input.detail,
|
|
15310
|
+
status: "active",
|
|
15311
|
+
read: false,
|
|
15312
|
+
createdAt: episode.createdAt,
|
|
15313
|
+
updatedAt: now,
|
|
15314
|
+
source: {
|
|
15315
|
+
type: "addon",
|
|
15316
|
+
id: this.deps.sourceId
|
|
15317
|
+
},
|
|
15318
|
+
metadata: {
|
|
15319
|
+
locationId: input.locationId,
|
|
15320
|
+
nodeId: this.deps.nodeId,
|
|
15321
|
+
reason: input.reason,
|
|
15322
|
+
episodeKey: id,
|
|
15323
|
+
count: episode.count
|
|
15324
|
+
}
|
|
15325
|
+
};
|
|
15326
|
+
this.deps.port.emit(alert).catch((err) => {
|
|
15327
|
+
this.deps.logger.warn("recorder: storage alert emit failed (advisory)", { meta: {
|
|
15328
|
+
locationId: input.locationId,
|
|
15329
|
+
reason: input.reason,
|
|
15330
|
+
error: require_dist.errMsg(err)
|
|
15331
|
+
} });
|
|
15332
|
+
});
|
|
15333
|
+
}
|
|
15334
|
+
/** The fault is gone: close its alert. A fault that never fired is a no-op. */
|
|
15335
|
+
resolve(locationId, reason) {
|
|
15336
|
+
const id = placementAlertId(locationId, reason);
|
|
15337
|
+
const episode = this.episodes.get(id);
|
|
15338
|
+
if (episode === void 0) return;
|
|
15339
|
+
this.episodes.delete(id);
|
|
15340
|
+
this.deps.logger.info("recorder: storage fault recovered — closing its alert", { meta: {
|
|
15341
|
+
locationId,
|
|
15342
|
+
reason,
|
|
15343
|
+
alertId: id,
|
|
15344
|
+
raisedTimes: episode.count
|
|
15345
|
+
} });
|
|
15346
|
+
this.deps.port.update({
|
|
15347
|
+
alertId: id,
|
|
15348
|
+
patch: {
|
|
15349
|
+
status: "completed",
|
|
15350
|
+
read: true,
|
|
15351
|
+
updatedAt: this.deps.now()
|
|
15352
|
+
}
|
|
15353
|
+
}).catch((err) => {
|
|
15354
|
+
this.deps.logger.warn("recorder: closing a recovered storage alert failed (advisory)", { meta: {
|
|
15355
|
+
locationId,
|
|
15356
|
+
reason,
|
|
15357
|
+
alertId: id,
|
|
15358
|
+
error: require_dist.errMsg(err)
|
|
15359
|
+
} });
|
|
15360
|
+
});
|
|
15361
|
+
}
|
|
15362
|
+
};
|
|
15363
|
+
/**
|
|
15364
|
+
* Keeps the `writer-restart` alerts true to the live set of pending writer
|
|
15365
|
+
* moves: one alert per PLANNED location, raised while any camera is still
|
|
15366
|
+
* pending for it, completed when none is (the move landed, or the plan was
|
|
15367
|
+
* dropped - the target was drained or deleted).
|
|
15368
|
+
*/
|
|
15369
|
+
var WriterRestartAlerts = class {
|
|
15370
|
+
publisher;
|
|
15371
|
+
logger;
|
|
15372
|
+
previous = [];
|
|
15373
|
+
constructor(publisher, logger) {
|
|
15374
|
+
this.publisher = publisher;
|
|
15375
|
+
this.logger = logger;
|
|
15376
|
+
}
|
|
15377
|
+
update(moves) {
|
|
15378
|
+
const byLocation = /* @__PURE__ */ new Map();
|
|
15379
|
+
for (const move of moves) byLocation.set(move.plannedFor, (byLocation.get(move.plannedFor) ?? 0) + 1);
|
|
15380
|
+
for (const [locationId, count] of byLocation) this.publisher.raise({
|
|
15381
|
+
locationId,
|
|
15382
|
+
reason: "writer-restart",
|
|
15383
|
+
detail: `${String(count)} recording profile(s) are planned for ${locationId} and will keep writing to their current location until each camera next attaches. Continuously-recording cameras never re-attach on their own.`
|
|
15384
|
+
});
|
|
15385
|
+
const stillPending = new Set(moves.map((m) => `${String(m.deviceId)}:${m.profile}>${m.plannedFor}`));
|
|
15386
|
+
for (const gone of this.previous) {
|
|
15387
|
+
if (stillPending.has(`${String(gone.deviceId)}:${gone.profile}>${gone.plannedFor}`)) continue;
|
|
15388
|
+
this.logger.info("recorder placement: writer-restart no longer pending for this camera", {
|
|
15389
|
+
tags: { deviceId: gone.deviceId },
|
|
15390
|
+
meta: {
|
|
15391
|
+
locationId: gone.plannedFor,
|
|
15392
|
+
profile: gone.profile,
|
|
15393
|
+
writingTo: gone.writingTo
|
|
15394
|
+
}
|
|
15395
|
+
});
|
|
15396
|
+
}
|
|
15397
|
+
for (const gone of this.previous) if (!byLocation.has(gone.plannedFor)) this.publisher.resolve(gone.plannedFor, "writer-restart");
|
|
15398
|
+
this.previous = moves;
|
|
15399
|
+
}
|
|
15400
|
+
};
|
|
15401
|
+
//#endregion
|
|
15108
15402
|
//#region src/recorder/addon/placement-guard.ts
|
|
15109
15403
|
/**
|
|
15110
15404
|
* Same-root guard for recordings placement.
|
|
@@ -15749,6 +16043,9 @@ var PlacementService = class {
|
|
|
15749
16043
|
verified = /* @__PURE__ */ new Set();
|
|
15750
16044
|
/** Locations the probe declared unusable — re-probed after a change. */
|
|
15751
16045
|
unusable = /* @__PURE__ */ new Set();
|
|
16046
|
+
/** Locations with an OPEN mount-fault alert. Survives a re-resolve (unlike
|
|
16047
|
+
* `unusable`): the alert closes only when the probe verifies the volume. */
|
|
16048
|
+
faulted = /* @__PURE__ */ new Set();
|
|
15752
16049
|
/** Locations whose capacity could not be read, by reason. One line per
|
|
15753
16050
|
* distinct fault (this is on the 30 s tick) and one when it clears. */
|
|
15754
16051
|
capacityFaults = /* @__PURE__ */ new Map();
|
|
@@ -16263,6 +16560,7 @@ var PlacementService = class {
|
|
|
16263
16560
|
return chosen;
|
|
16264
16561
|
}
|
|
16265
16562
|
this.verified.add(chosen.id);
|
|
16563
|
+
this.reportMountRecovered(chosen.id);
|
|
16266
16564
|
if (result.outcome === "adopted" && result.foundVolumeId !== null) {
|
|
16267
16565
|
try {
|
|
16268
16566
|
await rememberVolumeId(this.deps.state, chosen.id, result.foundVolumeId);
|
|
@@ -16286,6 +16584,13 @@ var PlacementService = class {
|
|
|
16286
16584
|
}
|
|
16287
16585
|
return chosen;
|
|
16288
16586
|
}
|
|
16587
|
+
/** The probe verified a location that had an open fault: close its alert. */
|
|
16588
|
+
reportMountRecovered(locationId) {
|
|
16589
|
+
if (!this.faulted.delete(locationId)) return;
|
|
16590
|
+
try {
|
|
16591
|
+
this.deps.recovered?.(locationId);
|
|
16592
|
+
} catch {}
|
|
16593
|
+
}
|
|
16289
16594
|
/** One loud line + one alert + one audit row per mount fault. */
|
|
16290
16595
|
reportMountFault(result, deviceId) {
|
|
16291
16596
|
this.deps.logger.error("recorder placement: storage volume MISMATCH — the disk under this location is not the one it last wrote to; failing over", {
|
|
@@ -16299,8 +16604,10 @@ var PlacementService = class {
|
|
|
16299
16604
|
}
|
|
16300
16605
|
});
|
|
16301
16606
|
try {
|
|
16607
|
+
this.faulted.add(result.locationId);
|
|
16302
16608
|
this.deps.alert?.({
|
|
16303
16609
|
locationId: result.locationId,
|
|
16610
|
+
reason: "unusable",
|
|
16304
16611
|
detail: result.detail
|
|
16305
16612
|
});
|
|
16306
16613
|
} catch {}
|
|
@@ -23558,6 +23865,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
23558
23865
|
state: this.placementStore(),
|
|
23559
23866
|
opsLog,
|
|
23560
23867
|
alert: (input) => this.emitPlacementAlert(input),
|
|
23868
|
+
recovered: (locationId) => this.resolvePlacementAlert(locationId),
|
|
23561
23869
|
capacityFor: (location) => this.locationCapacity(location.root),
|
|
23562
23870
|
usedOnLocation: async (locationId) => (await this.segmentHours?.accountingForLocations(new Set([locationId])))?.bytes ?? 0,
|
|
23563
23871
|
dailyBytesFor: (deviceId, profile) => this.dailyBytesFor(deviceId, profile)
|
|
@@ -23759,6 +24067,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
23759
24067
|
resumeForStorageMigration: (leaseId) => this.resumeForStorageMigration(leaseId),
|
|
23760
24068
|
refreshStorageLocationsForMigration: (leaseId) => this.refreshStorageLocationsForMigration(leaseId),
|
|
23761
24069
|
assertStorageMigrationLease: (leaseId) => this.assertStorageMigrationLease(leaseId),
|
|
24070
|
+
moverClearance: (locationIds) => this.ctx.api.storageMigration.moverClearance.query({ locationIds }),
|
|
23762
24071
|
placementSnapshot: () => this.placementSnapshot(),
|
|
23763
24072
|
placementView: () => {
|
|
23764
24073
|
const placement = this.placement;
|
|
@@ -24734,6 +25043,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
24734
25043
|
} });
|
|
24735
25044
|
this.emitPlacementAlert({
|
|
24736
25045
|
locationId: conflict.keptId,
|
|
25046
|
+
reason: "shared-root",
|
|
24737
25047
|
detail: `Storage locations ${[conflict.keptId, ...conflict.demotedIds].join(", ")} all resolve to ${conflict.root}. Only ${conflict.keptId} will be written to.`
|
|
24738
25048
|
});
|
|
24739
25049
|
}
|
|
@@ -24872,6 +25182,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
24872
25182
|
const signature = pendingMovesSignature(moves);
|
|
24873
25183
|
if (signature === this.pendingWriterMoves) return;
|
|
24874
25184
|
this.pendingWriterMoves = signature;
|
|
25185
|
+
this.writerRestartAlerts().update(moves);
|
|
24875
25186
|
if (moves.length === 0) return;
|
|
24876
25187
|
for (const move of moves) this.ctx.logger.warn("recorder placement: this camera is PLANNED for another location and its writer will not move until it next attaches", {
|
|
24877
25188
|
tags: { deviceId: move.deviceId },
|
|
@@ -24882,12 +25193,6 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
24882
25193
|
hint: "a continuously-recording camera never re-attaches on its own — toggle its recording switch, or restart the recorder, to apply the plan (each costs one gap on that camera)"
|
|
24883
25194
|
}
|
|
24884
25195
|
});
|
|
24885
|
-
this.emitAlert({
|
|
24886
|
-
severity: "warning",
|
|
24887
|
-
title: "Recording placement waiting on a writer restart",
|
|
24888
|
-
message: `${String(moves.length)} recording profile(s) are planned for a different storage location and will keep writing to their current one until each camera next attaches. Continuously-recording cameras never re-attach on their own.`,
|
|
24889
|
-
locationId: moves[0]?.plannedFor ?? ""
|
|
24890
|
-
});
|
|
24891
25196
|
}
|
|
24892
25197
|
/**
|
|
24893
25198
|
* A placement pass that plans NOTHING says so — once per episode.
|
|
@@ -25109,38 +25414,34 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
25109
25414
|
/**
|
|
25110
25415
|
* Surface a storage-placement fault on the liveness/alert surface. STRICTLY
|
|
25111
25416
|
* best-effort: the alerts cap is a nice-to-have and an unmounted disk must
|
|
25112
|
-
* still be shouted about in the log even when it is unreachable.
|
|
25417
|
+
* still be shouted about in the log even when it is unreachable. One row per
|
|
25418
|
+
* (location, reason) episode - see `placement-alerts.ts`.
|
|
25113
25419
|
*/
|
|
25114
25420
|
emitPlacementAlert(input) {
|
|
25115
|
-
this.
|
|
25116
|
-
|
|
25117
|
-
|
|
25118
|
-
|
|
25119
|
-
|
|
25120
|
-
|
|
25121
|
-
|
|
25122
|
-
|
|
25123
|
-
|
|
25124
|
-
|
|
25125
|
-
this.
|
|
25126
|
-
|
|
25127
|
-
|
|
25128
|
-
|
|
25129
|
-
|
|
25130
|
-
|
|
25131
|
-
|
|
25132
|
-
read: false,
|
|
25133
|
-
createdAt: Date.now(),
|
|
25134
|
-
updatedAt: Date.now(),
|
|
25135
|
-
source: {
|
|
25136
|
-
type: "addon",
|
|
25137
|
-
id: this.ctx.id
|
|
25421
|
+
this.placementAlerts().raise(input);
|
|
25422
|
+
}
|
|
25423
|
+
/** The faulted location passed its volume probe again: close its alert. */
|
|
25424
|
+
resolvePlacementAlert(locationId) {
|
|
25425
|
+
this.placementAlerts().resolve(locationId, "unusable");
|
|
25426
|
+
}
|
|
25427
|
+
placementAlertPublisher = null;
|
|
25428
|
+
writerRestartAlertSync = null;
|
|
25429
|
+
writerRestartAlerts() {
|
|
25430
|
+
this.writerRestartAlertSync ??= new WriterRestartAlerts(this.placementAlerts(), this.ctx.logger);
|
|
25431
|
+
return this.writerRestartAlertSync;
|
|
25432
|
+
}
|
|
25433
|
+
placementAlerts() {
|
|
25434
|
+
this.placementAlertPublisher ??= new PlacementAlertPublisher({
|
|
25435
|
+
port: {
|
|
25436
|
+
emit: (alert) => this.ctx.api.alerts.emit.mutate(alert),
|
|
25437
|
+
update: (input) => this.ctx.api.alerts.update.mutate(input)
|
|
25138
25438
|
},
|
|
25139
|
-
|
|
25140
|
-
|
|
25141
|
-
|
|
25142
|
-
|
|
25143
|
-
})
|
|
25439
|
+
logger: this.ctx.logger,
|
|
25440
|
+
sourceId: this.ctx.id,
|
|
25441
|
+
nodeId: this.nodeId,
|
|
25442
|
+
now: () => Date.now()
|
|
25443
|
+
});
|
|
25444
|
+
return this.placementAlertPublisher;
|
|
25144
25445
|
}
|
|
25145
25446
|
async pauseForStorageMigration(leaseId) {
|
|
25146
25447
|
if (this.storageMigrationLeaseId !== null && this.storageMigrationLeaseId !== leaseId) throw new Error("recorder is already paused by another storage migration");
|