@camstack/addon-pipeline-orchestrator 1.2.325 → 1.2.327
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/_stub.js +2 -2
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-DUstnfGf.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-CxcjyRWF.mjs} +2 -2
- package/dist/{_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-6CTaeZSL.mjs → _virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D0nHvaSr.mjs} +1 -1
- package/dist/{_virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-s9I9eY7F.mjs → _virtual_mf___mfe_internal__addon_pipeline_orchestrator_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DkOTHkEX.mjs} +1 -1
- package/dist/{hostInit-DMNJfKN-.mjs → hostInit-B3TkIIX_.mjs} +2 -2
- package/dist/index.js +302 -93
- package/dist/index.mjs +302 -93
- package/dist/remoteEntry.js +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -5390,7 +5390,7 @@ var ZodIssueCode = {
|
|
|
5390
5390
|
var ZodFirstPartyTypeKind;
|
|
5391
5391
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5392
5392
|
//#endregion
|
|
5393
|
-
//#region ../types/dist/sleep-
|
|
5393
|
+
//#region ../types/dist/sleep-bwsTj221.mjs
|
|
5394
5394
|
/**
|
|
5395
5395
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5396
5396
|
* window to float samples (D455).
|
|
@@ -6657,7 +6657,6 @@ function createHandle(raw, opts) {
|
|
|
6657
6657
|
const writeAddon = (patch) => write("addon", opts.addonTree(), void 0, patch, () => readStoredAddonBlob(raw), (p) => raw.writeAddonStore(p));
|
|
6658
6658
|
const readAddonStoreResult = raw.readAddonStoreResult;
|
|
6659
6659
|
const readAddonStoreKeyResult = raw.readAddonStoreKeyResult;
|
|
6660
|
-
const readDeviceStoreBatch = raw.readDeviceStoreBatch;
|
|
6661
6660
|
const overrides = {
|
|
6662
6661
|
readAddonStore: async () => resolveRead("addon", await raw.readAddonStore()),
|
|
6663
6662
|
...readAddonStoreResult !== void 0 ? { readAddonStoreResult: async () => {
|
|
@@ -6681,12 +6680,12 @@ function createHandle(raw, opts) {
|
|
|
6681
6680
|
};
|
|
6682
6681
|
} } : {},
|
|
6683
6682
|
readDeviceStore: async (deviceId) => resolveRead(`device:${deviceId}`, await raw.readDeviceStore(deviceId)),
|
|
6684
|
-
|
|
6685
|
-
const rows = await readDeviceStoreBatch
|
|
6683
|
+
readDeviceStoreBatch: async (deviceIds) => {
|
|
6684
|
+
const rows = await raw.readDeviceStoreBatch(deviceIds);
|
|
6686
6685
|
const out = /* @__PURE__ */ new Map();
|
|
6687
6686
|
for (const [deviceId, blob] of rows) out.set(deviceId, await resolveRead(`device:${deviceId}`, blob));
|
|
6688
6687
|
return out;
|
|
6689
|
-
}
|
|
6688
|
+
},
|
|
6690
6689
|
writeAddonStore: async (patch) => {
|
|
6691
6690
|
await writeAddon(patch);
|
|
6692
6691
|
},
|
|
@@ -7513,7 +7512,7 @@ var BaseAddon = class {
|
|
|
7513
7512
|
return this._addonSecretTree;
|
|
7514
7513
|
}
|
|
7515
7514
|
deviceSecretTree() {
|
|
7516
|
-
this._deviceSecretTree ??= secretTreeFromSchema(this.deviceSettingsSchema());
|
|
7515
|
+
this._deviceSecretTree ??= mergeSecretStatePaths(secretTreeFromSchema(this.deviceSettingsSchema()), this.secretStatePaths);
|
|
7517
7516
|
return this._deviceSecretTree;
|
|
7518
7517
|
}
|
|
7519
7518
|
/**
|
|
@@ -7589,42 +7588,135 @@ var BaseAddon = class {
|
|
|
7589
7588
|
this[timerOf] = timer;
|
|
7590
7589
|
}
|
|
7591
7590
|
/**
|
|
7592
|
-
* Wrap `ctx.settings.readAddonStore()` with a
|
|
7593
|
-
*
|
|
7594
|
-
* swap, or any race where the SqliteSettingsBackend is between shutdown and
|
|
7595
|
-
* re-initialize) doesn't propagate up into `initialize()` and leave the
|
|
7591
|
+
* Wrap `ctx.settings.readAddonStore()` with a retry budget so a transient
|
|
7592
|
+
* settings-store outage doesn't propagate up into `initialize()` and leave the
|
|
7596
7593
|
* addon permanently broken.
|
|
7597
7594
|
*
|
|
7598
|
-
*
|
|
7599
|
-
*
|
|
7600
|
-
* `
|
|
7595
|
+
* Two kinds of outage, two budgets:
|
|
7596
|
+
* - the store's own restart fingerprints (`SqliteSettingsBackend not
|
|
7597
|
+
* initialized`, `provider not available`): a short budget, then the addon
|
|
7598
|
+
* falls back to `{}` (defaults) - its first successful patch rehydrates;
|
|
7599
|
+
* - a TRANSPORT failure (the hub is restarting while this runner boots:
|
|
7600
|
+
* `discovery deadline exceeded`, `parent could not route`, a refused or
|
|
7601
|
+
* timed-out connection). Since D870 a runner's settings read THROWS instead
|
|
7602
|
+
* of answering `{}`, so without a budget a hub restart ends in a respawn
|
|
7603
|
+
* loop. A long, bounded budget; only after it the error propagates - the
|
|
7604
|
+
* addon never runs on defaults for a store it could not ask.
|
|
7605
|
+
* Anything else propagates immediately so real bugs surface.
|
|
7601
7606
|
*/
|
|
7602
7607
|
async readAddonStoreWithRetry() {
|
|
7603
7608
|
const settings = this.rawSettings();
|
|
7604
7609
|
if (!settings) return {};
|
|
7605
|
-
const delaysMs = [
|
|
7606
|
-
150,
|
|
7607
|
-
350,
|
|
7608
|
-
600,
|
|
7609
|
-
900
|
|
7610
|
-
];
|
|
7611
7610
|
let lastErr;
|
|
7612
|
-
for (let attempt = 0
|
|
7611
|
+
for (let attempt = 0;; attempt++) try {
|
|
7613
7612
|
const stored = await settings.readAddonStore() ?? {};
|
|
7614
7613
|
this.settingsStoreReady = true;
|
|
7615
7614
|
return stored;
|
|
7616
7615
|
} catch (err) {
|
|
7617
7616
|
lastErr = err;
|
|
7618
|
-
const
|
|
7619
|
-
if (
|
|
7620
|
-
|
|
7621
|
-
|
|
7617
|
+
const kind = classifyStoreError(err);
|
|
7618
|
+
if (kind === "permanent") throw err;
|
|
7619
|
+
const delay = (kind === "transport" ? TRANSPORT_RETRY_DELAYS_MS : RESTART_RETRY_DELAYS_MS)[attempt];
|
|
7620
|
+
if (delay === void 0) {
|
|
7621
|
+
if (kind === "transport") throw err;
|
|
7622
|
+
break;
|
|
7623
|
+
}
|
|
7624
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
7622
7625
|
}
|
|
7623
7626
|
this.settingsStoreReady = false;
|
|
7624
7627
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
7625
7628
|
return {};
|
|
7626
7629
|
}
|
|
7627
7630
|
};
|
|
7631
|
+
/** The settings store's own restart fingerprints. */
|
|
7632
|
+
var RESTART_RETRY_DELAYS_MS = [
|
|
7633
|
+
150,
|
|
7634
|
+
350,
|
|
7635
|
+
600,
|
|
7636
|
+
900
|
|
7637
|
+
];
|
|
7638
|
+
/** A hub restarting under a booting runner: ~100 s in total. */
|
|
7639
|
+
var TRANSPORT_RETRY_DELAYS_MS = [
|
|
7640
|
+
150,
|
|
7641
|
+
350,
|
|
7642
|
+
600,
|
|
7643
|
+
900,
|
|
7644
|
+
2e3,
|
|
7645
|
+
5e3,
|
|
7646
|
+
1e4,
|
|
7647
|
+
2e4,
|
|
7648
|
+
3e4,
|
|
7649
|
+
3e4
|
|
7650
|
+
];
|
|
7651
|
+
var RESTART_FINGERPRINTS = ["SqliteSettingsBackend not initialized", "provider not available"];
|
|
7652
|
+
/** Node / socket error codes of a connection that did not happen or broke. */
|
|
7653
|
+
var TRANSPORT_CODES = new Set([
|
|
7654
|
+
"ECONNREFUSED",
|
|
7655
|
+
"ECONNRESET",
|
|
7656
|
+
"ETIMEDOUT",
|
|
7657
|
+
"EPIPE",
|
|
7658
|
+
"EHOSTUNREACH",
|
|
7659
|
+
"ENETUNREACH"
|
|
7660
|
+
]);
|
|
7661
|
+
/** tRPC error codes that mean "the other side is not answering now", not "your call is wrong". */
|
|
7662
|
+
var UNAVAILABLE_TRPC_CODES = new Set([
|
|
7663
|
+
"TIMEOUT",
|
|
7664
|
+
"SERVICE_UNAVAILABLE",
|
|
7665
|
+
"BAD_GATEWAY",
|
|
7666
|
+
"GATEWAY_TIMEOUT"
|
|
7667
|
+
]);
|
|
7668
|
+
/** The exact phrases OUR transport raises when it cannot reach the hub. */
|
|
7669
|
+
var TRANSPORT_PHRASES = [
|
|
7670
|
+
"discovery deadline exceeded",
|
|
7671
|
+
"parent could not route child unowned cap call",
|
|
7672
|
+
"UDS request timed out after",
|
|
7673
|
+
"channel closed"
|
|
7674
|
+
];
|
|
7675
|
+
/** Moleculer error `type`s of a call that could not be served right now. */
|
|
7676
|
+
var MOLECULER_TRANSIENT_TYPES = new Set([
|
|
7677
|
+
"REQUEST_TIMEOUT",
|
|
7678
|
+
"SERVICE_NOT_FOUND",
|
|
7679
|
+
"SERVICE_NOT_AVAILABLE",
|
|
7680
|
+
"REQUEST_REJECTED",
|
|
7681
|
+
"BROKER_DISCONNECTED"
|
|
7682
|
+
]);
|
|
7683
|
+
function stringProp(value, key) {
|
|
7684
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
7685
|
+
const found = Reflect.get(value, key);
|
|
7686
|
+
return typeof found === "string" ? found : void 0;
|
|
7687
|
+
}
|
|
7688
|
+
/** The code an error carries: its own, its cause's, or a tRPC `data.code`. */
|
|
7689
|
+
function errorCode(err) {
|
|
7690
|
+
const out = {};
|
|
7691
|
+
const cause = typeof err === "object" && err !== null ? Reflect.get(err, "cause") : void 0;
|
|
7692
|
+
const data = typeof err === "object" && err !== null ? Reflect.get(err, "data") : void 0;
|
|
7693
|
+
const node = stringProp(err, "code") ?? stringProp(cause, "code");
|
|
7694
|
+
if (node !== void 0) out.node = node;
|
|
7695
|
+
const trpc = stringProp(data, "code");
|
|
7696
|
+
if (trpc !== void 0) out.trpc = trpc;
|
|
7697
|
+
return out;
|
|
7698
|
+
}
|
|
7699
|
+
/**
|
|
7700
|
+
* Is a settings read failure worth retrying, and with which budget? Only
|
|
7701
|
+
* EXPLICIT signals count: a socket error code, a tRPC "unavailable" code, or
|
|
7702
|
+
* one of the exact phrases our own transport raises. A message that merely
|
|
7703
|
+
* contains "timed out" or "unreachable" is not evidence of anything, and
|
|
7704
|
+
* `settings store not wired` is a wiring bug that retrying cannot fix.
|
|
7705
|
+
*/
|
|
7706
|
+
function classifyStoreError(err) {
|
|
7707
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7708
|
+
if (RESTART_FINGERPRINTS.some((f) => message.includes(f))) return "restart";
|
|
7709
|
+
const code = errorCode(err);
|
|
7710
|
+
if (code.node !== void 0 && TRANSPORT_CODES.has(code.node)) return "transport";
|
|
7711
|
+
if (code.trpc !== void 0 && UNAVAILABLE_TRPC_CODES.has(code.trpc)) return "transport";
|
|
7712
|
+
if (typeof err === "object" && err !== null) {
|
|
7713
|
+
if (Reflect.get(err, "retryable") === true) return "transport";
|
|
7714
|
+
const type = stringProp(err, "type");
|
|
7715
|
+
if (type !== void 0 && MOLECULER_TRANSIENT_TYPES.has(type)) return "transport";
|
|
7716
|
+
}
|
|
7717
|
+
if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
|
|
7718
|
+
return "permanent";
|
|
7719
|
+
}
|
|
7628
7720
|
/**
|
|
7629
7721
|
* Collect the keys of every field marked `perNode: true`, recursing into
|
|
7630
7722
|
* layout containers (`group` fields and `sub-tabs` tabs) the same way
|
|
@@ -12770,11 +12862,10 @@ var ClipModelMetaSchema = object({
|
|
|
12770
12862
|
/**
|
|
12771
12863
|
* The `vector-store` index this model's vectors live in. ONE feature space
|
|
12772
12864
|
* per index: two models share an index only when their vectors are ranked
|
|
12773
|
-
* against each other, which for CLIP means never across families.
|
|
12774
|
-
*
|
|
12775
|
-
* `modelId`); any other model gets its own.
|
|
12865
|
+
* against each other, which for CLIP means never across families. Every
|
|
12866
|
+
* model gets its own.
|
|
12776
12867
|
*/
|
|
12777
|
-
vectorIndex: string().regex(/^object-clip
|
|
12868
|
+
vectorIndex: string().regex(/^object-clip-[a-z0-9][a-z0-9-]*$/),
|
|
12778
12869
|
/**
|
|
12779
12870
|
* The text encoder's tokenizer, a declared SIBLING file of its onnx. The name
|
|
12780
12871
|
* must be unique per tokenizer: every model's siblings land in ONE flat
|
|
@@ -16946,6 +17037,28 @@ id: union([string(), number()]) }), {
|
|
|
16946
17037
|
kind: "mutation",
|
|
16947
17038
|
auth: "admin"
|
|
16948
17039
|
});
|
|
17040
|
+
/** One table of the settings database. */
|
|
17041
|
+
var StorageTableSchema = object({
|
|
17042
|
+
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
17043
|
+
name: string(),
|
|
17044
|
+
/** The owner prefix of a scoped name (`recorder` for `recorder:addon-settings`), else null. */
|
|
17045
|
+
owner: string().nullable(),
|
|
17046
|
+
rows: number().int().nonnegative(),
|
|
17047
|
+
/** Bytes the table's pages occupy (`dbstat`); null when the engine cannot measure. */
|
|
17048
|
+
bytes: number().int().nonnegative().nullable(),
|
|
17049
|
+
/** Declared by an addon since this engine process started (a running addon claims it). */
|
|
17050
|
+
declaredThisBoot: boolean()
|
|
17051
|
+
});
|
|
17052
|
+
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
17053
|
+
collection: string().min(1),
|
|
17054
|
+
expectRows: number().int().nonnegative()
|
|
17055
|
+
}), object({
|
|
17056
|
+
dropped: literal(true),
|
|
17057
|
+
rows: number().int().nonnegative()
|
|
17058
|
+
}), {
|
|
17059
|
+
kind: "mutation",
|
|
17060
|
+
auth: "admin"
|
|
17061
|
+
});
|
|
16949
17062
|
/**
|
|
16950
17063
|
* `keychain` — the hub's encrypted store of secret values (D787).
|
|
16951
17064
|
*
|
|
@@ -17487,6 +17600,16 @@ method(object({}), KeychainStatusSchema, { auth: "admin" }), method(object({}),
|
|
|
17487
17600
|
kind: "mutation",
|
|
17488
17601
|
auth: "admin",
|
|
17489
17602
|
caller: "required"
|
|
17603
|
+
}), method(object({
|
|
17604
|
+
ref: string().min(1),
|
|
17605
|
+
value: string().min(1)
|
|
17606
|
+
}), object({
|
|
17607
|
+
ref: string(),
|
|
17608
|
+
version: number().int()
|
|
17609
|
+
}), {
|
|
17610
|
+
kind: "mutation",
|
|
17611
|
+
auth: "admin",
|
|
17612
|
+
caller: "required"
|
|
17490
17613
|
}), method(object({ refs: array(string().min(1)).max(1e3) }), object({
|
|
17491
17614
|
deleted: array(string()).readonly(),
|
|
17492
17615
|
kept: array(object({
|
|
@@ -56702,7 +56825,19 @@ var TlsStatusSchema = object({
|
|
|
56702
56825
|
sans: array(string()),
|
|
56703
56826
|
caCertPem: string().nullable(),
|
|
56704
56827
|
reissueError: string().nullable(),
|
|
56705
|
-
restartRequired: boolean()
|
|
56828
|
+
restartRequired: boolean(),
|
|
56829
|
+
/** An uploaded certificate is served but no CA is kept for it and it is not publicly signed (D873). */
|
|
56830
|
+
caMissing: boolean(),
|
|
56831
|
+
/** Does the hub's own generated CA carry a critical name constraint? `null` while it has none. */
|
|
56832
|
+
localCaConstrained: boolean().nullable(),
|
|
56833
|
+
/** ISO time the generated CA was replaced by a constrained one; devices must re-download it. */
|
|
56834
|
+
caReplacedAt: string().nullable(),
|
|
56835
|
+
/** The uploaded certificate kept on disk, selectable again after "Revert to generated". */
|
|
56836
|
+
storedUpload: object({
|
|
56837
|
+
leafFingerprintSha256: string(),
|
|
56838
|
+
validTo: string(),
|
|
56839
|
+
hasCa: boolean()
|
|
56840
|
+
}).nullable()
|
|
56706
56841
|
});
|
|
56707
56842
|
method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
|
|
56708
56843
|
/**
|
|
@@ -56758,6 +56893,9 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
|
|
|
56758
56893
|
}), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
|
|
56759
56894
|
kind: "mutation",
|
|
56760
56895
|
auth: "admin"
|
|
56896
|
+
}), method(_void(), TlsStatusSchema, {
|
|
56897
|
+
kind: "mutation",
|
|
56898
|
+
auth: "admin"
|
|
56761
56899
|
});
|
|
56762
56900
|
object({
|
|
56763
56901
|
/** Lifecycle state of the lock. `jammed` means the motor reported
|
|
@@ -65893,6 +66031,12 @@ Object.freeze({
|
|
|
65893
66031
|
addonId: null,
|
|
65894
66032
|
access: "create"
|
|
65895
66033
|
},
|
|
66034
|
+
"keychainAdmin.importSecret": {
|
|
66035
|
+
capName: "keychain-admin",
|
|
66036
|
+
capScope: "system",
|
|
66037
|
+
addonId: null,
|
|
66038
|
+
access: "create"
|
|
66039
|
+
},
|
|
65896
66040
|
"keychainAdmin.listAudit": {
|
|
65897
66041
|
capName: "keychain-admin",
|
|
65898
66042
|
capScope: "system",
|
|
@@ -66289,6 +66433,12 @@ Object.freeze({
|
|
|
66289
66433
|
addonId: null,
|
|
66290
66434
|
access: "create"
|
|
66291
66435
|
},
|
|
66436
|
+
"localNetwork.useStoredUploadedCertificate": {
|
|
66437
|
+
capName: "local-network",
|
|
66438
|
+
capScope: "system",
|
|
66439
|
+
addonId: null,
|
|
66440
|
+
access: "create"
|
|
66441
|
+
},
|
|
66292
66442
|
"lockControl.getStatus": {
|
|
66293
66443
|
capName: "lock-control",
|
|
66294
66444
|
capScope: "device",
|
|
@@ -69673,6 +69823,18 @@ Object.freeze({
|
|
|
69673
69823
|
addonId: null,
|
|
69674
69824
|
access: "create"
|
|
69675
69825
|
},
|
|
69826
|
+
"storageAdmin.dropCollection": {
|
|
69827
|
+
capName: "storage-admin",
|
|
69828
|
+
capScope: "system",
|
|
69829
|
+
addonId: null,
|
|
69830
|
+
access: "delete"
|
|
69831
|
+
},
|
|
69832
|
+
"storageAdmin.listTables": {
|
|
69833
|
+
capName: "storage-admin",
|
|
69834
|
+
capScope: "system",
|
|
69835
|
+
addonId: null,
|
|
69836
|
+
access: "view"
|
|
69837
|
+
},
|
|
69676
69838
|
"storageEvictable.evict": {
|
|
69677
69839
|
capName: "storage-evictable",
|
|
69678
69840
|
capScope: "system",
|
|
@@ -74718,7 +74880,11 @@ var REMOVED_MODEL_IDS = {
|
|
|
74718
74880
|
"face-embedding": ["arcface-r100", "inception-resnet-v1"],
|
|
74719
74881
|
"plate-detection": ["yolov8n-plate"],
|
|
74720
74882
|
"plate-ocr": ["vgg-english-g2"],
|
|
74721
|
-
"clip-embedding": [
|
|
74883
|
+
"clip-embedding": [
|
|
74884
|
+
"mobileclip-s0",
|
|
74885
|
+
"mobileclip-s1",
|
|
74886
|
+
"mobileclip-s2"
|
|
74887
|
+
],
|
|
74722
74888
|
"package-detection": ["yolov8n-package"],
|
|
74723
74889
|
"bird-classifier": ["bird-classifier-aiy-edgetpu", "bird-nabirds-404"],
|
|
74724
74890
|
"animal-classifier": ["animals-10"],
|
|
@@ -76615,6 +76781,22 @@ var DurableLedger = class DurableLedger {
|
|
|
76615
76781
|
}
|
|
76616
76782
|
}
|
|
76617
76783
|
/**
|
|
76784
|
+
* Drop every MIRRORED row about `deviceId` (per the spec's `deviceIdOf`),
|
|
76785
|
+
* leaving the durable rows to the caller's `deleteWhere` (D871). Returns how
|
|
76786
|
+
* many mirror entries went; a spec without `deviceIdOf` evicts nothing.
|
|
76787
|
+
*/
|
|
76788
|
+
evictDevice(deviceId) {
|
|
76789
|
+
const of = this.spec.deviceIdOf;
|
|
76790
|
+
if (of === void 0) return 0;
|
|
76791
|
+
let evicted = 0;
|
|
76792
|
+
for (const [key, row] of [...this.mirror.entries()]) {
|
|
76793
|
+
if (of(row) !== deviceId) continue;
|
|
76794
|
+
this.mirror.delete(key);
|
|
76795
|
+
evicted += 1;
|
|
76796
|
+
}
|
|
76797
|
+
return evicted;
|
|
76798
|
+
}
|
|
76799
|
+
/**
|
|
76618
76800
|
* Drop every mirrored key NOT in `activeKeys`. Returns how many rows went.
|
|
76619
76801
|
*
|
|
76620
76802
|
* **The caller must hold an AUTHORITATIVE active set.** A prune driven by a
|
|
@@ -83946,15 +84128,10 @@ var DeviceFeaturesMirror = class {
|
|
|
83946
84128
|
async hydrate() {
|
|
83947
84129
|
const settings = this.settings;
|
|
83948
84130
|
if (settings === null) return 0;
|
|
83949
|
-
const
|
|
83950
|
-
|
|
83951
|
-
const
|
|
83952
|
-
|
|
83953
|
-
const blobs = batch === void 0 ? new Map(await Promise.all(ids.map(async (id) => [id, await settings.readDeviceStore(id)]))) : await batch.call(settings, ids);
|
|
83954
|
-
for (const [deviceId, blob] of blobs) {
|
|
83955
|
-
const row = rowOf(deviceId, blob[DEVICE_FEATURES_KEY]);
|
|
83956
|
-
if (row !== null) this.local.set(deviceId, row);
|
|
83957
|
-
}
|
|
84131
|
+
const ids = await settings.listDeviceStoreIds();
|
|
84132
|
+
for (const [deviceId, blob] of await settings.readDeviceStoreBatch(ids)) {
|
|
84133
|
+
const row = rowOf(deviceId, blob[DEVICE_FEATURES_KEY]);
|
|
84134
|
+
if (row !== null) this.local.set(deviceId, row);
|
|
83958
84135
|
}
|
|
83959
84136
|
this.logger.info("device-features mirror restored", { meta: { devices: this.local.size } });
|
|
83960
84137
|
return this.local.size;
|
|
@@ -87612,25 +87789,33 @@ var NodeStressController = class NodeStressController {
|
|
|
87612
87789
|
//#region src/durable/lts-aggregator.ts
|
|
87613
87790
|
/** Wall-clock bucket width. Five minutes, matching HA's statistics tier. */
|
|
87614
87791
|
var LTS_BUCKET_MS = 5 * 6e4;
|
|
87792
|
+
/** Buckets written per transaction — bounds one statement, not the flush. */
|
|
87793
|
+
var FLUSH_BATCH = 200;
|
|
87615
87794
|
/** How often the row cap is enforced. Rarely: it is a bound, not a deadline. */
|
|
87616
87795
|
var CAP_SWEEP_INTERVAL_MS = 6 * 36e5;
|
|
87796
|
+
/**
|
|
87797
|
+
* The row's identity IS its four key columns (D871): a composite
|
|
87798
|
+
* `primaryKey` + `WITHOUT ROWID`, so the table is its own index and there is no
|
|
87799
|
+
* TEXT `id` repeating what the row already says. The old layout kept
|
|
87800
|
+
* `<subject>|<series>|<scope>|<bucketStart>` as a TEXT primary key beside the
|
|
87801
|
+
* four columns — 85 MB of rows plus a 44 MB autoindex for 1.07 M rows. A
|
|
87802
|
+
* composite-key collection is written with `upsertMany` (a bucket flushed twice
|
|
87803
|
+
* replaces itself) and read with `query` / `count` / `deleteWhere`; the calls
|
|
87804
|
+
* that address one row by id are refused by the engine.
|
|
87805
|
+
*/
|
|
87806
|
+
var LTS_KEY_COLUMNS = [
|
|
87807
|
+
"subject",
|
|
87808
|
+
"series",
|
|
87809
|
+
"scope",
|
|
87810
|
+
"bucketStart"
|
|
87811
|
+
];
|
|
87617
87812
|
var LTS_COLUMNS = [
|
|
87618
|
-
(
|
|
87619
|
-
/** `<subject>|<series>|<scope>|<bucketStart>` — deterministic, so a bucket
|
|
87620
|
-
* flushed twice replaces itself rather than doubling. */
|
|
87621
|
-
{
|
|
87622
|
-
name: "id",
|
|
87623
|
-
type: "TEXT",
|
|
87624
|
-
primaryKey: true,
|
|
87625
|
-
notNull: true
|
|
87626
|
-
}),
|
|
87627
87813
|
(
|
|
87628
87814
|
/** The camera id, or the node id. One column, because every query is
|
|
87629
87815
|
* "this thing over time" and the thing is one or the other. */
|
|
87630
87816
|
{
|
|
87631
87817
|
name: "subject",
|
|
87632
|
-
type: "TEXT"
|
|
87633
|
-
notNull: true
|
|
87818
|
+
type: "TEXT"
|
|
87634
87819
|
}),
|
|
87635
87820
|
(
|
|
87636
87821
|
/** Numeric mirror of `subject` for camera rows, so a per-camera question is
|
|
@@ -87642,22 +87827,19 @@ var LTS_COLUMNS = [
|
|
|
87642
87827
|
}),
|
|
87643
87828
|
{
|
|
87644
87829
|
name: "series",
|
|
87645
|
-
type: "TEXT"
|
|
87646
|
-
notNull: true
|
|
87830
|
+
type: "TEXT"
|
|
87647
87831
|
},
|
|
87648
87832
|
(
|
|
87649
87833
|
/** Sub-scope within a series: a zoneId for occupancy, `''` otherwise. */
|
|
87650
87834
|
{
|
|
87651
87835
|
name: "scope",
|
|
87652
|
-
type: "TEXT"
|
|
87653
|
-
notNull: true
|
|
87836
|
+
type: "TEXT"
|
|
87654
87837
|
}),
|
|
87655
87838
|
(
|
|
87656
87839
|
/** Bucket start, wall-clock aligned to {@link LTS_BUCKET_MS}. */
|
|
87657
87840
|
{
|
|
87658
87841
|
name: "bucketStart",
|
|
87659
|
-
type: "INTEGER"
|
|
87660
|
-
notNull: true
|
|
87842
|
+
type: "INTEGER"
|
|
87661
87843
|
}),
|
|
87662
87844
|
{
|
|
87663
87845
|
name: "samples",
|
|
@@ -87680,12 +87862,15 @@ var LTS_COLUMNS = [
|
|
|
87680
87862
|
notNull: true
|
|
87681
87863
|
}
|
|
87682
87864
|
];
|
|
87865
|
+
/**
|
|
87866
|
+
* The primary key serves every per-subject read (`subject, series, scope` then a
|
|
87867
|
+
* `bucketStart` range, already in bucket order); this index serves the read that
|
|
87868
|
+
* names a series without a subject. The old `deviceId` index went with the TEXT
|
|
87869
|
+
* id: nothing queries a series by the numeric mirror.
|
|
87870
|
+
*/
|
|
87683
87871
|
var LTS_INDEXES = [{
|
|
87684
87872
|
name: "idx_lts_series_bucket",
|
|
87685
87873
|
columns: ["series", "bucketStart"]
|
|
87686
|
-
}, {
|
|
87687
|
-
name: "idx_lts_device",
|
|
87688
|
-
columns: ["deviceId"]
|
|
87689
87874
|
}];
|
|
87690
87875
|
function ltsBucketStart(at, bucketMs = LTS_BUCKET_MS) {
|
|
87691
87876
|
return Math.floor(at / bucketMs) * bucketMs;
|
|
@@ -87714,6 +87899,8 @@ var LtsAggregator = class {
|
|
|
87714
87899
|
return store.declareCollection.mutate({
|
|
87715
87900
|
collection,
|
|
87716
87901
|
columns: [...LTS_COLUMNS],
|
|
87902
|
+
primaryKey: [...LTS_KEY_COLUMNS],
|
|
87903
|
+
withoutRowid: true,
|
|
87717
87904
|
indexes: [...LTS_INDEXES]
|
|
87718
87905
|
});
|
|
87719
87906
|
}
|
|
@@ -87773,43 +87960,60 @@ var LtsAggregator = class {
|
|
|
87773
87960
|
return 0;
|
|
87774
87961
|
}
|
|
87775
87962
|
let written = 0;
|
|
87776
|
-
for (const
|
|
87777
|
-
|
|
87778
|
-
|
|
87779
|
-
await this.store.set.mutate({
|
|
87780
|
-
collection: this.collection,
|
|
87781
|
-
key,
|
|
87782
|
-
value: {
|
|
87783
|
-
subject: bucket.subject,
|
|
87784
|
-
...bucket.deviceId !== void 0 ? { deviceId: bucket.deviceId } : {},
|
|
87785
|
-
series: bucket.series,
|
|
87786
|
-
scope: bucket.scope,
|
|
87787
|
-
bucketStart: bucket.bucketStart,
|
|
87788
|
-
samples: bucket.samples,
|
|
87789
|
-
sum: bucket.sum,
|
|
87790
|
-
min: bucket.min,
|
|
87791
|
-
max: bucket.max
|
|
87792
|
-
}
|
|
87793
|
-
});
|
|
87794
|
-
written += 1;
|
|
87795
|
-
this.groups.add(groupKey(bucket.subject, bucket.series, bucket.scope));
|
|
87796
|
-
} catch (err) {
|
|
87797
|
-
this.logger.warn("lts bucket write failed — this interval will be missing", {
|
|
87798
|
-
...bucket.deviceId !== void 0 ? { tags: { deviceId: bucket.deviceId } } : {},
|
|
87799
|
-
meta: {
|
|
87800
|
-
collection: this.collection,
|
|
87801
|
-
series: bucket.series,
|
|
87802
|
-
subject: bucket.subject,
|
|
87803
|
-
bucketStart: bucket.bucketStart,
|
|
87804
|
-
error: String(err)
|
|
87805
|
-
}
|
|
87806
|
-
});
|
|
87807
|
-
}
|
|
87808
|
-
this.open.delete(key);
|
|
87963
|
+
for (const batch of chunk(due, FLUSH_BATCH)) {
|
|
87964
|
+
written += await this.writeBatch(batch);
|
|
87965
|
+
for (const bucket of batch) this.open.delete(rowId(bucket.subject, bucket.series, bucket.scope, bucket.bucketStart));
|
|
87809
87966
|
}
|
|
87810
87967
|
await this.maybeSweepCap(now);
|
|
87811
87968
|
return written;
|
|
87812
87969
|
}
|
|
87970
|
+
/**
|
|
87971
|
+
* Upsert one batch in a single transaction. If the batch is refused as a
|
|
87972
|
+
* whole (all-or-nothing), each bucket is retried alone so one bad row costs
|
|
87973
|
+
* one interval, not forty. Returns the number of rows written.
|
|
87974
|
+
*/
|
|
87975
|
+
async writeBatch(batch) {
|
|
87976
|
+
try {
|
|
87977
|
+
await this.upsert(batch);
|
|
87978
|
+
for (const bucket of batch) this.groups.add(groupKey(bucket.subject, bucket.series, bucket.scope));
|
|
87979
|
+
return batch.length;
|
|
87980
|
+
} catch (err) {
|
|
87981
|
+
if (batch.length > 1) {
|
|
87982
|
+
let written = 0;
|
|
87983
|
+
for (const bucket of batch) written += await this.writeBatch([bucket]);
|
|
87984
|
+
return written;
|
|
87985
|
+
}
|
|
87986
|
+
const bucket = batch[0];
|
|
87987
|
+
this.logger.warn("lts bucket write failed — this interval will be missing", {
|
|
87988
|
+
...bucket?.deviceId !== void 0 ? { tags: { deviceId: bucket.deviceId } } : {},
|
|
87989
|
+
meta: {
|
|
87990
|
+
collection: this.collection,
|
|
87991
|
+
series: bucket?.series,
|
|
87992
|
+
subject: bucket?.subject,
|
|
87993
|
+
bucketStart: bucket?.bucketStart,
|
|
87994
|
+
error: String(err)
|
|
87995
|
+
}
|
|
87996
|
+
});
|
|
87997
|
+
return 0;
|
|
87998
|
+
}
|
|
87999
|
+
}
|
|
88000
|
+
async upsert(batch) {
|
|
88001
|
+
await this.store.upsertMany.mutate({
|
|
88002
|
+
collection: this.collection,
|
|
88003
|
+
conflict: [...LTS_KEY_COLUMNS],
|
|
88004
|
+
records: batch.map((bucket) => ({ data: {
|
|
88005
|
+
subject: bucket.subject,
|
|
88006
|
+
deviceId: bucket.deviceId ?? null,
|
|
88007
|
+
series: bucket.series,
|
|
88008
|
+
scope: bucket.scope,
|
|
88009
|
+
bucketStart: bucket.bucketStart,
|
|
88010
|
+
samples: bucket.samples,
|
|
88011
|
+
sum: bucket.sum,
|
|
88012
|
+
min: bucket.min,
|
|
88013
|
+
max: bucket.max
|
|
88014
|
+
} }))
|
|
88015
|
+
});
|
|
88016
|
+
}
|
|
87813
88017
|
/** Read closed buckets back. The read surface every chart will use. */
|
|
87814
88018
|
async read(query = {}) {
|
|
87815
88019
|
const where = {};
|
|
@@ -87894,6 +88098,11 @@ var LtsAggregator = class {
|
|
|
87894
88098
|
}
|
|
87895
88099
|
}
|
|
87896
88100
|
};
|
|
88101
|
+
function chunk(items, size) {
|
|
88102
|
+
const out = [];
|
|
88103
|
+
for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));
|
|
88104
|
+
return out;
|
|
88105
|
+
}
|
|
87897
88106
|
function groupKey(subject, series, scope) {
|
|
87898
88107
|
return `${subject}${series}${scope}`;
|
|
87899
88108
|
}
|
|
@@ -87952,7 +88161,7 @@ function recordToRow(data) {
|
|
|
87952
88161
|
* write="one row per (node, series, 5-min bucket), written ONCE when the bucket closes; a node reporting no samples writes nothing"
|
|
87953
88162
|
* retention="row CAP per (subject, series, scope) — 105,120 rows ≈ one year of 5-minute buckets. Not an age sweep: an LTS row summarises an interval and has no owner to be orphaned from."
|
|
87954
88163
|
*/
|
|
87955
|
-
var NODE_STRESS_LTS_COLLECTION = "pipeline-orchestrator:stats-5m";
|
|
88164
|
+
var NODE_STRESS_LTS_COLLECTION = "pipeline-orchestrator:stats-5m-v2";
|
|
87956
88165
|
var NodeStressLts = class {
|
|
87957
88166
|
lts;
|
|
87958
88167
|
constructor(deps) {
|
package/dist/remoteEntry.js
CHANGED
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_orchestrator_widgets-CxcjyRWF.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline-orchestrator",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.327",
|
|
4
4
|
"description": "Hub-side camera-to-agent load balancer — tracks runner capacity and dispatches attachCamera calls to the optimal pipeline-runner instance",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|