camstack 1.2.70 → 1.2.71
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.
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-CFTKQGym.js
|
|
23637
|
+
var require_dist_CFTKQGym = __commonJS({
|
|
23638
|
+
"../system/dist/dist-CFTKQGym.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -26326,6 +26326,13 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
26326
26326
|
]);
|
|
26327
26327
|
var RelocateMediaInputSchema = zod.z.object({
|
|
26328
26328
|
toLocationId: zod.z.string(),
|
|
26329
|
+
/**
|
|
26330
|
+
* Restrict the pass to rows currently on this location. Omitted / `'*'` =
|
|
26331
|
+
* every row that is not already on `toLocationId` (the historical
|
|
26332
|
+
* behaviour). A named source is what a from→to migration needs: without it
|
|
26333
|
+
* "move events off disk 2" also emptied disk 1.
|
|
26334
|
+
*/
|
|
26335
|
+
fromLocationId: zod.z.string().optional(),
|
|
26329
26336
|
throttleMbps: zod.z.number().min(1).max(1e3).optional(),
|
|
26330
26337
|
/** Omitted = `move`, the pre-existing behaviour. */
|
|
26331
26338
|
mode: MediaRelocateModeSchema.optional()
|
|
@@ -26357,9 +26364,18 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
26357
26364
|
backups: zod.z.string().min(1).optional(),
|
|
26358
26365
|
galleryMedia: zod.z.string().min(1).optional()
|
|
26359
26366
|
}).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
|
|
26367
|
+
var StorageMigrationSourcesSchema = zod.z.object({
|
|
26368
|
+
recordings: zod.z.string().min(1).optional(),
|
|
26369
|
+
recordingsLow: zod.z.string().min(1).optional(),
|
|
26370
|
+
eventMedia: zod.z.string().min(1).optional(),
|
|
26371
|
+
backups: zod.z.string().min(1).optional(),
|
|
26372
|
+
galleryMedia: zod.z.string().min(1).optional()
|
|
26373
|
+
}).optional();
|
|
26360
26374
|
var StorageMigrationModeSchema = zod.z.enum(["blocking", "nonBlocking"]);
|
|
26361
26375
|
var StorageMigrationInputSchema = zod.z.object({
|
|
26362
26376
|
destinations: StorageMigrationDestinationsSchema,
|
|
26377
|
+
/** Omitted = each class's current default. */
|
|
26378
|
+
sources: StorageMigrationSourcesSchema,
|
|
26363
26379
|
throttleMbps: zod.z.number().min(1).max(1e3).optional(),
|
|
26364
26380
|
/** Omitted = `blocking`, which stays the default. */
|
|
26365
26381
|
mode: StorageMigrationModeSchema.optional()
|
|
@@ -26405,6 +26421,13 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
26405
26421
|
storageClass: StorageMigrationClassSchema,
|
|
26406
26422
|
fromLocationId: zod.z.string(),
|
|
26407
26423
|
toLocationId: zod.z.string(),
|
|
26424
|
+
/**
|
|
26425
|
+
* True when `from` was NOT the class default at plan time. The move still
|
|
26426
|
+
* copies bytes, but the default is left alone and the source is disabled
|
|
26427
|
+
* once the copy verifies. Absent on jobs planned before this field existed
|
|
26428
|
+
* — those jobs always repointed, which is `false`.
|
|
26429
|
+
*/
|
|
26430
|
+
freezeSource: zod.z.boolean().optional(),
|
|
26408
26431
|
moverJobId: zod.z.string().nullable(),
|
|
26409
26432
|
state: RelocateJobStateSchema.nullable(),
|
|
26410
26433
|
error: zod.z.string().nullable(),
|
|
@@ -26418,6 +26441,7 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
26418
26441
|
* can tell a seconds-long cutover from a thirty-hour one. */
|
|
26419
26442
|
mode: StorageMigrationModeSchema,
|
|
26420
26443
|
destinations: StorageMigrationDestinationsSchema,
|
|
26444
|
+
sources: StorageMigrationSourcesSchema,
|
|
26421
26445
|
throttleMbps: zod.z.number(),
|
|
26422
26446
|
moves: zod.z.array(StorageMigrationMoveSchema),
|
|
26423
26447
|
pauseLeaseId: zod.z.string().nullable(),
|
|
@@ -26444,6 +26468,7 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
26444
26468
|
});
|
|
26445
26469
|
var StorageMigrationPlanSchema = zod.z.object({
|
|
26446
26470
|
destinations: StorageMigrationDestinationsSchema,
|
|
26471
|
+
sources: StorageMigrationSourcesSchema,
|
|
26447
26472
|
/** The mode this plan was built for. A plan is only valid for its mode: the
|
|
26448
26473
|
* `eventMedia` seal gate and the single-cardinality refusal both depend on
|
|
26449
26474
|
* it. */
|
|
@@ -26451,7 +26476,8 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
26451
26476
|
moves: zod.z.array(zod.z.object({
|
|
26452
26477
|
storageClass: StorageMigrationClassSchema,
|
|
26453
26478
|
fromLocationId: zod.z.string(),
|
|
26454
|
-
toLocationId: zod.z.string()
|
|
26479
|
+
toLocationId: zod.z.string(),
|
|
26480
|
+
freezeSource: zod.z.boolean().optional()
|
|
26455
26481
|
})),
|
|
26456
26482
|
findings: zod.z.array(StorageMigrationFindingSchema)
|
|
26457
26483
|
});
|
|
@@ -26563,9 +26589,42 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
26563
26589
|
var RelocatableMediaCountSchema = zod.z.object({ rows: zod.z.number().int().nonnegative() }).nullable();
|
|
26564
26590
|
var RelocatableMediaCountInputSchema = zod.z.object({
|
|
26565
26591
|
toLocationId: zod.z.string().min(1),
|
|
26592
|
+
/** Restrict the count to one source; omitted / `'*'` = every non-target row. */
|
|
26593
|
+
fromLocationId: zod.z.string().optional(),
|
|
26566
26594
|
/** Omitted = `move`. */
|
|
26567
26595
|
mode: MediaRelocateModeSchema.optional()
|
|
26568
26596
|
});
|
|
26597
|
+
var StorageCleanupPhaseSchema = zod.z.enum([
|
|
26598
|
+
"orphans",
|
|
26599
|
+
"debug-media",
|
|
26600
|
+
"ghost-ledger",
|
|
26601
|
+
"done",
|
|
26602
|
+
"failed",
|
|
26603
|
+
"cancelled"
|
|
26604
|
+
]);
|
|
26605
|
+
var StorageCleanupInputSchema = zod.z.object({
|
|
26606
|
+
/** Also walk motion stills / track filmstrips. Off by default. */
|
|
26607
|
+
includeDebugMedia: zod.z.boolean().optional()
|
|
26608
|
+
});
|
|
26609
|
+
var StorageCleanupJobSchema = zod.z.object({
|
|
26610
|
+
jobId: zod.z.string(),
|
|
26611
|
+
phase: StorageCleanupPhaseSchema,
|
|
26612
|
+
includeDebugMedia: zod.z.boolean(),
|
|
26613
|
+
orphansReclaimed: zod.z.number().int().nonnegative(),
|
|
26614
|
+
orphanBytesReclaimed: zod.z.number().int().nonnegative(),
|
|
26615
|
+
debugMediaReclaimed: zod.z.number().int().nonnegative(),
|
|
26616
|
+
debugMediaBytesReclaimed: zod.z.number().int().nonnegative(),
|
|
26617
|
+
ghostsForgotten: zod.z.number().int().nonnegative(),
|
|
26618
|
+
ghostBytesForgotten: zod.z.number().int().nonnegative(),
|
|
26619
|
+
/** Short operator-facing line: current collection, pass, or location. */
|
|
26620
|
+
detail: zod.z.string().nullable(),
|
|
26621
|
+
cancelRequested: zod.z.boolean(),
|
|
26622
|
+
startedAt: zod.z.number(),
|
|
26623
|
+
updatedAt: zod.z.number(),
|
|
26624
|
+
finishedAt: zod.z.number().nullable(),
|
|
26625
|
+
error: zod.z.string().nullable()
|
|
26626
|
+
});
|
|
26627
|
+
var StorageCleanupStatusInputSchema = zod.z.object({ jobId: zod.z.string().optional() });
|
|
26569
26628
|
var StorageLocationTypeSchema = zod.z.string().regex(/^[a-z][a-zA-Z0-9-]*$/);
|
|
26570
26629
|
var StorageLocationSchema = zod.z.object({
|
|
26571
26630
|
id: zod.z.string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
|
|
@@ -40343,7 +40402,23 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
40343
40402
|
drain: method(StorageMigrationDrainInputSchema, zod.z.object({ jobId: zod.z.string() }), {
|
|
40344
40403
|
kind: "mutation",
|
|
40345
40404
|
auth: "admin"
|
|
40346
|
-
})
|
|
40405
|
+
}),
|
|
40406
|
+
/**
|
|
40407
|
+
* One operator cleanup of leftover analytics (DB + blobs) and ghost
|
|
40408
|
+
* ledger rows on frozen footage locations. Optional debug-media sweep.
|
|
40409
|
+
* Returns immediately; poll {@link cleanupStatus}.
|
|
40410
|
+
*/
|
|
40411
|
+
cleanupStart: method(StorageCleanupInputSchema, zod.z.object({ jobId: zod.z.string() }), {
|
|
40412
|
+
kind: "mutation",
|
|
40413
|
+
auth: "admin"
|
|
40414
|
+
}),
|
|
40415
|
+
cleanupStatus: method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }),
|
|
40416
|
+
cleanupCancel: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
|
|
40417
|
+
kind: "mutation",
|
|
40418
|
+
auth: "admin"
|
|
40419
|
+
}),
|
|
40420
|
+
/** Recent finished migration jobs, newest first. The live job is `status`. */
|
|
40421
|
+
history: method(zod.z.object({}), zod.z.array(StorageMigrationJobSchema).readonly(), { auth: "admin" })
|
|
40347
40422
|
}
|
|
40348
40423
|
};
|
|
40349
40424
|
var ProviderInfoSchema = zod.z.discriminatedUnion("shouldSaveDiskSpace", [zod.z.object({
|
|
@@ -47135,6 +47210,26 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
47135
47210
|
/** Ignore piles smaller than this (default 1 GB). */
|
|
47136
47211
|
minMoveGb: zod.z.number().min(0).optional()
|
|
47137
47212
|
});
|
|
47213
|
+
var RecordingDevicePlacementSchema = zod.z.object({
|
|
47214
|
+
deviceId: zod.z.number().int(),
|
|
47215
|
+
profile: zod.z.string(),
|
|
47216
|
+
locationId: zod.z.string()
|
|
47217
|
+
});
|
|
47218
|
+
var RecordingDevicePinSchema = zod.z.object({
|
|
47219
|
+
deviceId: zod.z.number().int(),
|
|
47220
|
+
/** Recordings-class location this camera is pinned to. */
|
|
47221
|
+
locationId: zod.z.string()
|
|
47222
|
+
});
|
|
47223
|
+
var RecordingPlacementViewSchema = zod.z.object({
|
|
47224
|
+
assignments: zod.z.array(RecordingDevicePlacementSchema),
|
|
47225
|
+
pins: zod.z.array(RecordingDevicePinSchema),
|
|
47226
|
+
defaultLocations: zod.z.record(zod.z.string(), zod.z.string())
|
|
47227
|
+
});
|
|
47228
|
+
var RecordingSetDevicePlacementInputSchema = zod.z.object({
|
|
47229
|
+
deviceId: zod.z.number().int(),
|
|
47230
|
+
/** `null` = Auto. Otherwise a `recordings:*` location id. */
|
|
47231
|
+
locationId: zod.z.string().nullable()
|
|
47232
|
+
});
|
|
47138
47233
|
var LocateSegmentResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
47139
47234
|
kind: zod.z.literal("segment"),
|
|
47140
47235
|
startMs: zod.z.number(),
|
|
@@ -47453,6 +47548,22 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
47453
47548
|
startStorageRebalance: method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
|
|
47454
47549
|
kind: "mutation",
|
|
47455
47550
|
auth: "admin"
|
|
47551
|
+
}),
|
|
47552
|
+
/**
|
|
47553
|
+
* The placement plan in force plus operator pins. Drives the Locations
|
|
47554
|
+
* admin page: Auto vs a named recordings location, per camera.
|
|
47555
|
+
*/
|
|
47556
|
+
getPlacement: method(zod.z.object({}), RecordingPlacementViewSchema, {
|
|
47557
|
+
kind: "query",
|
|
47558
|
+
auth: "admin"
|
|
47559
|
+
}),
|
|
47560
|
+
/**
|
|
47561
|
+
* Pin a camera to a recordings location, or clear the pin (Auto). High and
|
|
47562
|
+
* mid follow the pin; low stays with the recordingsLow planner.
|
|
47563
|
+
*/
|
|
47564
|
+
setDevicePlacement: method(RecordingSetDevicePlacementInputSchema, zod.z.object({ ok: zod.z.literal(true) }), {
|
|
47565
|
+
kind: "mutation",
|
|
47566
|
+
auth: "admin"
|
|
47456
47567
|
})
|
|
47457
47568
|
}
|
|
47458
47569
|
};
|
|
@@ -54676,6 +54787,12 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
54676
54787
|
addonId: null,
|
|
54677
54788
|
access: "view"
|
|
54678
54789
|
},
|
|
54790
|
+
"recording.getPlacement": {
|
|
54791
|
+
capName: "recording",
|
|
54792
|
+
capScope: "system",
|
|
54793
|
+
addonId: null,
|
|
54794
|
+
access: "view"
|
|
54795
|
+
},
|
|
54679
54796
|
"recording.getPlaybackManifest": {
|
|
54680
54797
|
capName: "recording",
|
|
54681
54798
|
capScope: "system",
|
|
@@ -54802,6 +54919,12 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
54802
54919
|
addonId: null,
|
|
54803
54920
|
access: "create"
|
|
54804
54921
|
},
|
|
54922
|
+
"recording.setDevicePlacement": {
|
|
54923
|
+
capName: "recording",
|
|
54924
|
+
capScope: "system",
|
|
54925
|
+
addonId: null,
|
|
54926
|
+
access: "create"
|
|
54927
|
+
},
|
|
54805
54928
|
"recording.startStorageMigrationMove": {
|
|
54806
54929
|
capName: "recording",
|
|
54807
54930
|
capScope: "system",
|
|
@@ -55246,12 +55369,36 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
55246
55369
|
addonId: null,
|
|
55247
55370
|
access: "create"
|
|
55248
55371
|
},
|
|
55372
|
+
"storageMigration.cleanupCancel": {
|
|
55373
|
+
capName: "storage-migration",
|
|
55374
|
+
capScope: "system",
|
|
55375
|
+
addonId: null,
|
|
55376
|
+
access: "create"
|
|
55377
|
+
},
|
|
55378
|
+
"storageMigration.cleanupStart": {
|
|
55379
|
+
capName: "storage-migration",
|
|
55380
|
+
capScope: "system",
|
|
55381
|
+
addonId: null,
|
|
55382
|
+
access: "create"
|
|
55383
|
+
},
|
|
55384
|
+
"storageMigration.cleanupStatus": {
|
|
55385
|
+
capName: "storage-migration",
|
|
55386
|
+
capScope: "system",
|
|
55387
|
+
addonId: null,
|
|
55388
|
+
access: "view"
|
|
55389
|
+
},
|
|
55249
55390
|
"storageMigration.drain": {
|
|
55250
55391
|
capName: "storage-migration",
|
|
55251
55392
|
capScope: "system",
|
|
55252
55393
|
addonId: null,
|
|
55253
55394
|
access: "create"
|
|
55254
55395
|
},
|
|
55396
|
+
"storageMigration.history": {
|
|
55397
|
+
capName: "storage-migration",
|
|
55398
|
+
capScope: "system",
|
|
55399
|
+
addonId: null,
|
|
55400
|
+
access: "view"
|
|
55401
|
+
},
|
|
55255
55402
|
"storageMigration.movers": {
|
|
55256
55403
|
capName: "storage-migration",
|
|
55257
55404
|
capScope: "system",
|
|
@@ -57738,6 +57885,11 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
57738
57885
|
form: "single",
|
|
57739
57886
|
optional: false
|
|
57740
57887
|
}],
|
|
57888
|
+
"recording.setDevicePlacement": [{
|
|
57889
|
+
name: "deviceId",
|
|
57890
|
+
form: "single",
|
|
57891
|
+
optional: false
|
|
57892
|
+
}],
|
|
57741
57893
|
"recording.startStorageMigrationMove": [{
|
|
57742
57894
|
name: "deviceId",
|
|
57743
57895
|
form: "single",
|
|
@@ -58978,6 +59130,12 @@ var require_dist_BhE8zNfY = __commonJS({
|
|
|
58978
59130
|
return ScopedTokenSchema;
|
|
58979
59131
|
}
|
|
58980
59132
|
});
|
|
59133
|
+
Object.defineProperty(exports, "StorageCleanupJobSchema", {
|
|
59134
|
+
enumerable: true,
|
|
59135
|
+
get: function() {
|
|
59136
|
+
return StorageCleanupJobSchema;
|
|
59137
|
+
}
|
|
59138
|
+
});
|
|
58981
59139
|
Object.defineProperty(exports, "StorageLocationTypeSchema", {
|
|
58982
59140
|
enumerable: true,
|
|
58983
59141
|
get: function() {
|
|
@@ -59482,7 +59640,7 @@ var require_alerts_addon = __commonJS({
|
|
|
59482
59640
|
[Symbol.toStringTag]: { value: "Module" }
|
|
59483
59641
|
});
|
|
59484
59642
|
require_chunk_Cek0wNdY();
|
|
59485
|
-
var require_dist10 =
|
|
59643
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
59486
59644
|
function selectExpired(alerts, cutoffMs) {
|
|
59487
59645
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
59488
59646
|
}
|
|
@@ -60301,7 +60459,7 @@ var require_console_logging = __commonJS({
|
|
|
60301
60459
|
[Symbol.toStringTag]: { value: "Module" }
|
|
60302
60460
|
});
|
|
60303
60461
|
require_chunk_Cek0wNdY();
|
|
60304
|
-
var require_dist10 =
|
|
60462
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
60305
60463
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
60306
60464
|
var LEVEL_RANK = {
|
|
60307
60465
|
debug: 0,
|
|
@@ -60395,7 +60553,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
60395
60553
|
"use strict";
|
|
60396
60554
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
60397
60555
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
60398
|
-
var require_dist10 =
|
|
60556
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
60399
60557
|
var node_crypto = __require("crypto");
|
|
60400
60558
|
var node_fs_promises = __require("fs/promises");
|
|
60401
60559
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -61292,11 +61450,11 @@ var require_core_blocks = __commonJS({
|
|
|
61292
61450
|
}
|
|
61293
61451
|
});
|
|
61294
61452
|
|
|
61295
|
-
// ../system/dist/retired-settings-keys-
|
|
61296
|
-
var
|
|
61297
|
-
"../system/dist/retired-settings-keys-
|
|
61453
|
+
// ../system/dist/retired-settings-keys-dehyu2N3.js
|
|
61454
|
+
var require_retired_settings_keys_dehyu2N3 = __commonJS({
|
|
61455
|
+
"../system/dist/retired-settings-keys-dehyu2N3.js"(exports) {
|
|
61298
61456
|
"use strict";
|
|
61299
|
-
var require_dist10 =
|
|
61457
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
61300
61458
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
61301
61459
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
61302
61460
|
return raw === "" || raw === "hub";
|
|
@@ -63510,8 +63668,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
63510
63668
|
[Symbol.toStringTag]: { value: "Module" }
|
|
63511
63669
|
});
|
|
63512
63670
|
require_chunk_Cek0wNdY();
|
|
63513
|
-
var require_dist10 =
|
|
63514
|
-
var require_retired_settings_keys =
|
|
63671
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
63672
|
+
var require_retired_settings_keys = require_retired_settings_keys_dehyu2N3();
|
|
63515
63673
|
var node_crypto = __require("crypto");
|
|
63516
63674
|
var _camstack_types_node = require_node();
|
|
63517
63675
|
var JOB_HISTORY = 20;
|
|
@@ -68327,7 +68485,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
68327
68485
|
[Symbol.toStringTag]: { value: "Module" }
|
|
68328
68486
|
});
|
|
68329
68487
|
require_chunk_Cek0wNdY();
|
|
68330
|
-
var require_dist10 =
|
|
68488
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
68331
68489
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
68332
68490
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
68333
68491
|
var HubForwarderDestination = class {
|
|
@@ -68464,7 +68622,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
68464
68622
|
"use strict";
|
|
68465
68623
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
68466
68624
|
require_chunk_Cek0wNdY();
|
|
68467
|
-
var require_dist10 =
|
|
68625
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
68468
68626
|
var NO_DEVICES = "liveness:no-devices";
|
|
68469
68627
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
68470
68628
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -68654,7 +68812,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
68654
68812
|
[Symbol.toStringTag]: { value: "Module" }
|
|
68655
68813
|
});
|
|
68656
68814
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
68657
|
-
var require_dist10 =
|
|
68815
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
68658
68816
|
var node_crypto = __require("crypto");
|
|
68659
68817
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
68660
68818
|
var crypto$1 = __require("crypto");
|
|
@@ -76467,7 +76625,7 @@ var require_loki_logging = __commonJS({
|
|
|
76467
76625
|
[Symbol.toStringTag]: { value: "Module" }
|
|
76468
76626
|
});
|
|
76469
76627
|
require_chunk_Cek0wNdY();
|
|
76470
|
-
var require_dist10 =
|
|
76628
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
76471
76629
|
function sanitizeLabelName(raw) {
|
|
76472
76630
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
76473
76631
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -77032,7 +77190,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77032
77190
|
[Symbol.toStringTag]: { value: "Module" }
|
|
77033
77191
|
});
|
|
77034
77192
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
77035
|
-
var require_dist10 =
|
|
77193
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
77036
77194
|
var node_fs_promises = __require("fs/promises");
|
|
77037
77195
|
var node_child_process = __require("child_process");
|
|
77038
77196
|
var node_util = __require("util");
|
|
@@ -79654,7 +79812,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
79654
79812
|
[Symbol.toStringTag]: { value: "Module" }
|
|
79655
79813
|
});
|
|
79656
79814
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
79657
|
-
var require_dist10 =
|
|
79815
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
79658
79816
|
var node_crypto = __require("crypto");
|
|
79659
79817
|
var node_fs_promises = __require("fs/promises");
|
|
79660
79818
|
var node_path = __require("path");
|
|
@@ -80770,8 +80928,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
80770
80928
|
[Symbol.toStringTag]: { value: "Module" }
|
|
80771
80929
|
});
|
|
80772
80930
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
80773
|
-
var require_dist10 =
|
|
80774
|
-
var require_retired_settings_keys =
|
|
80931
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
80932
|
+
var require_retired_settings_keys = require_retired_settings_keys_dehyu2N3();
|
|
80775
80933
|
var node_crypto = __require("crypto");
|
|
80776
80934
|
var node_fs = __require("fs");
|
|
80777
80935
|
var node_module = __require("module");
|
|
@@ -83180,7 +83338,8 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83180
83338
|
[Symbol.toStringTag]: { value: "Module" }
|
|
83181
83339
|
});
|
|
83182
83340
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
83183
|
-
var require_dist10 =
|
|
83341
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
83342
|
+
var zod = require_zod();
|
|
83184
83343
|
var node_crypto = __require("crypto");
|
|
83185
83344
|
var node_fs_promises = __require("fs/promises");
|
|
83186
83345
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -83402,17 +83561,22 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83402
83561
|
for (const storageClass of STORAGE_CLASSES) {
|
|
83403
83562
|
const targetId = input.destinations[storageClass];
|
|
83404
83563
|
if (targetId === void 0) continue;
|
|
83405
|
-
const
|
|
83406
|
-
|
|
83564
|
+
const namedSourceId = input.sources?.[storageClass];
|
|
83565
|
+
const defaultLoc = this.deps.locations.getDefaultLocation(storageClass);
|
|
83566
|
+
const source = namedSourceId ? this.deps.locations.getLocationById(namedSourceId) : defaultLoc;
|
|
83567
|
+
if (!source) throw new Error(namedSourceId ? `Storage location "${namedSourceId}" not found` : `No default storage location for "${storageClass}"`);
|
|
83568
|
+
if (source.type !== storageClass) throw new Error(`Storage location "${source.id}" is type "${source.type}", expected "${storageClass}"`);
|
|
83407
83569
|
const target = this.deps.locations.getLocationById(targetId);
|
|
83408
83570
|
if (!target) throw new Error(`Storage location "${targetId}" not found`);
|
|
83409
83571
|
if (target.type !== storageClass) throw new Error(`Storage location "${targetId}" is type "${target.type}", expected "${storageClass}"`);
|
|
83410
|
-
if (source.id === target.id) throw new Error(`Storage location "${targetId}" is already the "${storageClass}" default`);
|
|
83572
|
+
if (source.id === target.id) throw new Error(namedSourceId ? `Source and destination are the same location ("${targetId}")` : `Storage location "${targetId}" is already the "${storageClass}" default`);
|
|
83573
|
+
const freezeSource = defaultLoc !== void 0 && source.id !== defaultLoc.id;
|
|
83411
83574
|
if (!MOVER_CLASSES.includes(storageClass)) throw new Error(`No mover owns "${storageClass}" \u2014 the migration can repoint its default but cannot move its bytes. Move it by hand, then repoint the default with upsertLocation.`);
|
|
83412
83575
|
moves.push({
|
|
83413
83576
|
storageClass,
|
|
83414
83577
|
fromLocationId: source.id,
|
|
83415
83578
|
toLocationId: target.id,
|
|
83579
|
+
freezeSource,
|
|
83416
83580
|
moverJobId: null,
|
|
83417
83581
|
state: null,
|
|
83418
83582
|
error: null,
|
|
@@ -83443,11 +83607,13 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83443
83607
|
}
|
|
83444
83608
|
return {
|
|
83445
83609
|
destinations: input.destinations,
|
|
83610
|
+
sources: input.sources,
|
|
83446
83611
|
mode,
|
|
83447
|
-
moves: moves.map(({ storageClass, fromLocationId, toLocationId }) => ({
|
|
83612
|
+
moves: moves.map(({ storageClass, fromLocationId, toLocationId, freezeSource }) => ({
|
|
83448
83613
|
storageClass,
|
|
83449
83614
|
fromLocationId,
|
|
83450
|
-
toLocationId
|
|
83615
|
+
toLocationId,
|
|
83616
|
+
freezeSource
|
|
83451
83617
|
})),
|
|
83452
83618
|
findings
|
|
83453
83619
|
};
|
|
@@ -83477,12 +83643,12 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83477
83643
|
this.startReserved = true;
|
|
83478
83644
|
try {
|
|
83479
83645
|
const existing = await this.status();
|
|
83480
|
-
if (existing && isTerminal(existing) && existing.pausedParticipants.length > 0) {
|
|
83646
|
+
if (existing && isTerminal$1(existing) && existing.pausedParticipants.length > 0) {
|
|
83481
83647
|
await this.releaseAfterTerminal(existing);
|
|
83482
83648
|
await this.persist(existing);
|
|
83483
83649
|
if (existing.pausedParticipants.length > 0) throw new Error(`storage migration ${existing.jobId} still holds maintenance leases`);
|
|
83484
83650
|
}
|
|
83485
|
-
if (existing && !isTerminal(existing)) throw new Error(`storage migration is already active (${existing.jobId})`);
|
|
83651
|
+
if (existing && !isTerminal$1(existing)) throw new Error(`storage migration is already active (${existing.jobId})`);
|
|
83486
83652
|
const plan = await this.plan(input);
|
|
83487
83653
|
const now = this.deps.now();
|
|
83488
83654
|
const job = {
|
|
@@ -83490,6 +83656,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83490
83656
|
phase: "planning",
|
|
83491
83657
|
mode: plan.mode,
|
|
83492
83658
|
destinations: input.destinations,
|
|
83659
|
+
sources: input.sources,
|
|
83493
83660
|
throttleMbps: input.throttleMbps ?? 40,
|
|
83494
83661
|
moves: plan.moves.map((move) => ({
|
|
83495
83662
|
...move,
|
|
@@ -83521,10 +83688,15 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83521
83688
|
if (jobId !== void 0 && job?.jobId !== jobId) return null;
|
|
83522
83689
|
return job;
|
|
83523
83690
|
}
|
|
83691
|
+
/** Finished jobs, newest first, excluding the one `status` currently shows. */
|
|
83692
|
+
async history() {
|
|
83693
|
+
const current = await this.status();
|
|
83694
|
+
return (await this.deps.history?.get() ?? []).filter((job) => job.jobId !== current?.jobId);
|
|
83695
|
+
}
|
|
83524
83696
|
async cancel(jobId) {
|
|
83525
83697
|
const job = await this.status(jobId);
|
|
83526
83698
|
const cutoverInFlight = job !== null && job.repointed && (job.phase === "refreshing" || job.phase === "resuming");
|
|
83527
|
-
if (!job || isTerminal(job) || cutoverInFlight) return false;
|
|
83699
|
+
if (!job || isTerminal$1(job) || cutoverInFlight) return false;
|
|
83528
83700
|
job.cancelRequested = true;
|
|
83529
83701
|
await this.persist(job);
|
|
83530
83702
|
await Promise.all(job.moves.filter((move) => move.moverJobId !== null).map((move) => this.cancelMove(move)));
|
|
@@ -83581,18 +83753,22 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83581
83753
|
const target = this.deps.locations.getDefaultLocation(storageClass);
|
|
83582
83754
|
if (!target) continue;
|
|
83583
83755
|
if (laneOf(storageClass) === "media") {
|
|
83584
|
-
const
|
|
83585
|
-
|
|
83586
|
-
|
|
83587
|
-
|
|
83588
|
-
|
|
83589
|
-
|
|
83590
|
-
|
|
83591
|
-
|
|
83592
|
-
|
|
83593
|
-
|
|
83594
|
-
|
|
83595
|
-
|
|
83756
|
+
for (const source of this.deps.locations.listLocations({ type: storageClass })) {
|
|
83757
|
+
if (source.id === target.id) continue;
|
|
83758
|
+
const count = await unanswerable(this.deps.participants.analytics.residue({
|
|
83759
|
+
toLocationId: target.id,
|
|
83760
|
+
fromLocationId: source.id,
|
|
83761
|
+
mode: "move"
|
|
83762
|
+
}));
|
|
83763
|
+
if (count !== null && count.rows === 0) continue;
|
|
83764
|
+
out.push({
|
|
83765
|
+
storageClass,
|
|
83766
|
+
fromLocationId: source.id,
|
|
83767
|
+
toLocationId: target.id,
|
|
83768
|
+
items: count?.rows ?? null,
|
|
83769
|
+
bytes: null
|
|
83770
|
+
});
|
|
83771
|
+
}
|
|
83596
83772
|
continue;
|
|
83597
83773
|
}
|
|
83598
83774
|
for (const source of this.deps.locations.listLocations({ type: storageClass })) {
|
|
@@ -83646,12 +83822,12 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83646
83822
|
this.startReserved = true;
|
|
83647
83823
|
try {
|
|
83648
83824
|
const existing = await this.status();
|
|
83649
|
-
if (existing && isTerminal(existing) && existing.pausedParticipants.length > 0) {
|
|
83825
|
+
if (existing && isTerminal$1(existing) && existing.pausedParticipants.length > 0) {
|
|
83650
83826
|
await this.releaseAfterTerminal(existing);
|
|
83651
83827
|
await this.persist(existing);
|
|
83652
83828
|
if (existing.pausedParticipants.length > 0) throw new Error(`storage migration ${existing.jobId} still holds maintenance leases`);
|
|
83653
83829
|
}
|
|
83654
|
-
if (existing && !isTerminal(existing)) throw new Error(`storage migration is already active (${existing.jobId})`);
|
|
83830
|
+
if (existing && !isTerminal$1(existing)) throw new Error(`storage migration is already active (${existing.jobId})`);
|
|
83655
83831
|
for (const storageClass of input.classes) {
|
|
83656
83832
|
if (MOVER_CLASSES.includes(storageClass)) continue;
|
|
83657
83833
|
throw new Error(`No mover owns "${storageClass}" \u2014 there is nothing that can drain it. Move it by hand.`);
|
|
@@ -83716,7 +83892,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83716
83892
|
await this.persist(job);
|
|
83717
83893
|
return;
|
|
83718
83894
|
}
|
|
83719
|
-
if (isTerminal(job)) {
|
|
83895
|
+
if (isTerminal$1(job)) {
|
|
83720
83896
|
if (job.pausedParticipants.length > 0) {
|
|
83721
83897
|
await this.releaseAfterTerminal(job);
|
|
83722
83898
|
await this.persist(job);
|
|
@@ -83777,11 +83953,12 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83777
83953
|
if (job.phase === "verifying" && !nonBlocking) {
|
|
83778
83954
|
await this.verifyMoves(job);
|
|
83779
83955
|
if (job.cancelRequested) return this.finishCancelled(job);
|
|
83956
|
+
await this.freezeDrainedSources(job);
|
|
83780
83957
|
await this.setPhase(job, "repointing");
|
|
83781
83958
|
}
|
|
83782
83959
|
if (job.phase === "repointing") {
|
|
83783
|
-
const targets = new Map(job.moves.map((move) => [move.storageClass, move.toLocationId]));
|
|
83784
|
-
await this.deps.locations.setDefaultLocations(targets);
|
|
83960
|
+
const targets = new Map(job.moves.filter((move) => move.freezeSource !== true).map((move) => [move.storageClass, move.toLocationId]));
|
|
83961
|
+
if (targets.size > 0) await this.deps.locations.setDefaultLocations(targets);
|
|
83785
83962
|
job.repointed = true;
|
|
83786
83963
|
await this.setPhase(job, "refreshing");
|
|
83787
83964
|
}
|
|
@@ -83804,6 +83981,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83804
83981
|
if (job.phase === "verifying" && nonBlocking) {
|
|
83805
83982
|
await this.verifyMoves(job);
|
|
83806
83983
|
if (job.cancelRequested) return this.finishCancelled(job);
|
|
83984
|
+
await this.freezeDrainedSources(job);
|
|
83807
83985
|
await this.setPhase(job, "done");
|
|
83808
83986
|
}
|
|
83809
83987
|
} catch (err) {
|
|
@@ -83819,7 +83997,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83819
83997
|
await this.releaseAfterTerminal(job);
|
|
83820
83998
|
await this.persist(job);
|
|
83821
83999
|
} finally {
|
|
83822
|
-
if (isTerminal(job)) {
|
|
84000
|
+
if (isTerminal$1(job)) {
|
|
83823
84001
|
await this.releaseAfterTerminal(job);
|
|
83824
84002
|
this.active = job;
|
|
83825
84003
|
}
|
|
@@ -83980,6 +84158,24 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83980
84158
|
for (const move of job.moves) if (move.state !== "done") throw new Error(`${move.storageClass} move did not complete verification`);
|
|
83981
84159
|
}
|
|
83982
84160
|
/**
|
|
84161
|
+
* After a from→to copy whose source was NOT the class default: stop new
|
|
84162
|
+
* writes to `from`. The default is unchanged (that is the whole point of
|
|
84163
|
+
* naming a non-default source). A location that is already disabled is
|
|
84164
|
+
* left alone.
|
|
84165
|
+
*/
|
|
84166
|
+
freezeDrainedSources(job) {
|
|
84167
|
+
for (const move of job.moves) {
|
|
84168
|
+
if (move.freezeSource !== true) continue;
|
|
84169
|
+
const loc = this.deps.locations.getLocationById(move.fromLocationId);
|
|
84170
|
+
if (!loc || loc.enabled === false) continue;
|
|
84171
|
+
const { createdAt: _c, updatedAt: _u, capacity: _cap, ...rest } = loc;
|
|
84172
|
+
this.deps.locations.upsertLocation({
|
|
84173
|
+
...rest,
|
|
84174
|
+
enabled: false
|
|
84175
|
+
});
|
|
84176
|
+
}
|
|
84177
|
+
}
|
|
84178
|
+
/**
|
|
83983
84179
|
* Arm one class's mover.
|
|
83984
84180
|
*
|
|
83985
84181
|
* `draining` runs after every writer has been resumed, so there is no lease
|
|
@@ -83992,6 +84188,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
83992
84188
|
if (laneOf(move.storageClass) === "media") {
|
|
83993
84189
|
const input2 = {
|
|
83994
84190
|
toLocationId: move.toLocationId,
|
|
84191
|
+
fromLocationId: move.fromLocationId,
|
|
83995
84192
|
throttleMbps: job.throttleMbps,
|
|
83996
84193
|
mode: "move"
|
|
83997
84194
|
};
|
|
@@ -84025,7 +84222,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84025
84222
|
}
|
|
84026
84223
|
async setPhase(job, phase) {
|
|
84027
84224
|
job.phase = phase;
|
|
84028
|
-
if (isTerminal(job)) job.finishedAt = this.deps.now();
|
|
84225
|
+
if (isTerminal$1(job)) job.finishedAt = this.deps.now();
|
|
84029
84226
|
await this.persist(job);
|
|
84030
84227
|
}
|
|
84031
84228
|
async finishCancelled(job) {
|
|
@@ -84037,6 +84234,9 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84037
84234
|
async persist(job) {
|
|
84038
84235
|
job.updatedAt = this.deps.now();
|
|
84039
84236
|
await this.deps.state.set(job);
|
|
84237
|
+
if (!isTerminal$1(job) || this.deps.history === void 0) return;
|
|
84238
|
+
const prev = [...await this.deps.history.get() ?? []];
|
|
84239
|
+
await this.deps.history.set([job, ...prev.filter((row) => row.jobId !== job.jobId)].slice(0, HISTORY_CAP));
|
|
84040
84240
|
}
|
|
84041
84241
|
};
|
|
84042
84242
|
async function unanswerable(read) {
|
|
@@ -84050,9 +84250,10 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84050
84250
|
if (job.pauseLeaseId === null) throw new Error("storage migration has no maintenance lease");
|
|
84051
84251
|
return job.pauseLeaseId;
|
|
84052
84252
|
}
|
|
84053
|
-
function isTerminal(job) {
|
|
84253
|
+
function isTerminal$1(job) {
|
|
84054
84254
|
return job.phase === "done" || job.phase === "failed" || job.phase === "cancelled";
|
|
84055
84255
|
}
|
|
84256
|
+
var HISTORY_CAP = 20;
|
|
84056
84257
|
function laneOf(storageClass) {
|
|
84057
84258
|
return storageClass === "eventMedia" ? "media" : "footage";
|
|
84058
84259
|
}
|
|
@@ -84105,6 +84306,46 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84105
84306
|
function canProbeOccupancyLocally(locality) {
|
|
84106
84307
|
return locality === true;
|
|
84107
84308
|
}
|
|
84309
|
+
var STORAGE_CLASS_SUBTREES = {
|
|
84310
|
+
eventMedia: ["events"],
|
|
84311
|
+
recordingsLow: ["low"],
|
|
84312
|
+
recordings: ["high", "mid"]
|
|
84313
|
+
};
|
|
84314
|
+
function isDotEntry(name) {
|
|
84315
|
+
return name.startsWith(".");
|
|
84316
|
+
}
|
|
84317
|
+
async function dirHasAnyEntry(dir) {
|
|
84318
|
+
let handle;
|
|
84319
|
+
try {
|
|
84320
|
+
handle = await (0, node_fs_promises.opendir)(dir);
|
|
84321
|
+
} catch (err) {
|
|
84322
|
+
if (err.code === "ENOENT") return false;
|
|
84323
|
+
throw err;
|
|
84324
|
+
}
|
|
84325
|
+
try {
|
|
84326
|
+
return await handle.read() !== null;
|
|
84327
|
+
} finally {
|
|
84328
|
+
await handle.close();
|
|
84329
|
+
}
|
|
84330
|
+
}
|
|
84331
|
+
async function probeLocalDirectoryOccupancy(input) {
|
|
84332
|
+
let names;
|
|
84333
|
+
try {
|
|
84334
|
+
names = await (0, node_fs_promises.readdir)(input.basePath);
|
|
84335
|
+
} catch (err) {
|
|
84336
|
+
if (err.code === "ENOENT") return "empty";
|
|
84337
|
+
return "unknown";
|
|
84338
|
+
}
|
|
84339
|
+
const visible = names.filter((name) => !isDotEntry(name));
|
|
84340
|
+
const subtrees = STORAGE_CLASS_SUBTREES[input.type];
|
|
84341
|
+
if (subtrees === void 0) return visible.length > 0 ? "occupied" : "empty";
|
|
84342
|
+
try {
|
|
84343
|
+
for (const camera of visible) for (const subtree of subtrees) if (await dirHasAnyEntry(node_path.default.join(input.basePath, camera, subtree))) return "occupied";
|
|
84344
|
+
} catch {
|
|
84345
|
+
return "unknown";
|
|
84346
|
+
}
|
|
84347
|
+
return "empty";
|
|
84348
|
+
}
|
|
84108
84349
|
function resolveEngine(getEngines) {
|
|
84109
84350
|
const engines = getEngines();
|
|
84110
84351
|
if (engines.length === 0) throw new Error("settings-store: no data-store-provider engine is registered \u2014 the data door has nothing behind it");
|
|
@@ -84194,6 +84435,164 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84194
84435
|
}
|
|
84195
84436
|
return out;
|
|
84196
84437
|
}
|
|
84438
|
+
var FOOTAGE_TYPES = /* @__PURE__ */ new Set(["recordings", "recordingsLow"]);
|
|
84439
|
+
function isTerminal(job) {
|
|
84440
|
+
return job.phase === "done" || job.phase === "failed" || job.phase === "cancelled";
|
|
84441
|
+
}
|
|
84442
|
+
function footageFrozen(location) {
|
|
84443
|
+
return location.enabled === false || location.config["readOnly"] === true;
|
|
84444
|
+
}
|
|
84445
|
+
var StorageCleanupCoordinator = class {
|
|
84446
|
+
deps;
|
|
84447
|
+
active = null;
|
|
84448
|
+
startReserved = false;
|
|
84449
|
+
constructor(deps) {
|
|
84450
|
+
this.deps = deps;
|
|
84451
|
+
}
|
|
84452
|
+
async start(input) {
|
|
84453
|
+
if (this.startReserved) throw new Error("storage cleanup is already active");
|
|
84454
|
+
this.startReserved = true;
|
|
84455
|
+
try {
|
|
84456
|
+
const existing = await this.status();
|
|
84457
|
+
if (existing && !isTerminal(existing)) throw new Error(`storage cleanup is already active (${existing.jobId})`);
|
|
84458
|
+
const now = this.deps.now();
|
|
84459
|
+
const job = {
|
|
84460
|
+
jobId: this.deps.newId(),
|
|
84461
|
+
phase: "orphans",
|
|
84462
|
+
includeDebugMedia: input.includeDebugMedia === true,
|
|
84463
|
+
orphansReclaimed: 0,
|
|
84464
|
+
orphanBytesReclaimed: 0,
|
|
84465
|
+
debugMediaReclaimed: 0,
|
|
84466
|
+
debugMediaBytesReclaimed: 0,
|
|
84467
|
+
ghostsForgotten: 0,
|
|
84468
|
+
ghostBytesForgotten: 0,
|
|
84469
|
+
detail: "Starting orphan reclaim",
|
|
84470
|
+
cancelRequested: false,
|
|
84471
|
+
startedAt: now,
|
|
84472
|
+
updatedAt: now,
|
|
84473
|
+
finishedAt: null,
|
|
84474
|
+
error: null
|
|
84475
|
+
};
|
|
84476
|
+
await this.persist(job);
|
|
84477
|
+
this.active = job;
|
|
84478
|
+
this.run(job);
|
|
84479
|
+
return job.jobId;
|
|
84480
|
+
} finally {
|
|
84481
|
+
this.startReserved = false;
|
|
84482
|
+
}
|
|
84483
|
+
}
|
|
84484
|
+
async status(jobId) {
|
|
84485
|
+
const job = this.active ?? await this.deps.state.get();
|
|
84486
|
+
if (jobId !== void 0 && job?.jobId !== jobId) return null;
|
|
84487
|
+
return job;
|
|
84488
|
+
}
|
|
84489
|
+
async cancel(jobId) {
|
|
84490
|
+
const job = await this.status(jobId);
|
|
84491
|
+
if (!job || isTerminal(job)) return false;
|
|
84492
|
+
job.cancelRequested = true;
|
|
84493
|
+
job.detail = "Cancel requested \u2014 finishing the current step";
|
|
84494
|
+
await this.persist(job);
|
|
84495
|
+
return true;
|
|
84496
|
+
}
|
|
84497
|
+
async run(job) {
|
|
84498
|
+
try {
|
|
84499
|
+
await this.reclaimOrphans(job);
|
|
84500
|
+
if (await this.stopped(job)) return;
|
|
84501
|
+
if (job.includeDebugMedia) {
|
|
84502
|
+
await this.setPhase(job, "debug-media", "Reclaiming debug media");
|
|
84503
|
+
await this.reclaimDebugMedia(job);
|
|
84504
|
+
if (await this.stopped(job)) return;
|
|
84505
|
+
}
|
|
84506
|
+
await this.setPhase(job, "ghost-ledger", "Forgetting ghost footage rows");
|
|
84507
|
+
await this.forgetGhosts(job);
|
|
84508
|
+
if (await this.stopped(job)) return;
|
|
84509
|
+
await this.finish(job, "done", null);
|
|
84510
|
+
} catch (err) {
|
|
84511
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
84512
|
+
await this.finish(job, "failed", message);
|
|
84513
|
+
}
|
|
84514
|
+
}
|
|
84515
|
+
async reclaimOrphans(job) {
|
|
84516
|
+
let restart = true;
|
|
84517
|
+
for (; ; ) {
|
|
84518
|
+
if (await this.stopped(job)) return;
|
|
84519
|
+
const start = await this.deps.participants.startOrphan(restart);
|
|
84520
|
+
restart = false;
|
|
84521
|
+
if (!start.started && !start.alreadyRunning) throw new Error("orphan reclaim did not start");
|
|
84522
|
+
const status = await this.waitUntilIdle(() => this.deps.participants.orphanStatus(), job, (s) => `Orphan reclaim: ${s.totalReclaimed} rows / ${String(s.totalBytesReclaimed)} bytes`);
|
|
84523
|
+
job.orphansReclaimed += status.totalReclaimed;
|
|
84524
|
+
job.orphanBytesReclaimed += status.totalBytesReclaimed;
|
|
84525
|
+
job.detail = `Orphans: ${job.orphansReclaimed} rows, ${String(job.orphanBytesReclaimed)} bytes`;
|
|
84526
|
+
await this.persist(job);
|
|
84527
|
+
if (status.error) throw new Error(status.error);
|
|
84528
|
+
if (status.complete === true) return;
|
|
84529
|
+
}
|
|
84530
|
+
}
|
|
84531
|
+
async reclaimDebugMedia(job) {
|
|
84532
|
+
const start = await this.deps.participants.startDebugMedia();
|
|
84533
|
+
if (!start.started && !start.alreadyRunning) throw new Error("debug-media reclaim did not start");
|
|
84534
|
+
const status = await this.waitUntilIdle(() => this.deps.participants.debugMediaStatus(), job, (s) => `Debug media: ${s.totalReclaimed} files`);
|
|
84535
|
+
job.debugMediaReclaimed = status.totalReclaimed;
|
|
84536
|
+
job.debugMediaBytesReclaimed = status.totalBytesReclaimed;
|
|
84537
|
+
await this.persist(job);
|
|
84538
|
+
if (status.error) throw new Error(status.error);
|
|
84539
|
+
}
|
|
84540
|
+
async forgetGhosts(job) {
|
|
84541
|
+
const frozen = this.deps.locations.listLocations().filter((l) => FOOTAGE_TYPES.has(l.type) && footageFrozen(l));
|
|
84542
|
+
if (frozen.length === 0) {
|
|
84543
|
+
job.detail = "No frozen footage locations";
|
|
84544
|
+
await this.persist(job);
|
|
84545
|
+
return;
|
|
84546
|
+
}
|
|
84547
|
+
for (const loc of frozen) {
|
|
84548
|
+
if (await this.stopped(job)) return;
|
|
84549
|
+
job.detail = `Ghost ledger: ${loc.id}`;
|
|
84550
|
+
await this.persist(job);
|
|
84551
|
+
const report = await this.deps.participants.walkLedger({
|
|
84552
|
+
locationId: loc.id,
|
|
84553
|
+
apply: true
|
|
84554
|
+
});
|
|
84555
|
+
job.ghostsForgotten += report.forgottenSegments;
|
|
84556
|
+
job.ghostBytesForgotten += report.forgottenBytes;
|
|
84557
|
+
await this.persist(job);
|
|
84558
|
+
}
|
|
84559
|
+
}
|
|
84560
|
+
async waitUntilIdle(read, job, detail) {
|
|
84561
|
+
const pollMs = this.deps.pollMs ?? 2e3;
|
|
84562
|
+
const sleep = this.deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
84563
|
+
for (; ; ) {
|
|
84564
|
+
const status = await read();
|
|
84565
|
+
job.detail = detail(status);
|
|
84566
|
+
await this.persist(job);
|
|
84567
|
+
if (!status.running) return status;
|
|
84568
|
+
await sleep(pollMs);
|
|
84569
|
+
}
|
|
84570
|
+
}
|
|
84571
|
+
async stopped(job) {
|
|
84572
|
+
if ((await this.status(job.jobId))?.cancelRequested === true) {
|
|
84573
|
+
await this.finish(job, "cancelled", null);
|
|
84574
|
+
return true;
|
|
84575
|
+
}
|
|
84576
|
+
return false;
|
|
84577
|
+
}
|
|
84578
|
+
async setPhase(job, phase, detail) {
|
|
84579
|
+
job.phase = phase;
|
|
84580
|
+
job.detail = detail;
|
|
84581
|
+
await this.persist(job);
|
|
84582
|
+
}
|
|
84583
|
+
async finish(job, phase, error) {
|
|
84584
|
+
job.phase = phase;
|
|
84585
|
+
job.error = error;
|
|
84586
|
+
job.finishedAt = this.deps.now();
|
|
84587
|
+
job.detail = phase === "done" ? "Cleanup finished" : job.detail;
|
|
84588
|
+
await this.persist(job);
|
|
84589
|
+
}
|
|
84590
|
+
async persist(job) {
|
|
84591
|
+
job.updatedAt = this.deps.now();
|
|
84592
|
+
this.active = job;
|
|
84593
|
+
await this.deps.state.set(job);
|
|
84594
|
+
}
|
|
84595
|
+
};
|
|
84197
84596
|
var SESSION_VOCABULARY = {
|
|
84198
84597
|
upload: {
|
|
84199
84598
|
idLabel: "uploadId",
|
|
@@ -84281,7 +84680,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84281
84680
|
* Reconciles both directions so operator edits survive a reboot:
|
|
84282
84681
|
* 1. hydrate — DB rows win over any early in-memory seed (restores
|
|
84283
84682
|
* operator config like `minFreePercent` that the pre-store boot
|
|
84284
|
-
* can't see)
|
|
84683
|
+
* can't see);
|
|
84285
84684
|
* 2. backfill — in-memory locations the DB doesn't have yet (the
|
|
84286
84685
|
* pre-store seed defaults on a fresh install) are persisted, so the
|
|
84287
84686
|
* store becomes the durable source of truth from here on.
|
|
@@ -84303,15 +84702,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84303
84702
|
const rows = await store.loadAll();
|
|
84304
84703
|
this.locationStore = store;
|
|
84305
84704
|
const dbIds = new Set(rows.map((r) => r.id));
|
|
84306
|
-
for (const loc of rows)
|
|
84307
|
-
const upgraded = !loc.isSystem && loc.id === `${loc.type}:default` ? {
|
|
84308
|
-
...loc,
|
|
84309
|
-
isSystem: true
|
|
84310
|
-
} : loc;
|
|
84311
|
-
this.locations.set(upgraded.id, upgraded);
|
|
84312
|
-
if (upgraded !== loc) store.upsert(upgraded).catch(() => {
|
|
84313
|
-
});
|
|
84314
|
-
}
|
|
84705
|
+
for (const loc of rows) this.locations.set(loc.id, loc);
|
|
84315
84706
|
const backfill = [...this.locations.values()].filter((l) => !dbIds.has(l.id));
|
|
84316
84707
|
for (const loc of backfill) store.upsert(loc).catch((err) => {
|
|
84317
84708
|
this.logger.warn("storage-orchestrator: attachStore backfill persist failed", { meta: {
|
|
@@ -84403,25 +84794,8 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84403
84794
|
async initialize() {
|
|
84404
84795
|
if (!this.locationStore) return;
|
|
84405
84796
|
const rows = await this.locationStore.loadAll();
|
|
84406
|
-
|
|
84407
|
-
|
|
84408
|
-
const upgradedLoc = {
|
|
84409
|
-
...loc,
|
|
84410
|
-
isSystem: true
|
|
84411
|
-
};
|
|
84412
|
-
this.locations.set(upgradedLoc.id, upgradedLoc);
|
|
84413
|
-
this.locationStore.upsert(upgradedLoc).catch((err) => {
|
|
84414
|
-
this.logger.warn("storage-orchestrator: isSystem upgrade persist failed", { meta: {
|
|
84415
|
-
id: upgradedLoc.id,
|
|
84416
|
-
error: err instanceof Error ? err.message : String(err)
|
|
84417
|
-
} });
|
|
84418
|
-
});
|
|
84419
|
-
upgraded++;
|
|
84420
|
-
} else this.locations.set(loc.id, loc);
|
|
84421
|
-
this.logger.info("storage-orchestrator: hydrated locations from store", { meta: {
|
|
84422
|
-
loaded: this.locations.size,
|
|
84423
|
-
isSystemUpgraded: upgraded
|
|
84424
|
-
} });
|
|
84797
|
+
for (const loc of rows) this.locations.set(loc.id, loc);
|
|
84798
|
+
this.logger.info("storage-orchestrator: hydrated locations from store", { meta: { loaded: this.locations.size } });
|
|
84425
84799
|
this.reportDisabledDefaults();
|
|
84426
84800
|
}
|
|
84427
84801
|
/**
|
|
@@ -84607,10 +84981,6 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84607
84981
|
...input,
|
|
84608
84982
|
nodeId: "hub"
|
|
84609
84983
|
};
|
|
84610
|
-
if (existing?.isSystem === true) input = {
|
|
84611
|
-
...input,
|
|
84612
|
-
isSystem: true
|
|
84613
|
-
};
|
|
84614
84984
|
input = {
|
|
84615
84985
|
...input,
|
|
84616
84986
|
...resolveEnabled(input, existing, this.hasAnyLocationOfType(input.type))
|
|
@@ -84657,21 +85027,22 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84657
85027
|
return next;
|
|
84658
85028
|
}
|
|
84659
85029
|
/**
|
|
84660
|
-
* Remove a location. Refuses
|
|
84661
|
-
*
|
|
84662
|
-
*
|
|
84663
|
-
*
|
|
84664
|
-
*
|
|
84665
|
-
*
|
|
84666
|
-
* routed to the logger — see `upsertLocation` for the rationale.
|
|
85030
|
+
* Remove a location. Refuses the last location of a type and the last
|
|
85031
|
+
* enabled location of a type. `isSystem` is informational — a frozen
|
|
85032
|
+
* recordings `:default` is deletable once a sibling is live. Deleting
|
|
85033
|
+
* the flagged default promotes an enabled sibling. Occupancy still
|
|
85034
|
+
* refuses unless `force` is set; force never overrides uniqueness /
|
|
85035
|
+
* last-enabled.
|
|
84667
85036
|
*/
|
|
84668
85037
|
async deleteLocation(id, options) {
|
|
84669
85038
|
const loc = this.locations.get(id);
|
|
84670
85039
|
if (!loc) throw new Error(`Storage location "${id}" not found`);
|
|
84671
|
-
|
|
84672
|
-
if (
|
|
84673
|
-
|
|
84674
|
-
}
|
|
85040
|
+
const ofType = [...this.locations.values()].filter((l) => l.type === loc.type);
|
|
85041
|
+
if (ofType.length <= 1) throw new Error(`Cannot delete "${id}" \u2014 it is the only location for type "${loc.type}"`);
|
|
85042
|
+
const enabledOfType = ofType.filter((l) => l.enabled !== false);
|
|
85043
|
+
if (loc.enabled !== false && enabledOfType.length <= 1) throw new Error(`Cannot delete "${id}" \u2014 it is the only enabled location for type "${loc.type}"`);
|
|
85044
|
+
const successor = loc.isDefault === true ? ofType.find((l) => l.id !== id && l.enabled !== false) : void 0;
|
|
85045
|
+
if (loc.isDefault === true && successor === void 0) throw new Error(`Cannot delete "${id}" \u2014 it is the only enabled location for type "${loc.type}"`);
|
|
84675
85046
|
const occupancy = await this.probeOccupancy(loc);
|
|
84676
85047
|
if (occupancy !== "empty") {
|
|
84677
85048
|
if (options?.force !== true) throw new Error(occupancy === "occupied" ? `Storage location "${id}" still holds data \u2014 drain it first (storage migration / relocate), or pass force to delete the record anyway and strand what is on it` : `Storage location "${id}" could not be checked for remaining data (unreachable provider, another node, or an unmounted root) \u2014 pass force to delete the record anyway`);
|
|
@@ -84681,6 +85052,21 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84681
85052
|
occupancy
|
|
84682
85053
|
} });
|
|
84683
85054
|
}
|
|
85055
|
+
if (successor !== void 0 && successor.isDefault !== true) {
|
|
85056
|
+
const now = Date.now();
|
|
85057
|
+
const promoted = {
|
|
85058
|
+
...successor,
|
|
85059
|
+
isDefault: true,
|
|
85060
|
+
updatedAt: now
|
|
85061
|
+
};
|
|
85062
|
+
this.locations.set(successor.id, promoted);
|
|
85063
|
+
if (this.locationStore) this.locationStore.upsert(promoted).catch((err) => {
|
|
85064
|
+
this.logger.error("storage-orchestrator: default promotion persist failed", { meta: {
|
|
85065
|
+
id: successor.id,
|
|
85066
|
+
error: err instanceof Error ? err.message : String(err)
|
|
85067
|
+
} });
|
|
85068
|
+
});
|
|
85069
|
+
}
|
|
84684
85070
|
this.locations.delete(id);
|
|
84685
85071
|
if (this.locationStore) this.locationStore.delete(id).catch((err) => {
|
|
84686
85072
|
this.logger.error("storage-orchestrator: delete persistence failed", { meta: {
|
|
@@ -84707,15 +85093,14 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84707
85093
|
}
|
|
84708
85094
|
}
|
|
84709
85095
|
/**
|
|
84710
|
-
* Remove
|
|
84711
|
-
* addon (stale defaults from a removed location type).
|
|
84712
|
-
*
|
|
84713
|
-
* operator owns them. Requires the registry to be set first.
|
|
85096
|
+
* Remove seed-shaped locations (`<type>:default`) whose type is no longer
|
|
85097
|
+
* declared by any addon (stale defaults from a removed location type).
|
|
85098
|
+
* Operator-added locations of an undeclared type are KEPT but warned.
|
|
84714
85099
|
*
|
|
84715
85100
|
* FAIL-SAFE: if the registry is EMPTY (no addon declared any location), we
|
|
84716
85101
|
* refuse to prune anything. An empty registry almost always means
|
|
84717
85102
|
* declarations failed to load (boot ordering, a stale install) — pruning
|
|
84718
|
-
* "everything undeclared" in that state would wipe every
|
|
85103
|
+
* "everything undeclared" in that state would wipe every seeded location
|
|
84719
85104
|
* (data/logs/recordings/…). Better to keep stale rows than destroy live ones.
|
|
84720
85105
|
*/
|
|
84721
85106
|
pruneUndeclaredSystemLocations() {
|
|
@@ -84726,7 +85111,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84726
85111
|
}
|
|
84727
85112
|
for (const [id, loc] of Array.from(this.locations)) {
|
|
84728
85113
|
if (this.registry.cardinalityOf(loc.type) !== null) continue;
|
|
84729
|
-
if (loc.
|
|
85114
|
+
if (loc.id === `${loc.type}:default`) {
|
|
84730
85115
|
this.locations.delete(id);
|
|
84731
85116
|
if (this.locationStore) this.locationStore.delete(id).catch((err) => {
|
|
84732
85117
|
this.logger.error("storage-orchestrator: prune persistence failed", { meta: {
|
|
@@ -84734,7 +85119,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84734
85119
|
error: err instanceof Error ? err.message : String(err)
|
|
84735
85120
|
} });
|
|
84736
85121
|
});
|
|
84737
|
-
this.logger.info("storage-orchestrator: pruned stale
|
|
85122
|
+
this.logger.info("storage-orchestrator: pruned stale seeded location", { meta: {
|
|
84738
85123
|
id,
|
|
84739
85124
|
type: loc.type
|
|
84740
85125
|
} });
|
|
@@ -84894,7 +85279,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
84894
85279
|
providerId: input.providerId,
|
|
84895
85280
|
config: { basePath: base },
|
|
84896
85281
|
isDefault: true,
|
|
84897
|
-
isSystem:
|
|
85282
|
+
isSystem: false
|
|
84898
85283
|
});
|
|
84899
85284
|
added++;
|
|
84900
85285
|
}
|
|
@@ -85076,6 +85461,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85076
85461
|
pressureTimer = null;
|
|
85077
85462
|
pressureSweepInFlight = false;
|
|
85078
85463
|
migration = null;
|
|
85464
|
+
cleanup = null;
|
|
85079
85465
|
/**
|
|
85080
85466
|
* Cached `providerId → nodeLocal` snapshot (SP1). Backs the orchestrator's
|
|
85081
85467
|
* synchronous `NodeLocalResolver` — `getProviderInfo()` is async, so we
|
|
@@ -85133,7 +85519,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85133
85519
|
const rows = type !== void 0 ? service.listLocations({ type }) : service.listLocations();
|
|
85134
85520
|
return Promise.all(rows.map(async (loc) => ({
|
|
85135
85521
|
...this.redacted(loc),
|
|
85136
|
-
capacity: await this.localCapacityOf(loc)
|
|
85522
|
+
capacity: loc.enabled === false ? null : await this.localCapacityOf(loc)
|
|
85137
85523
|
})));
|
|
85138
85524
|
},
|
|
85139
85525
|
getDefaultLocation: async ({ type }) => {
|
|
@@ -85301,6 +85687,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85301
85687
|
const migration = new StorageMigrationCoordinator({
|
|
85302
85688
|
locations: service,
|
|
85303
85689
|
state: this.state("storage-migration", require_dist10.StorageMigrationJobSchema.nullable(), null),
|
|
85690
|
+
history: this.state("storage-migration-history", zod.z.array(require_dist10.StorageMigrationJobSchema), []),
|
|
85304
85691
|
participants: {
|
|
85305
85692
|
pipeline: {
|
|
85306
85693
|
pause: async (leaseId) => {
|
|
@@ -85351,6 +85738,36 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85351
85738
|
deviceKeyOf: (locationId) => this.locationDeviceKey(locationId)
|
|
85352
85739
|
});
|
|
85353
85740
|
this.migration = migration;
|
|
85741
|
+
const cleanup = new StorageCleanupCoordinator({
|
|
85742
|
+
locations: service,
|
|
85743
|
+
state: this.state("storage-cleanup", require_dist10.StorageCleanupJobSchema.nullable(), null),
|
|
85744
|
+
participants: {
|
|
85745
|
+
startOrphan: async (restart) => {
|
|
85746
|
+
return parseStarted(await this.ctx.api.addons.custom.mutate({
|
|
85747
|
+
addonId: "pipeline-analytics",
|
|
85748
|
+
action: "retention.orphanAudit",
|
|
85749
|
+
input: {
|
|
85750
|
+
mode: "reclaim",
|
|
85751
|
+
restart,
|
|
85752
|
+
maxRowsPerScope: 2e4
|
|
85753
|
+
}
|
|
85754
|
+
}));
|
|
85755
|
+
},
|
|
85756
|
+
orphanStatus: async () => {
|
|
85757
|
+
return parseOrphanStatus(await this.ctx.api.addons.custom.mutate({
|
|
85758
|
+
addonId: "pipeline-analytics",
|
|
85759
|
+
action: "retention.orphanAuditStatus",
|
|
85760
|
+
input: {}
|
|
85761
|
+
}));
|
|
85762
|
+
},
|
|
85763
|
+
startDebugMedia: () => this.ctx.api.pipelineAnalytics.reclaimDebugMedia.mutate({ mode: "reclaim" }),
|
|
85764
|
+
debugMediaStatus: () => this.ctx.api.pipelineAnalytics.getMediaReclaimStatus.query({}),
|
|
85765
|
+
walkLedger: (input) => this.ctx.api.recording.reconcileLedgerAgainstDisk.mutate(input)
|
|
85766
|
+
},
|
|
85767
|
+
now: () => Date.now(),
|
|
85768
|
+
newId: () => (0, node_crypto.randomUUID)()
|
|
85769
|
+
});
|
|
85770
|
+
this.cleanup = cleanup;
|
|
85354
85771
|
const migrationProvider = {
|
|
85355
85772
|
plan: (input) => migration.plan(input),
|
|
85356
85773
|
start: async (input) => ({ jobId: await migration.start(input) }),
|
|
@@ -85358,7 +85775,11 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85358
85775
|
cancel: async ({ jobId }) => ({ cancelled: await migration.cancel(jobId) }),
|
|
85359
85776
|
movers: () => migration.movers(),
|
|
85360
85777
|
residue: () => migration.residue(),
|
|
85361
|
-
drain: async (input) => ({ jobId: await migration.drain(input) })
|
|
85778
|
+
drain: async (input) => ({ jobId: await migration.drain(input) }),
|
|
85779
|
+
cleanupStart: async (input) => ({ jobId: await cleanup.start(input) }),
|
|
85780
|
+
cleanupStatus: ({ jobId }) => cleanup.status(jobId),
|
|
85781
|
+
cleanupCancel: async ({ jobId }) => ({ cancelled: await cleanup.cancel(jobId) }),
|
|
85782
|
+
history: () => migration.history()
|
|
85362
85783
|
};
|
|
85363
85784
|
await this.seedFromDeclarations();
|
|
85364
85785
|
const eventBus = this.ctx.eventBus;
|
|
@@ -85603,11 +86024,14 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85603
86024
|
}
|
|
85604
86025
|
}
|
|
85605
86026
|
/**
|
|
85606
|
-
* Does this location still hold anything
|
|
85607
|
-
*
|
|
85608
|
-
*
|
|
85609
|
-
*
|
|
85610
|
-
*
|
|
86027
|
+
* Does this location still hold anything of ITS class?
|
|
86028
|
+
*
|
|
86029
|
+
* Shared roots (`/recordings` hosting high + low + events) are scored by
|
|
86030
|
+
* class subtree (`<camera>/high|mid`, `/low`, `/events`), not by a raw
|
|
86031
|
+
* `readdir` of the root — camera dirs and `.camstack-location` would
|
|
86032
|
+
* otherwise make every class look occupied. The walk stays shallow: one
|
|
86033
|
+
* dirent per camera, then first-entry of the named subtree. A `find` of
|
|
86034
|
+
* segments is precisely what must not happen here.
|
|
85611
86035
|
*
|
|
85612
86036
|
* **What it cannot see, stated rather than papered over:**
|
|
85613
86037
|
*
|
|
@@ -85616,9 +86040,10 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85616
86040
|
* `unknown`, never `empty`.
|
|
85617
86041
|
* - A location with no `basePath` — same answer.
|
|
85618
86042
|
* - The difference between "holds live footage" and "holds one stray
|
|
85619
|
-
* lock-file". It measures
|
|
85620
|
-
* a location holding orphan files that no index
|
|
85621
|
-
* the safe one, and `force` is the escape
|
|
86043
|
+
* lock-file". It measures ON-DISK entries of this class, not durable
|
|
86044
|
+
* rows, so it refuses a location holding orphan files that no index
|
|
86045
|
+
* names. That direction is the safe one, and `force` is the escape
|
|
86046
|
+
* hatch for it.
|
|
85622
86047
|
*
|
|
85623
86048
|
* A missing root (`ENOENT`) is `empty`, not `unknown`: an unmounted disk and
|
|
85624
86049
|
* a deleted directory are indistinguishable here, and if the record's own
|
|
@@ -85636,16 +86061,16 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85636
86061
|
if ((location.nodeId === void 0 || location.nodeId === "" ? HUB_NODE_ID : location.nodeId) !== (this.service?.getLocalNodeId() ?? HUB_NODE_ID)) return "unknown";
|
|
85637
86062
|
const basePath = this.locationBasePath(location.id);
|
|
85638
86063
|
if (basePath === null) return "unknown";
|
|
85639
|
-
|
|
85640
|
-
|
|
85641
|
-
|
|
85642
|
-
|
|
85643
|
-
|
|
85644
|
-
|
|
85645
|
-
|
|
85646
|
-
|
|
85647
|
-
|
|
85648
|
-
|
|
86064
|
+
const occupancy = await probeLocalDirectoryOccupancy({
|
|
86065
|
+
type: location.type,
|
|
86066
|
+
basePath
|
|
86067
|
+
});
|
|
86068
|
+
if (occupancy === "unknown") this.ctx.logger.warn("storage-orchestrator: could not read a location root to check it", { meta: {
|
|
86069
|
+
id: location.id,
|
|
86070
|
+
basePath,
|
|
86071
|
+
type: location.type
|
|
86072
|
+
} });
|
|
86073
|
+
return occupancy;
|
|
85649
86074
|
}
|
|
85650
86075
|
/** Free capacity (%) on a location's volume via `statfs`; 100 (guard inert) when unstattable. */
|
|
85651
86076
|
async locationFreePercent(locationId) {
|
|
@@ -85721,6 +86146,38 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
85721
86146
|
}
|
|
85722
86147
|
}
|
|
85723
86148
|
};
|
|
86149
|
+
function parseStarted(raw) {
|
|
86150
|
+
if (raw !== null && typeof raw === "object") {
|
|
86151
|
+
const o = raw;
|
|
86152
|
+
if (typeof o["started"] === "boolean" && typeof o["alreadyRunning"] === "boolean") return {
|
|
86153
|
+
started: o["started"],
|
|
86154
|
+
alreadyRunning: o["alreadyRunning"]
|
|
86155
|
+
};
|
|
86156
|
+
}
|
|
86157
|
+
return {
|
|
86158
|
+
started: false,
|
|
86159
|
+
alreadyRunning: false
|
|
86160
|
+
};
|
|
86161
|
+
}
|
|
86162
|
+
function parseOrphanStatus(raw) {
|
|
86163
|
+
if (raw !== null && typeof raw === "object") {
|
|
86164
|
+
const o = raw;
|
|
86165
|
+
return {
|
|
86166
|
+
running: o["running"] === true,
|
|
86167
|
+
complete: typeof o["complete"] === "boolean" ? o["complete"] : null,
|
|
86168
|
+
totalReclaimed: typeof o["totalReclaimed"] === "number" ? o["totalReclaimed"] : 0,
|
|
86169
|
+
totalBytesReclaimed: typeof o["totalBytesReclaimed"] === "number" ? o["totalBytesReclaimed"] : 0,
|
|
86170
|
+
error: typeof o["error"] === "string" ? o["error"] : null
|
|
86171
|
+
};
|
|
86172
|
+
}
|
|
86173
|
+
return {
|
|
86174
|
+
running: false,
|
|
86175
|
+
complete: true,
|
|
86176
|
+
totalReclaimed: 0,
|
|
86177
|
+
totalBytesReclaimed: 0,
|
|
86178
|
+
error: "orphan audit status unreadable"
|
|
86179
|
+
};
|
|
86180
|
+
}
|
|
85724
86181
|
exports.SqliteLocationStore = SqliteLocationStore;
|
|
85725
86182
|
exports.StorageMigrationCoordinator = StorageMigrationCoordinator;
|
|
85726
86183
|
exports.StorageOrchestratorAddon = StorageOrchestratorAddon;
|
|
@@ -85757,7 +86214,7 @@ var require_system_config_addon = __commonJS({
|
|
|
85757
86214
|
[Symbol.toStringTag]: { value: "Module" }
|
|
85758
86215
|
});
|
|
85759
86216
|
require_chunk_Cek0wNdY();
|
|
85760
|
-
var require_dist10 =
|
|
86217
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
85761
86218
|
var SECTION_TITLES = {
|
|
85762
86219
|
server: "Server",
|
|
85763
86220
|
auth: "Authentication"
|
|
@@ -103818,7 +104275,7 @@ var require_winston_logging = __commonJS({
|
|
|
103818
104275
|
[Symbol.toStringTag]: { value: "Module" }
|
|
103819
104276
|
});
|
|
103820
104277
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
103821
|
-
var require_dist10 =
|
|
104278
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
103822
104279
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
103823
104280
|
var node_path = __require("path");
|
|
103824
104281
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -116320,12 +116777,12 @@ var require_dist2 = __commonJS({
|
|
|
116320
116777
|
}
|
|
116321
116778
|
});
|
|
116322
116779
|
|
|
116323
|
-
// ../system/dist/manifest-system-deps-
|
|
116324
|
-
var
|
|
116325
|
-
"../system/dist/manifest-system-deps-
|
|
116780
|
+
// ../system/dist/manifest-system-deps-BIxY1Y5e.js
|
|
116781
|
+
var require_manifest_system_deps_BIxY1Y5e = __commonJS({
|
|
116782
|
+
"../system/dist/manifest-system-deps-BIxY1Y5e.js"(exports) {
|
|
116326
116783
|
"use strict";
|
|
116327
116784
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
116328
|
-
|
|
116785
|
+
require_dist_CFTKQGym();
|
|
116329
116786
|
var node_crypto = __require("crypto");
|
|
116330
116787
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
116331
116788
|
var _camstack_types_node = require_node();
|
|
@@ -128473,7 +128930,7 @@ var require_dist3 = __commonJS({
|
|
|
128473
128930
|
"use strict";
|
|
128474
128931
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
128475
128932
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
128476
|
-
var require_dist10 =
|
|
128933
|
+
var require_dist10 = require_dist_CFTKQGym();
|
|
128477
128934
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
128478
128935
|
require_alerts();
|
|
128479
128936
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -128499,7 +128956,7 @@ var require_dist3 = __commonJS({
|
|
|
128499
128956
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
128500
128957
|
var require_file_data_plane = require_file_data_plane_DO8KbxCe();
|
|
128501
128958
|
var require_tls$1 = require_tls_BxQlomxd();
|
|
128502
|
-
var require_manifest_system_deps =
|
|
128959
|
+
var require_manifest_system_deps = require_manifest_system_deps_BIxY1Y5e();
|
|
128503
128960
|
var require_resource_monitor = require_resource_monitor_CdnzxBLP();
|
|
128504
128961
|
var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
|
|
128505
128962
|
var zod = require_zod();
|
|
@@ -210740,6 +211197,13 @@ var require_dist4 = __commonJS({
|
|
|
210740
211197
|
]);
|
|
210741
211198
|
var RelocateMediaInputSchema = zod.z.object({
|
|
210742
211199
|
toLocationId: zod.z.string(),
|
|
211200
|
+
/**
|
|
211201
|
+
* Restrict the pass to rows currently on this location. Omitted / `'*'` =
|
|
211202
|
+
* every row that is not already on `toLocationId` (the historical
|
|
211203
|
+
* behaviour). A named source is what a from→to migration needs: without it
|
|
211204
|
+
* "move events off disk 2" also emptied disk 1.
|
|
211205
|
+
*/
|
|
211206
|
+
fromLocationId: zod.z.string().optional(),
|
|
210743
211207
|
throttleMbps: zod.z.number().min(1).max(1e3).optional(),
|
|
210744
211208
|
/** Omitted = `move`, the pre-existing behaviour. */
|
|
210745
211209
|
mode: MediaRelocateModeSchema.optional()
|
|
@@ -210771,9 +211235,18 @@ var require_dist4 = __commonJS({
|
|
|
210771
211235
|
backups: zod.z.string().min(1).optional(),
|
|
210772
211236
|
galleryMedia: zod.z.string().min(1).optional()
|
|
210773
211237
|
}).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
|
|
211238
|
+
var StorageMigrationSourcesSchema = zod.z.object({
|
|
211239
|
+
recordings: zod.z.string().min(1).optional(),
|
|
211240
|
+
recordingsLow: zod.z.string().min(1).optional(),
|
|
211241
|
+
eventMedia: zod.z.string().min(1).optional(),
|
|
211242
|
+
backups: zod.z.string().min(1).optional(),
|
|
211243
|
+
galleryMedia: zod.z.string().min(1).optional()
|
|
211244
|
+
}).optional();
|
|
210774
211245
|
var StorageMigrationModeSchema = zod.z.enum(["blocking", "nonBlocking"]);
|
|
210775
211246
|
var StorageMigrationInputSchema = zod.z.object({
|
|
210776
211247
|
destinations: StorageMigrationDestinationsSchema,
|
|
211248
|
+
/** Omitted = each class's current default. */
|
|
211249
|
+
sources: StorageMigrationSourcesSchema,
|
|
210777
211250
|
throttleMbps: zod.z.number().min(1).max(1e3).optional(),
|
|
210778
211251
|
/** Omitted = `blocking`, which stays the default. */
|
|
210779
211252
|
mode: StorageMigrationModeSchema.optional()
|
|
@@ -210819,6 +211292,13 @@ var require_dist4 = __commonJS({
|
|
|
210819
211292
|
storageClass: StorageMigrationClassSchema,
|
|
210820
211293
|
fromLocationId: zod.z.string(),
|
|
210821
211294
|
toLocationId: zod.z.string(),
|
|
211295
|
+
/**
|
|
211296
|
+
* True when `from` was NOT the class default at plan time. The move still
|
|
211297
|
+
* copies bytes, but the default is left alone and the source is disabled
|
|
211298
|
+
* once the copy verifies. Absent on jobs planned before this field existed
|
|
211299
|
+
* — those jobs always repointed, which is `false`.
|
|
211300
|
+
*/
|
|
211301
|
+
freezeSource: zod.z.boolean().optional(),
|
|
210822
211302
|
moverJobId: zod.z.string().nullable(),
|
|
210823
211303
|
state: RelocateJobStateSchema.nullable(),
|
|
210824
211304
|
error: zod.z.string().nullable(),
|
|
@@ -210832,6 +211312,7 @@ var require_dist4 = __commonJS({
|
|
|
210832
211312
|
* can tell a seconds-long cutover from a thirty-hour one. */
|
|
210833
211313
|
mode: StorageMigrationModeSchema,
|
|
210834
211314
|
destinations: StorageMigrationDestinationsSchema,
|
|
211315
|
+
sources: StorageMigrationSourcesSchema,
|
|
210835
211316
|
throttleMbps: zod.z.number(),
|
|
210836
211317
|
moves: zod.z.array(StorageMigrationMoveSchema),
|
|
210837
211318
|
pauseLeaseId: zod.z.string().nullable(),
|
|
@@ -210858,6 +211339,7 @@ var require_dist4 = __commonJS({
|
|
|
210858
211339
|
});
|
|
210859
211340
|
var StorageMigrationPlanSchema = zod.z.object({
|
|
210860
211341
|
destinations: StorageMigrationDestinationsSchema,
|
|
211342
|
+
sources: StorageMigrationSourcesSchema,
|
|
210861
211343
|
/** The mode this plan was built for. A plan is only valid for its mode: the
|
|
210862
211344
|
* `eventMedia` seal gate and the single-cardinality refusal both depend on
|
|
210863
211345
|
* it. */
|
|
@@ -210865,7 +211347,8 @@ var require_dist4 = __commonJS({
|
|
|
210865
211347
|
moves: zod.z.array(zod.z.object({
|
|
210866
211348
|
storageClass: StorageMigrationClassSchema,
|
|
210867
211349
|
fromLocationId: zod.z.string(),
|
|
210868
|
-
toLocationId: zod.z.string()
|
|
211350
|
+
toLocationId: zod.z.string(),
|
|
211351
|
+
freezeSource: zod.z.boolean().optional()
|
|
210869
211352
|
})),
|
|
210870
211353
|
findings: zod.z.array(StorageMigrationFindingSchema)
|
|
210871
211354
|
});
|
|
@@ -210977,9 +211460,42 @@ var require_dist4 = __commonJS({
|
|
|
210977
211460
|
var RelocatableMediaCountSchema = zod.z.object({ rows: zod.z.number().int().nonnegative() }).nullable();
|
|
210978
211461
|
var RelocatableMediaCountInputSchema = zod.z.object({
|
|
210979
211462
|
toLocationId: zod.z.string().min(1),
|
|
211463
|
+
/** Restrict the count to one source; omitted / `'*'` = every non-target row. */
|
|
211464
|
+
fromLocationId: zod.z.string().optional(),
|
|
210980
211465
|
/** Omitted = `move`. */
|
|
210981
211466
|
mode: MediaRelocateModeSchema.optional()
|
|
210982
211467
|
});
|
|
211468
|
+
var StorageCleanupPhaseSchema = zod.z.enum([
|
|
211469
|
+
"orphans",
|
|
211470
|
+
"debug-media",
|
|
211471
|
+
"ghost-ledger",
|
|
211472
|
+
"done",
|
|
211473
|
+
"failed",
|
|
211474
|
+
"cancelled"
|
|
211475
|
+
]);
|
|
211476
|
+
var StorageCleanupInputSchema = zod.z.object({
|
|
211477
|
+
/** Also walk motion stills / track filmstrips. Off by default. */
|
|
211478
|
+
includeDebugMedia: zod.z.boolean().optional()
|
|
211479
|
+
});
|
|
211480
|
+
var StorageCleanupJobSchema = zod.z.object({
|
|
211481
|
+
jobId: zod.z.string(),
|
|
211482
|
+
phase: StorageCleanupPhaseSchema,
|
|
211483
|
+
includeDebugMedia: zod.z.boolean(),
|
|
211484
|
+
orphansReclaimed: zod.z.number().int().nonnegative(),
|
|
211485
|
+
orphanBytesReclaimed: zod.z.number().int().nonnegative(),
|
|
211486
|
+
debugMediaReclaimed: zod.z.number().int().nonnegative(),
|
|
211487
|
+
debugMediaBytesReclaimed: zod.z.number().int().nonnegative(),
|
|
211488
|
+
ghostsForgotten: zod.z.number().int().nonnegative(),
|
|
211489
|
+
ghostBytesForgotten: zod.z.number().int().nonnegative(),
|
|
211490
|
+
/** Short operator-facing line: current collection, pass, or location. */
|
|
211491
|
+
detail: zod.z.string().nullable(),
|
|
211492
|
+
cancelRequested: zod.z.boolean(),
|
|
211493
|
+
startedAt: zod.z.number(),
|
|
211494
|
+
updatedAt: zod.z.number(),
|
|
211495
|
+
finishedAt: zod.z.number().nullable(),
|
|
211496
|
+
error: zod.z.string().nullable()
|
|
211497
|
+
});
|
|
211498
|
+
var StorageCleanupStatusInputSchema = zod.z.object({ jobId: zod.z.string().optional() });
|
|
210983
211499
|
var SUB_DETECTION_TYPES = ["face", "plate"];
|
|
210984
211500
|
var RECOGNITION_TYPES = [
|
|
210985
211501
|
"face",
|
|
@@ -226903,7 +227419,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
226903
227419
|
drain: require_sleep.method(StorageMigrationDrainInputSchema, zod.z.object({ jobId: zod.z.string() }), {
|
|
226904
227420
|
kind: "mutation",
|
|
226905
227421
|
auth: "admin"
|
|
226906
|
-
})
|
|
227422
|
+
}),
|
|
227423
|
+
/**
|
|
227424
|
+
* One operator cleanup of leftover analytics (DB + blobs) and ghost
|
|
227425
|
+
* ledger rows on frozen footage locations. Optional debug-media sweep.
|
|
227426
|
+
* Returns immediately; poll {@link cleanupStatus}.
|
|
227427
|
+
*/
|
|
227428
|
+
cleanupStart: require_sleep.method(StorageCleanupInputSchema, zod.z.object({ jobId: zod.z.string() }), {
|
|
227429
|
+
kind: "mutation",
|
|
227430
|
+
auth: "admin"
|
|
227431
|
+
}),
|
|
227432
|
+
cleanupStatus: require_sleep.method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }),
|
|
227433
|
+
cleanupCancel: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
|
|
227434
|
+
kind: "mutation",
|
|
227435
|
+
auth: "admin"
|
|
227436
|
+
}),
|
|
227437
|
+
/** Recent finished migration jobs, newest first. The live job is `status`. */
|
|
227438
|
+
history: require_sleep.method(zod.z.object({}), zod.z.array(StorageMigrationJobSchema).readonly(), { auth: "admin" })
|
|
226907
227439
|
}
|
|
226908
227440
|
};
|
|
226909
227441
|
var ProviderInfoSchema = zod.z.discriminatedUnion("shouldSaveDiskSpace", [zod.z.object({
|
|
@@ -233704,6 +234236,26 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
233704
234236
|
/** Ignore piles smaller than this (default 1 GB). */
|
|
233705
234237
|
minMoveGb: zod.z.number().min(0).optional()
|
|
233706
234238
|
});
|
|
234239
|
+
var RecordingDevicePlacementSchema = zod.z.object({
|
|
234240
|
+
deviceId: zod.z.number().int(),
|
|
234241
|
+
profile: zod.z.string(),
|
|
234242
|
+
locationId: zod.z.string()
|
|
234243
|
+
});
|
|
234244
|
+
var RecordingDevicePinSchema = zod.z.object({
|
|
234245
|
+
deviceId: zod.z.number().int(),
|
|
234246
|
+
/** Recordings-class location this camera is pinned to. */
|
|
234247
|
+
locationId: zod.z.string()
|
|
234248
|
+
});
|
|
234249
|
+
var RecordingPlacementViewSchema = zod.z.object({
|
|
234250
|
+
assignments: zod.z.array(RecordingDevicePlacementSchema),
|
|
234251
|
+
pins: zod.z.array(RecordingDevicePinSchema),
|
|
234252
|
+
defaultLocations: zod.z.record(zod.z.string(), zod.z.string())
|
|
234253
|
+
});
|
|
234254
|
+
var RecordingSetDevicePlacementInputSchema = zod.z.object({
|
|
234255
|
+
deviceId: zod.z.number().int(),
|
|
234256
|
+
/** `null` = Auto. Otherwise a `recordings:*` location id. */
|
|
234257
|
+
locationId: zod.z.string().nullable()
|
|
234258
|
+
});
|
|
233707
234259
|
var LocateSegmentResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
233708
234260
|
kind: zod.z.literal("segment"),
|
|
233709
234261
|
startMs: zod.z.number(),
|
|
@@ -234022,6 +234574,22 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
234022
234574
|
startStorageRebalance: require_sleep.method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
|
|
234023
234575
|
kind: "mutation",
|
|
234024
234576
|
auth: "admin"
|
|
234577
|
+
}),
|
|
234578
|
+
/**
|
|
234579
|
+
* The placement plan in force plus operator pins. Drives the Locations
|
|
234580
|
+
* admin page: Auto vs a named recordings location, per camera.
|
|
234581
|
+
*/
|
|
234582
|
+
getPlacement: require_sleep.method(zod.z.object({}), RecordingPlacementViewSchema, {
|
|
234583
|
+
kind: "query",
|
|
234584
|
+
auth: "admin"
|
|
234585
|
+
}),
|
|
234586
|
+
/**
|
|
234587
|
+
* Pin a camera to a recordings location, or clear the pin (Auto). High and
|
|
234588
|
+
* mid follow the pin; low stays with the recordingsLow planner.
|
|
234589
|
+
*/
|
|
234590
|
+
setDevicePlacement: require_sleep.method(RecordingSetDevicePlacementInputSchema, zod.z.object({ ok: zod.z.literal(true) }), {
|
|
234591
|
+
kind: "mutation",
|
|
234592
|
+
auth: "admin"
|
|
234025
234593
|
})
|
|
234026
234594
|
}
|
|
234027
234595
|
};
|
|
@@ -244181,6 +244749,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
244181
244749
|
addonId: null,
|
|
244182
244750
|
access: "view"
|
|
244183
244751
|
},
|
|
244752
|
+
"recording.getPlacement": {
|
|
244753
|
+
capName: "recording",
|
|
244754
|
+
capScope: "system",
|
|
244755
|
+
addonId: null,
|
|
244756
|
+
access: "view"
|
|
244757
|
+
},
|
|
244184
244758
|
"recording.getPlaybackManifest": {
|
|
244185
244759
|
capName: "recording",
|
|
244186
244760
|
capScope: "system",
|
|
@@ -244307,6 +244881,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
244307
244881
|
addonId: null,
|
|
244308
244882
|
access: "create"
|
|
244309
244883
|
},
|
|
244884
|
+
"recording.setDevicePlacement": {
|
|
244885
|
+
capName: "recording",
|
|
244886
|
+
capScope: "system",
|
|
244887
|
+
addonId: null,
|
|
244888
|
+
access: "create"
|
|
244889
|
+
},
|
|
244310
244890
|
"recording.startStorageMigrationMove": {
|
|
244311
244891
|
capName: "recording",
|
|
244312
244892
|
capScope: "system",
|
|
@@ -244751,12 +245331,36 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
244751
245331
|
addonId: null,
|
|
244752
245332
|
access: "create"
|
|
244753
245333
|
},
|
|
245334
|
+
"storageMigration.cleanupCancel": {
|
|
245335
|
+
capName: "storage-migration",
|
|
245336
|
+
capScope: "system",
|
|
245337
|
+
addonId: null,
|
|
245338
|
+
access: "create"
|
|
245339
|
+
},
|
|
245340
|
+
"storageMigration.cleanupStart": {
|
|
245341
|
+
capName: "storage-migration",
|
|
245342
|
+
capScope: "system",
|
|
245343
|
+
addonId: null,
|
|
245344
|
+
access: "create"
|
|
245345
|
+
},
|
|
245346
|
+
"storageMigration.cleanupStatus": {
|
|
245347
|
+
capName: "storage-migration",
|
|
245348
|
+
capScope: "system",
|
|
245349
|
+
addonId: null,
|
|
245350
|
+
access: "view"
|
|
245351
|
+
},
|
|
244754
245352
|
"storageMigration.drain": {
|
|
244755
245353
|
capName: "storage-migration",
|
|
244756
245354
|
capScope: "system",
|
|
244757
245355
|
addonId: null,
|
|
244758
245356
|
access: "create"
|
|
244759
245357
|
},
|
|
245358
|
+
"storageMigration.history": {
|
|
245359
|
+
capName: "storage-migration",
|
|
245360
|
+
capScope: "system",
|
|
245361
|
+
addonId: null,
|
|
245362
|
+
access: "view"
|
|
245363
|
+
},
|
|
244760
245364
|
"storageMigration.movers": {
|
|
244761
245365
|
capName: "storage-migration",
|
|
244762
245366
|
capScope: "system",
|
|
@@ -247501,6 +248105,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
247501
248105
|
form: "single",
|
|
247502
248106
|
optional: false
|
|
247503
248107
|
}],
|
|
248108
|
+
"recording.setDevicePlacement": [{
|
|
248109
|
+
name: "deviceId",
|
|
248110
|
+
form: "single",
|
|
248111
|
+
optional: false
|
|
248112
|
+
}],
|
|
247504
248113
|
"recording.startStorageMigrationMove": [{
|
|
247505
248114
|
name: "deviceId",
|
|
247506
248115
|
form: "single",
|
|
@@ -247970,6 +248579,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
247970
248579
|
"recording.renderGif",
|
|
247971
248580
|
"recording.rescanStorage",
|
|
247972
248581
|
"recording.setDeviceConfig",
|
|
248582
|
+
"recording.setDevicePlacement",
|
|
247973
248583
|
"recording.startStorageMigrationMove",
|
|
247974
248584
|
"recordingExport.createExport",
|
|
247975
248585
|
"recordingExport.listExports",
|
|
@@ -248853,7 +249463,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
248853
249463
|
reconcileLedgerAgainstDisk: (input) => dispatch("recording", "reconcileLedgerAgainstDisk", "mutation", input),
|
|
248854
249464
|
cancelRelocateJob: (input) => dispatch("recording", "cancelRelocateJob", "mutation", input),
|
|
248855
249465
|
planStorageRebalance: (input) => dispatch("recording", "planStorageRebalance", "query", input),
|
|
248856
|
-
startStorageRebalance: (input) => dispatch("recording", "startStorageRebalance", "mutation", input)
|
|
249466
|
+
startStorageRebalance: (input) => dispatch("recording", "startStorageRebalance", "mutation", input),
|
|
249467
|
+
getPlacement: (input) => dispatch("recording", "getPlacement", "query", input),
|
|
249468
|
+
setDevicePlacement: (input) => dispatch("recording", "setDevicePlacement", "mutation", input)
|
|
248857
249469
|
},
|
|
248858
249470
|
recordingExport: {
|
|
248859
249471
|
createExport: (input) => dispatch("recordingExport", "createExport", "mutation", input),
|
|
@@ -248917,7 +249529,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
248917
249529
|
cancel: (input) => dispatch("storageMigration", "cancel", "mutation", input),
|
|
248918
249530
|
movers: (input) => dispatch("storageMigration", "movers", "query", input),
|
|
248919
249531
|
residue: (input) => dispatch("storageMigration", "residue", "query", input),
|
|
248920
|
-
drain: (input) => dispatch("storageMigration", "drain", "mutation", input)
|
|
249532
|
+
drain: (input) => dispatch("storageMigration", "drain", "mutation", input),
|
|
249533
|
+
cleanupStart: (input) => dispatch("storageMigration", "cleanupStart", "mutation", input),
|
|
249534
|
+
cleanupStatus: (input) => dispatch("storageMigration", "cleanupStatus", "query", input),
|
|
249535
|
+
cleanupCancel: (input) => dispatch("storageMigration", "cleanupCancel", "mutation", input),
|
|
249536
|
+
history: (input) => dispatch("storageMigration", "history", "query", input)
|
|
248921
249537
|
},
|
|
248922
249538
|
streamBroker: {
|
|
248923
249539
|
fetchEventMedia: (input) => dispatch("streamBroker", "fetchEventMedia", "mutation", input),
|
|
@@ -252534,6 +253150,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252534
253150
|
exports.StorageBeginDownloadResultSchema = BeginDownloadResultSchema;
|
|
252535
253151
|
exports.StorageBeginUploadInputSchema = BeginUploadInputSchema;
|
|
252536
253152
|
exports.StorageBeginUploadResultSchema = BeginUploadResultSchema;
|
|
253153
|
+
exports.StorageCleanupInputSchema = StorageCleanupInputSchema;
|
|
253154
|
+
exports.StorageCleanupJobSchema = StorageCleanupJobSchema;
|
|
253155
|
+
exports.StorageCleanupPhaseSchema = StorageCleanupPhaseSchema;
|
|
253156
|
+
exports.StorageCleanupStatusInputSchema = StorageCleanupStatusInputSchema;
|
|
252537
253157
|
exports.StorageEndDownloadInputSchema = EndDownloadInputSchema;
|
|
252538
253158
|
exports.StorageFinalizeUploadInputSchema = FinalizeUploadInputSchema;
|
|
252539
253159
|
exports.StorageLocationDeclarationSchema = StorageLocationDeclarationSchema;
|
|
@@ -252559,6 +253179,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
252559
253179
|
exports.StorageMigrationPhaseSchema = StorageMigrationPhaseSchema;
|
|
252560
253180
|
exports.StorageMigrationPlanSchema = StorageMigrationPlanSchema;
|
|
252561
253181
|
exports.StorageMigrationResidueSchema = StorageMigrationResidueSchema;
|
|
253182
|
+
exports.StorageMigrationSourcesSchema = StorageMigrationSourcesSchema;
|
|
252562
253183
|
exports.StorageProviderInfoSchema = ProviderInfoSchema;
|
|
252563
253184
|
exports.StorageReadChunkInputSchema = ReadChunkInputSchema;
|
|
252564
253185
|
exports.StorageTestLocationResultSchema = TestLocationResultSchema;
|