@camstack/system 1.2.57 → 1.2.59
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/addon-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/addon-utils.js +1 -1
- package/dist/addon-utils.mjs +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +2 -2
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +2 -2
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +2 -2
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +2 -2
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/binding-mirror.d.ts +65 -0
- package/dist/builtins/doorbell/virtual-doorbell.addon.d.ts +56 -11
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +248 -26
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +248 -26
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +2 -2
- package/dist/builtins/snapshot/index.mjs +2 -2
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +2 -2
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +2 -2
- package/dist/builtins/sqlite-storage/index.d.ts +3 -0
- package/dist/builtins/sqlite-storage/index.js +8 -0
- package/dist/builtins/sqlite-storage/index.mjs +2 -2
- package/dist/builtins/sqlite-storage/retired-settings-keys.d.ts +94 -0
- package/dist/builtins/sqlite-storage/sqlite-pragmas.d.ts +85 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +1 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +445 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +438 -3
- package/dist/builtins/sqlite-storage/wal-maintenance.d.ts +113 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-DhL_zGRT.mjs → dist-BqJJWCS8.mjs} +994 -34
- package/dist/{dist-BupxnZOi.js → dist-CV6XTApk.js} +1005 -33
- package/dist/index.js +190 -42
- package/dist/index.mjs +191 -43
- package/dist/kernel/addon-installer.d.ts +55 -7
- package/dist/kernel/addon-manifest.d.ts +36 -16
- package/dist/kernel/transport/frame-codec.d.ts +43 -2
- package/dist/{manifest-python-deps-Ck4-9K9m.mjs → manifest-python-deps-CX5tGRqf.mjs} +95 -10
- package/dist/{manifest-python-deps-BqE5j0-O.js → manifest-python-deps-d4acYXVV.js} +95 -10
- package/package.json +1 -1
- package/dist/{model-download-service-hf0ookyy.js → model-download-service-Cpc6SWzV.js} +1 -1
- package/dist/{model-download-service-Cp9f4dk6.mjs → model-download-service-D8B-4ktF.mjs} +1 -1
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
9
9
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { G as logDestinationCapability, pt as BaseAddon } from "../../dist-BqJJWCS8.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
4
4
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
4
4
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
5
5
|
var NO_DEVICES = "liveness:no-devices";
|
|
6
6
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Et as createEvent, ft as errMsg, pt as BaseAddon, zt as EventCategory } from "../../dist-BqJJWCS8.mjs";
|
|
2
2
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
3
3
|
var NO_DEVICES = "liveness:no-devices";
|
|
4
4
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
9
9
|
let crypto$1 = require("crypto");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { ct as userManagementCapability, d as ScopedTokenSchema, p as UserRecordSchema, pt as BaseAddon, r as ApiKeyRecordSchema, y as authProviderCapability } from "../../dist-BqJJWCS8.mjs";
|
|
3
3
|
import * as crypto$1 from "node:crypto";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import nodeCrypto from "crypto";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
4
4
|
let node_os = require("node:os");
|
|
5
5
|
node_os = require_chunk.__toESM(node_os);
|
|
6
6
|
//#region src/builtins/local-network/local-network.addon.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { W as localNetworkCapability, pt as BaseAddon, zt as EventCategory } from "../../dist-BqJJWCS8.mjs";
|
|
2
2
|
import * as os from "node:os";
|
|
3
3
|
//#region src/builtins/local-network/local-network.addon.ts
|
|
4
4
|
/**
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
7
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
8
8
|
/**
|
|
9
9
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { G as logDestinationCapability, pt as BaseAddon } from "../../dist-BqJJWCS8.mjs";
|
|
2
2
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
3
3
|
/**
|
|
4
4
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
9
|
let node_child_process = require("node:child_process");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Et as createEvent, J as metricsProviderCapability, pt as BaseAddon, zt as EventCategory } from "../../dist-BqJJWCS8.mjs";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import { execFile, execFileSync } from "node:child_process";
|
|
4
4
|
import { promisify } from "node:util";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
9
|
let node_child_process = require("node:child_process");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { A as enumerateInferenceDevices, Ot as emitReadiness, Q as platformProbeCapability, et as scoreRuntimes, ft as errMsg, pt as BaseAddon, zt as EventCategory } from "../../dist-BqJJWCS8.mjs";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import { execFile } from "node:child_process";
|
|
5
5
|
import { promisify } from "node:util";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
7
|
//#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
|
|
8
8
|
/**
|
|
9
9
|
* Reconcile the durable `enabledProviders` set against authoritative
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pt as BaseAddon, zt as EventCategory } from "../../dist-BqJJWCS8.mjs";
|
|
2
2
|
//#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
|
|
3
3
|
/**
|
|
4
4
|
* Reconcile the durable `enabledProviders` set against authoritative
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
7
|
let node_child_process = require("node:child_process");
|
|
8
8
|
//#region src/builtins/snapshot/snapshot-coalescing.ts
|
|
9
9
|
/**
|
|
@@ -604,7 +604,7 @@ var SnapshotAddon = class SnapshotAddon extends require_dist.BaseAddon {
|
|
|
604
604
|
access: "authenticated",
|
|
605
605
|
handler
|
|
606
606
|
}) ?? null;
|
|
607
|
-
this.ctx.logger.info("snapshot media data-plane served", { meta: { baseUrl: this.mediaDataPlane ? `/addon/${this.ctx.id}/media` : "(no dataPlane facility)" } });
|
|
607
|
+
this.ctx.logger.info("snapshot media data-plane served", { meta: { baseUrl: this.mediaDataPlane ? `/addon/${require_dist.bareAddonId(this.ctx.id)}/media` : "(no dataPlane facility)" } });
|
|
608
608
|
} catch (err) {
|
|
609
609
|
this.ctx.logger.warn("snapshot media data-plane failed to serve", { meta: { error: require_dist.errMsg(err) } });
|
|
610
610
|
this.mediaDataPlane = null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Mt as nodePin, _t as DeviceFeature, ft as errMsg, i as BatteryStatusSchema, ot as streamQualityLabel, pt as BaseAddon, rt as snapshotCapability, x as bareAddonId, yt as DeviceType } from "../../dist-BqJJWCS8.mjs";
|
|
2
2
|
import { execFile, spawn } from "node:child_process";
|
|
3
3
|
//#region src/builtins/snapshot/snapshot-coalescing.ts
|
|
4
4
|
/**
|
|
@@ -599,7 +599,7 @@ var SnapshotAddon = class SnapshotAddon extends BaseAddon {
|
|
|
599
599
|
access: "authenticated",
|
|
600
600
|
handler
|
|
601
601
|
}) ?? null;
|
|
602
|
-
this.ctx.logger.info("snapshot media data-plane served", { meta: { baseUrl: this.mediaDataPlane ? `/addon/${this.ctx.id}/media` : "(no dataPlane facility)" } });
|
|
602
|
+
this.ctx.logger.info("snapshot media data-plane served", { meta: { baseUrl: this.mediaDataPlane ? `/addon/${bareAddonId(this.ctx.id)}/media` : "(no dataPlane facility)" } });
|
|
603
603
|
} catch (err) {
|
|
604
604
|
this.ctx.logger.warn("snapshot media data-plane failed to serve", { meta: { error: errMsg(err) } });
|
|
605
605
|
this.mediaDataPlane = null;
|
|
@@ -3,12 +3,12 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CV6XTApk.js");
|
|
7
|
+
let node_crypto = require("node:crypto");
|
|
7
8
|
let node_fs = require("node:fs");
|
|
8
9
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
10
|
let node_path = require("node:path");
|
|
10
11
|
node_path = require_chunk.__toESM(node_path);
|
|
11
|
-
let node_crypto = require("node:crypto");
|
|
12
12
|
let node_os = require("node:os");
|
|
13
13
|
let node_fs_promises = require("node:fs/promises");
|
|
14
14
|
//#region src/builtins/sqlite-storage/path-guard.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { F as filesystemBrowseCapability, at as storageProviderCapability, pt as BaseAddon } from "../../dist-BqJJWCS8.mjs";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
2
3
|
import * as fs from "node:fs";
|
|
3
4
|
import * as path$1 from "node:path";
|
|
4
5
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
5
|
-
import { randomUUID } from "node:crypto";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
|
|
8
8
|
//#region src/builtins/sqlite-storage/path-guard.ts
|
|
@@ -3,5 +3,8 @@ export type { DeviceRow } from './device-store.js';
|
|
|
3
3
|
export { DeviceStore } from './device-store.js';
|
|
4
4
|
export { FilesystemStorageAddon, FilesystemStorageAddon as default, } from './filesystem-storage.addon.js';
|
|
5
5
|
export { FilesystemStorageProvider } from './filesystem-storage-provider.js';
|
|
6
|
+
export { SQLITE_JOURNAL_SIZE_LIMIT_BYTES, SQLITE_MMAP_SIZE_BYTES, SQLITE_PAGE_CACHE_KIB, } from './sqlite-pragmas.js';
|
|
6
7
|
export { SqliteSettingsAddon } from './sqlite-settings.addon.js';
|
|
7
8
|
export { SqliteSettingsBackend } from './sqlite-settings-backend.js';
|
|
9
|
+
export type { WalMaintenanceOptions, WalMaintenanceOutcome } from './wal-maintenance.js';
|
|
10
|
+
export { WAL_CHECKPOINT_BUSY_TIMEOUT_MS, WAL_HIGH_WATER_BYTES, WAL_IDLE_QUIET_MS, WAL_MAINTENANCE_INTERVAL_MS, WalMaintenance, } from './wal-maintenance.js';
|
|
@@ -57,6 +57,14 @@ exports.DeviceStore = DeviceStore;
|
|
|
57
57
|
exports.DeviceStore$1 = DeviceStore;
|
|
58
58
|
exports.FilesystemStorageAddon = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageAddon;
|
|
59
59
|
exports.FilesystemStorageProvider = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageProvider;
|
|
60
|
+
exports.SQLITE_JOURNAL_SIZE_LIMIT_BYTES = require_builtins_sqlite_storage_sqlite_settings_addon.SQLITE_JOURNAL_SIZE_LIMIT_BYTES;
|
|
61
|
+
exports.SQLITE_MMAP_SIZE_BYTES = require_builtins_sqlite_storage_sqlite_settings_addon.SQLITE_MMAP_SIZE_BYTES;
|
|
62
|
+
exports.SQLITE_PAGE_CACHE_KIB = require_builtins_sqlite_storage_sqlite_settings_addon.SQLITE_PAGE_CACHE_KIB;
|
|
60
63
|
exports.SqliteSettingsAddon = require_builtins_sqlite_storage_sqlite_settings_addon.SqliteSettingsAddon;
|
|
61
64
|
exports.SqliteSettingsBackend = require_builtins_sqlite_storage_sqlite_settings_addon.SqliteSettingsBackend;
|
|
65
|
+
exports.WAL_CHECKPOINT_BUSY_TIMEOUT_MS = require_builtins_sqlite_storage_sqlite_settings_addon.WAL_CHECKPOINT_BUSY_TIMEOUT_MS;
|
|
66
|
+
exports.WAL_HIGH_WATER_BYTES = require_builtins_sqlite_storage_sqlite_settings_addon.WAL_HIGH_WATER_BYTES;
|
|
67
|
+
exports.WAL_IDLE_QUIET_MS = require_builtins_sqlite_storage_sqlite_settings_addon.WAL_IDLE_QUIET_MS;
|
|
68
|
+
exports.WAL_MAINTENANCE_INTERVAL_MS = require_builtins_sqlite_storage_sqlite_settings_addon.WAL_MAINTENANCE_INTERVAL_MS;
|
|
69
|
+
exports.WalMaintenance = require_builtins_sqlite_storage_sqlite_settings_addon.WalMaintenance;
|
|
62
70
|
exports.default = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageAddon;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./filesystem-storage.addon.mjs";
|
|
2
|
-
import { SqliteSettingsAddon,
|
|
2
|
+
import { SqliteSettingsAddon, a as WalMaintenance, c as SQLITE_MMAP_SIZE_BYTES, i as WAL_MAINTENANCE_INTERVAL_MS, l as SQLITE_PAGE_CACHE_KIB, n as WAL_HIGH_WATER_BYTES, o as SqliteSettingsBackend, r as WAL_IDLE_QUIET_MS, s as SQLITE_JOURNAL_SIZE_LIMIT_BYTES, t as WAL_CHECKPOINT_BUSY_TIMEOUT_MS } from "./sqlite-settings.addon.mjs";
|
|
3
3
|
//#region src/builtins/sqlite-storage/config-store.ts
|
|
4
4
|
var ConfigStore = class {
|
|
5
5
|
db;
|
|
@@ -46,4 +46,4 @@ var DeviceStore = class {
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
//#endregion
|
|
49
|
-
export { ConfigStore, DeviceStore, FilesystemStorageAddon, FilesystemStorageAddon as default, FilesystemStorageProvider, SqliteSettingsAddon, SqliteSettingsBackend };
|
|
49
|
+
export { ConfigStore, DeviceStore, FilesystemStorageAddon, FilesystemStorageAddon as default, FilesystemStorageProvider, SQLITE_JOURNAL_SIZE_LIMIT_BYTES, SQLITE_MMAP_SIZE_BYTES, SQLITE_PAGE_CACHE_KIB, SqliteSettingsAddon, SqliteSettingsBackend, WAL_CHECKPOINT_BUSY_TIMEOUT_MS, WAL_HIGH_WATER_BYTES, WAL_IDLE_QUIET_MS, WAL_MAINTENANCE_INTERVAL_MS, WalMaintenance };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ISettingsBackend, SettingsCollection } from '@camstack/types';
|
|
2
|
+
/** One retired-key declaration, scoped to a single store row. */
|
|
3
|
+
export interface RetiredKeySpec {
|
|
4
|
+
/** Addon id owning the store (the settings-store namespace). */
|
|
5
|
+
readonly namespace: string;
|
|
6
|
+
/** Collection inside that namespace, e.g. `addon-settings`. */
|
|
7
|
+
readonly collection: SettingsCollection;
|
|
8
|
+
/** Row id inside the collection, e.g. `root`. */
|
|
9
|
+
readonly row: string;
|
|
10
|
+
/** Keys retired verbatim. Matched exactly. */
|
|
11
|
+
readonly keys: readonly string[];
|
|
12
|
+
/**
|
|
13
|
+
* Keys retired in both their bare form and their per-node form
|
|
14
|
+
* (`<key>@<nodeId>`), which is how `nodeScopedKey` persists a
|
|
15
|
+
* `perNode: true` schema field.
|
|
16
|
+
*/
|
|
17
|
+
readonly perNodeKeys: readonly string[];
|
|
18
|
+
/** Why they are dead — cited in the record, not re-derived at the call site. */
|
|
19
|
+
readonly reason: string;
|
|
20
|
+
}
|
|
21
|
+
/** What a purge pass deleted from one row. */
|
|
22
|
+
export interface RetiredKeyPurgeResult {
|
|
23
|
+
readonly addon: string;
|
|
24
|
+
readonly collection: string;
|
|
25
|
+
readonly row: string;
|
|
26
|
+
readonly keys: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/** The store access the purge needs. Narrow on purpose — trivially fakeable. */
|
|
29
|
+
export interface RetiredKeyStore {
|
|
30
|
+
/** Current row value, or `null` when the row does not exist. Throws on fault. */
|
|
31
|
+
read(spec: RetiredKeySpec): Promise<Record<string, unknown> | null>;
|
|
32
|
+
/** Replace the row with `value`. */
|
|
33
|
+
write(spec: RetiredKeySpec, value: Record<string, unknown>): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Is THIS node the one whose settings store is the cluster's authority?
|
|
37
|
+
*
|
|
38
|
+
* Mirrors `resolveNodeRole` (server/backend `node-role.ts`) — unset or `'hub'`
|
|
39
|
+
* means hub, which is the launcher's own default. It is duplicated rather than
|
|
40
|
+
* imported because `@camstack/system` is a dependency OF the backend, not the
|
|
41
|
+
* other way round; the parse is four lines and the env var is the contract.
|
|
42
|
+
*
|
|
43
|
+
* Anything else answers `false`. Skipping where the purge should have run is a
|
|
44
|
+
* missed cleanup the next hub boot fixes; running where it should not have is a
|
|
45
|
+
* write to a store this node does not own. Only one of those is recoverable.
|
|
46
|
+
*/
|
|
47
|
+
export declare function settingsStoreIsAuthoritativeHere(env: NodeJS.ProcessEnv): boolean;
|
|
48
|
+
/** The logging surface the purge uses — a structural subset of `IScopedLogger`. */
|
|
49
|
+
export interface RetiredKeyLogger {
|
|
50
|
+
info(message: string, context?: {
|
|
51
|
+
readonly meta?: Record<string, unknown>;
|
|
52
|
+
}): void;
|
|
53
|
+
warn(message: string, context?: {
|
|
54
|
+
readonly meta?: Record<string, unknown>;
|
|
55
|
+
}): void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The dead keys, per row.
|
|
59
|
+
*
|
|
60
|
+
* `detection-pipeline` / `addon-settings` / `root` — every key in this row is
|
|
61
|
+
* dead; the row itself is kept because the addon writes live keys into it
|
|
62
|
+
* (`pipelineTemplates`, `videoPipelineSteps`).
|
|
63
|
+
*
|
|
64
|
+
* - `pipelineSteps` / `pipelineEngine`: the persisted GLOBAL step + engine
|
|
65
|
+
* seed. Removed with `getGlobalSteps` becoming pure — dispatch builds steps
|
|
66
|
+
* from the orchestrator's `agentSettings` plus per-camera overrides, and
|
|
67
|
+
* never consulted the seed. See `addon-pipeline/src/detection-pipeline/provider.ts`.
|
|
68
|
+
* - `engineRuntime` / `engineBackend` / `engineDevice` / `probedBestEngine`:
|
|
69
|
+
* the per-node engine CASCADE, removed with the operator-facing engine
|
|
70
|
+
* election. Each node now runs a device-array of inference pools balanced
|
|
71
|
+
* per session, and the node-default pool derives live from the node's own
|
|
72
|
+
* hardware (`resolveAutoEngine`). See
|
|
73
|
+
* `addon-pipeline/src/detection-pipeline/engine-store-keys.ts`.
|
|
74
|
+
*/
|
|
75
|
+
export declare const RETIRED_SETTINGS_KEYS: readonly RetiredKeySpec[];
|
|
76
|
+
/**
|
|
77
|
+
* Adapt the settings backend to {@link RetiredKeyStore}.
|
|
78
|
+
*
|
|
79
|
+
* `get` answering a non-object (missing row) is a MISS, not a fault: it maps to
|
|
80
|
+
* `null` and the purge skips the row. A backend throw propagates, which is what
|
|
81
|
+
* routes it to the "read failed, row left untouched" branch.
|
|
82
|
+
*/
|
|
83
|
+
export declare function retiredKeyStoreOf(backend: ISettingsBackend): RetiredKeyStore;
|
|
84
|
+
/** Keys of `blob` that `spec` retires. Pure. */
|
|
85
|
+
export declare function planRetiredKeyPurge(blob: Readonly<Record<string, unknown>>, spec: RetiredKeySpec): readonly string[];
|
|
86
|
+
/**
|
|
87
|
+
* Delete every retired key present in the declared rows — on the hub.
|
|
88
|
+
*
|
|
89
|
+
* Off the authoritative node this is a no-op that touches nothing and says
|
|
90
|
+
* nothing (see the module header). Returns one entry per row that actually
|
|
91
|
+
* changed — empty when the store is already clean, which is the steady state
|
|
92
|
+
* after the first boot that ran it.
|
|
93
|
+
*/
|
|
94
|
+
export declare function purgeRetiredSettingsKeys(store: RetiredKeyStore, logger: RetiredKeyLogger, specs?: readonly RetiredKeySpec[], env?: NodeJS.ProcessEnv): Promise<readonly RetiredKeyPurgeResult[]>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection tuning for the hub's SQLite database.
|
|
3
|
+
*
|
|
4
|
+
* Every number here is sized against a MEASURED database, not a blog post.
|
|
5
|
+
* On the live hub (2026-08-06), 20 Hz syscall sampling of hub-main put **210
|
|
6
|
+
* of 2,561 samples inside `pread64`** — 161 on `camstack.db` and 49 on
|
|
7
|
+
* `camstack.db-wal`, all 4 KiB page reads, i.e. page-cache misses. That is
|
|
8
|
+
* 8.2% of wall-clock and ~20% during bursts, on the single thread that also
|
|
9
|
+
* serves every tRPC request. fds 79/81 of hub-main were the two files, so the
|
|
10
|
+
* cost is proven in-process rather than inferred.
|
|
11
|
+
*
|
|
12
|
+
* The database was **130 MB** with a **249 MB** WAL high-water mark. Its
|
|
13
|
+
* tenants are not settings: the analytics event/track/media stores and the
|
|
14
|
+
* sqlite-vec index all live in this one file.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Page cache, in KiB (SQLite reads a NEGATIVE `cache_size` as KiB rather than
|
|
18
|
+
* as a page count, which is what makes it independent of `page_size`).
|
|
19
|
+
*
|
|
20
|
+
* -65536 = **64 MiB**. Sized from the 130 MB file: the hot working set is the
|
|
21
|
+
* B-tree interior pages plus the indexes the analytics queries walk, which is
|
|
22
|
+
* a fraction of the total — 64 MiB covers roughly half the file outright, so a
|
|
23
|
+
* repeated query stops re-reading the same 4 KiB pages from disk. Going to the
|
|
24
|
+
* full 130 MB would buy the tail of a cold table scan for twice the resident
|
|
25
|
+
* cost; going smaller leaves the measured miss rate roughly where it is.
|
|
26
|
+
*
|
|
27
|
+
* Why the build default is not enough: better-sqlite3 compiles with
|
|
28
|
+
* `SQLITE_DEFAULT_CACHE_SIZE=-16000`, so the starting point is ~16 MiB — 8x
|
|
29
|
+
* short of the file, not the ~2 MiB stock SQLite default. This is a 4x
|
|
30
|
+
* increase, not a 32x one.
|
|
31
|
+
*
|
|
32
|
+
* Cost: 64 MiB of malloc'd C memory, ONE connection's worth (better-sqlite3
|
|
33
|
+
* holds a single handle and the vector index shares it). It is off-heap, so it
|
|
34
|
+
* does not move V8's heap ceiling — the thing that produced the hub's previous
|
|
35
|
+
* OOM.
|
|
36
|
+
*/
|
|
37
|
+
export declare const SQLITE_PAGE_CACHE_KIB = -65536;
|
|
38
|
+
/**
|
|
39
|
+
* Memory-mapped I/O window, in bytes. 268435456 = **256 MiB**.
|
|
40
|
+
*
|
|
41
|
+
* Chosen to exceed the 130 MB database with room for it to roughly double, so
|
|
42
|
+
* the whole main file can be mapped. Pages then arrive as minor faults against
|
|
43
|
+
* the OS page cache instead of `pread64` syscalls — which is precisely the
|
|
44
|
+
* 161-sample half of the measurement. It also means a page evicted from
|
|
45
|
+
* SQLite's own cache is usually still resident in the OS cache, so the two
|
|
46
|
+
* knobs compound rather than duplicate.
|
|
47
|
+
*
|
|
48
|
+
* Two honest caveats:
|
|
49
|
+
* - SQLite **never mmaps the WAL**. The 49 WAL samples are not addressed
|
|
50
|
+
* here; they are addressed by keeping the WAL small (see
|
|
51
|
+
* {@link SQLITE_JOURNAL_SIZE_LIMIT_BYTES} and `wal-maintenance.ts`).
|
|
52
|
+
* - With mmap, an I/O error on a mapped page surfaces as SIGBUS rather than a
|
|
53
|
+
* catchable SQLite error. The pragma is asserted in
|
|
54
|
+
* `__tests__/sqlite-pragmas.spec.ts` by reading it back, so a build that
|
|
55
|
+
* ignores it (`SQLITE_MAX_MMAP_SIZE=0`) fails loudly instead of quietly
|
|
56
|
+
* doing nothing.
|
|
57
|
+
*/
|
|
58
|
+
export declare const SQLITE_MMAP_SIZE_BYTES = 268435456;
|
|
59
|
+
/**
|
|
60
|
+
* Upper bound on the WAL file left on disk after a checkpoint resets it, in
|
|
61
|
+
* bytes. 67108864 = **64 MiB**.
|
|
62
|
+
*
|
|
63
|
+
* This is the passive half of the WAL fix and it carries no stall risk at all:
|
|
64
|
+
* it takes no lock and blocks nothing. It only says "when a checkpoint has
|
|
65
|
+
* already succeeded, truncate the file rather than leaving the space
|
|
66
|
+
* allocated". Without it, a WAL that spiked once stays spiked — which is how
|
|
67
|
+
* a 130 MB database ends up with a 249 MB sidecar.
|
|
68
|
+
*
|
|
69
|
+
* 64 MiB is deliberately well above the ~4 MiB `wal_autocheckpoint` threshold
|
|
70
|
+
* (1000 pages), so ordinary operation never touches this ceiling and the file
|
|
71
|
+
* is not being repeatedly truncated and re-grown.
|
|
72
|
+
*/
|
|
73
|
+
export declare const SQLITE_JOURNAL_SIZE_LIMIT_BYTES = 67108864;
|
|
74
|
+
/**
|
|
75
|
+
* `synchronous` is deliberately NOT set here.
|
|
76
|
+
*
|
|
77
|
+
* better-sqlite3 compiles with `SQLITE_DEFAULT_WAL_SYNCHRONOUS=1`, so a WAL
|
|
78
|
+
* database is **already** at `NORMAL`. Writing `PRAGMA synchronous = NORMAL`
|
|
79
|
+
* would be a no-op that reads, forever after, like a durability decision
|
|
80
|
+
* somebody made — the kind of leftover that is worse than nothing because it
|
|
81
|
+
* looks like verification. `__tests__/sqlite-pragmas.spec.ts` asserts the
|
|
82
|
+
* effective value instead, so a dependency bump that changes the default is
|
|
83
|
+
* caught rather than assumed.
|
|
84
|
+
*/
|
|
85
|
+
export declare const SQLITE_SYNCHRONOUS_IS_BUILD_DEFAULT = true;
|
|
@@ -20,6 +20,7 @@ import { SqliteVecVectorIndex } from './vector-index-vec.js';
|
|
|
20
20
|
export declare class SqliteSettingsAddon extends BaseAddon {
|
|
21
21
|
private backend;
|
|
22
22
|
private vectorIndex;
|
|
23
|
+
private walMaintenance;
|
|
23
24
|
constructor();
|
|
24
25
|
protected onInitialize(): Promise<ProviderRegistration[]>;
|
|
25
26
|
protected onShutdown(): Promise<void>;
|