@camstack/system 1.2.442 → 1.2.444
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/assets/record-entries/icon.svg +8 -0
- package/dist/addon-runner.js +41 -11
- package/dist/addon-runner.mjs +42 -12
- 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 +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.d.ts +10 -2
- package/dist/builtins/alerts/alerts.addon.js +43 -10
- package/dist/builtins/alerts/alerts.addon.mjs +43 -10
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.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/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.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/block-package.d.ts +4 -2
- package/dist/builtins/core-blocks/block-settings-store.d.ts +65 -19
- package/dist/builtins/core-blocks/core-blocks.addon.js +365 -38
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +365 -38
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- 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 +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
- package/dist/builtins/local-network/local-network.addon.js +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- 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 +2 -2
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +2 -2
- package/dist/builtins/platform-probe/index.js +2 -2
- package/dist/builtins/platform-probe/index.mjs +2 -2
- package/dist/builtins/record-entries/entries-service.d.ts +42 -0
- package/dist/builtins/record-entries/index.d.ts +1 -0
- package/dist/builtins/record-entries/index.js +142 -0
- package/dist/builtins/record-entries/index.mjs +136 -0
- package/dist/builtins/record-entries/record-entries.addon.d.ts +13 -0
- 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 +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/file-host-client.d.ts +2 -0
- package/dist/builtins/sqlite-storage/file-host-handlers.d.ts +4 -0
- package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +7 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +7 -0
- package/dist/builtins/sqlite-storage/placement-router.d.ts +5 -0
- package/dist/builtins/sqlite-storage/records/records-catalog.d.ts +29 -0
- package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +46 -0
- package/dist/builtins/sqlite-storage/records/records-engine.d.ts +90 -0
- package/dist/builtins/sqlite-storage/records/records-explain.d.ts +18 -0
- package/dist/builtins/sqlite-storage/records/records-plan.d.ts +90 -0
- package/dist/builtins/sqlite-storage/records/records-probe.d.ts +33 -0
- package/dist/builtins/sqlite-storage/records/records-provider.d.ts +59 -0
- package/dist/builtins/sqlite-storage/records/records-rows.d.ts +46 -0
- package/dist/builtins/sqlite-storage/records/records-sql.d.ts +41 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +0 -10
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +337 -4
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +337 -4
- package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +7 -1
- 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 +2 -2
- package/dist/builtins/system-config/system-config.addon.mjs +2 -2
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-CftPpY4O.mjs → composition-sources-C3rKncIF.mjs} +1 -1
- package/dist/{composition-sources-DmSEMtUD.js → composition-sources-NAPZddic.js} +1 -1
- package/dist/{constants-2iWQ-Nx-.mjs → constants-BKX2QnIg.mjs} +1 -1
- package/dist/{constants-b7kpjuO4.js → constants-BXiNEIeV.js} +1 -1
- package/dist/{device-ca-tKY_ZS9H.js → device-ca-DT9X2S6d.js} +1 -1
- package/dist/{device-ca-BJpYTAPg.mjs → device-ca-jxjSL8Ov.mjs} +1 -1
- package/dist/{dist-CyIHDLCg.js → dist-D1vECb_6.js} +1247 -120
- package/dist/{dist-DsrQYcLm.mjs → dist-DERK-gP5.mjs} +1068 -121
- package/dist/file-host-worker.js +11 -1
- package/dist/file-host-worker.mjs +11 -1
- package/dist/{hub-mdns-ciao-BS2akjWx.mjs → hub-mdns-ciao-CRaC97V0.mjs} +1 -1
- package/dist/{hub-mdns-ciao-Da-0NEyr.js → hub-mdns-ciao-Cah9GCIg.js} +1 -1
- package/dist/index.js +53 -21
- package/dist/index.mjs +54 -22
- package/dist/kernel/moleculer/records-api-transport.d.ts +9 -0
- package/dist/kernel/settings-view-types.d.ts +0 -7
- package/dist/{restore-archive-Cdf09dHm.js → restore-archive-Dy-qKTdF.js} +1 -1
- package/dist/{restore-archive-RaA3uZ7H.mjs → restore-archive-daKyE24F.mjs} +1 -1
- package/dist/{wal-maintenance-C-bmkDhm.js → wal-maintenance-dAv4IdzC.js} +0 -0
- package/dist/{wal-maintenance-DE8QrreK.mjs → wal-maintenance-zRc24mOC.mjs} +0 -0
- package/package.json +22 -1
- package/dist/{custom-action-registry-BKmoaqG0.js → custom-action-registry-COyb49zm.js} +1 -1
- package/dist/{custom-action-registry-CyUuhATc.mjs → custom-action-registry-stpC3Zy-.mjs} +1 -1
|
@@ -3,9 +3,9 @@ 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-D1vECb_6.js");
|
|
7
7
|
const require_retired_settings_keys = require("../../retired-settings-keys-D_VwZiDt.js");
|
|
8
|
-
const require_wal_maintenance = require("../../wal-maintenance-
|
|
8
|
+
const require_wal_maintenance = require("../../wal-maintenance-dAv4IdzC.js");
|
|
9
9
|
const require_sqlite_snapshot_protocol = require("../../sqlite-snapshot-protocol-B9OndqZv.js");
|
|
10
10
|
const require_wal_checkpoint_policy = require("../../wal-checkpoint-policy-d2z2qPqx.js");
|
|
11
11
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -107,6 +107,13 @@ var FileHostClient = class {
|
|
|
107
107
|
input
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
|
+
records(op, input) {
|
|
111
|
+
return this.request({
|
|
112
|
+
kind: "records",
|
|
113
|
+
op,
|
|
114
|
+
input
|
|
115
|
+
});
|
|
116
|
+
}
|
|
110
117
|
control(op, input) {
|
|
111
118
|
return this.request({
|
|
112
119
|
kind: "control",
|
|
@@ -869,6 +876,7 @@ var InlineOwnedFile = class extends OwnedFileBase {
|
|
|
869
876
|
vectorIndex = null;
|
|
870
877
|
vectorProvider = null;
|
|
871
878
|
maintenance = null;
|
|
879
|
+
recordsEngine = null;
|
|
872
880
|
constructor(spec, deps) {
|
|
873
881
|
super(spec, deps);
|
|
874
882
|
this.backend = new require_wal_maintenance.SqliteSettingsBackend(spec.livePath, deps.runtimeDefaults === void 0 ? {} : { ...deps.runtimeDefaults }, this.log("Query"), {
|
|
@@ -886,6 +894,11 @@ var InlineOwnedFile = class extends OwnedFileBase {
|
|
|
886
894
|
this.vectorIndex = vectorIndex;
|
|
887
895
|
this.vectorProvider = require_wal_maintenance.vectorProviderOf(vectorIndex);
|
|
888
896
|
}
|
|
897
|
+
const handle = this.backend.getDatabase();
|
|
898
|
+
if (handle !== null) this.recordsEngine = new require_wal_maintenance.RecordsEngine(handle, {
|
|
899
|
+
databaseId: this.spec.databaseId,
|
|
900
|
+
logger: this.log("Records")
|
|
901
|
+
});
|
|
889
902
|
await this.deps.afterOpen?.(this);
|
|
890
903
|
const db = this.backend.getDatabase();
|
|
891
904
|
if (db !== null) {
|
|
@@ -907,6 +920,10 @@ var InlineOwnedFile = class extends OwnedFileBase {
|
|
|
907
920
|
if (op === "declareCollection") this.declared = this.backend.declaredCollectionNames();
|
|
908
921
|
return result;
|
|
909
922
|
}
|
|
923
|
+
async records(op, input) {
|
|
924
|
+
if (this.recordsEngine === null) throw new Error(`database "${this.databaseId}" is not open`);
|
|
925
|
+
return require_wal_maintenance.callRecords(this.recordsEngine, op, input);
|
|
926
|
+
}
|
|
910
927
|
async vector(op, input) {
|
|
911
928
|
if (this.vectorProvider === null) throw new Error(`database "${this.databaseId}" does not serve vector calls`);
|
|
912
929
|
return require_wal_maintenance.callVector(this.vectorProvider, op, input);
|
|
@@ -962,6 +979,9 @@ var WorkerOwnedFile = class extends OwnedFileBase {
|
|
|
962
979
|
vector(op, input) {
|
|
963
980
|
return this.client.vector(op, input);
|
|
964
981
|
}
|
|
982
|
+
records(op, input) {
|
|
983
|
+
return this.client.records(op, input);
|
|
984
|
+
}
|
|
965
985
|
declaredCollections() {
|
|
966
986
|
return this.client.declaredCollections();
|
|
967
987
|
}
|
|
@@ -1094,6 +1114,14 @@ var PlacementRouter = class {
|
|
|
1094
1114
|
databaseOf(table) {
|
|
1095
1115
|
return this.placement.get(table) ?? "settings";
|
|
1096
1116
|
}
|
|
1117
|
+
/**
|
|
1118
|
+
* The file that hosts records of `databaseId`, created by the first
|
|
1119
|
+
* declaration that names it (`events`). `history` never hosts records.
|
|
1120
|
+
*/
|
|
1121
|
+
async recordsFileFor(databaseId) {
|
|
1122
|
+
if (databaseId === "history") throw new Error("placement: history.db is device-history's and never hosts records");
|
|
1123
|
+
return this.openFile(databaseId);
|
|
1124
|
+
}
|
|
1097
1125
|
/** The files currently open, settings first. */
|
|
1098
1126
|
openFiles() {
|
|
1099
1127
|
return require_dist.DATA_STORE_DATABASES.flatMap((id) => {
|
|
@@ -1204,6 +1232,267 @@ var PlacementRouter = class {
|
|
|
1204
1232
|
}
|
|
1205
1233
|
};
|
|
1206
1234
|
//#endregion
|
|
1235
|
+
//#region src/builtins/sqlite-storage/records/records-provider.ts
|
|
1236
|
+
/**
|
|
1237
|
+
* The `records` capability of the engine (D881): resolves WHO is calling and
|
|
1238
|
+
* WHICH file a kind lives in, then hands the call to that file's records engine.
|
|
1239
|
+
*
|
|
1240
|
+
* - **Owner** = the transport-stamped `callerAddonId` (as device-history's
|
|
1241
|
+
* `not-owner` and the keychain). It is never a field of any input; a call with
|
|
1242
|
+
* no stamp is refused `records/no-caller`.
|
|
1243
|
+
* - **Placement**: a kind's file is its declaration's `database`. The map is
|
|
1244
|
+
* rebuilt from each open file's own `_record_kinds` at boot and updated on
|
|
1245
|
+
* declaration. A kind declared for another file than the one it lives in is
|
|
1246
|
+
* refused (the engine never moves data, D853).
|
|
1247
|
+
* - **The boot guard**: after a declaration, a kind with `adoptsFrom` that is
|
|
1248
|
+
* EMPTY while its legacy table still holds rows is reported `adoptionPending`;
|
|
1249
|
+
* `ctx.records.declare` turns that into a refusal to start.
|
|
1250
|
+
*/
|
|
1251
|
+
/** The caller the transport stamped, or a refusal. */
|
|
1252
|
+
function recordsCallerOf(input) {
|
|
1253
|
+
const raw = input !== null && typeof input === "object" ? Reflect.get(input, "callerAddonId") : void 0;
|
|
1254
|
+
if (typeof raw !== "string" || raw.length === 0) throw new require_dist.NoCallerError("the call carries no caller identity; records are reached through ctx.records");
|
|
1255
|
+
return require_dist.normalizeSecretOwner(raw);
|
|
1256
|
+
}
|
|
1257
|
+
function keyOf(owner, kind) {
|
|
1258
|
+
return `${owner}\u0000${kind}`;
|
|
1259
|
+
}
|
|
1260
|
+
var RecordsProvider = class {
|
|
1261
|
+
router;
|
|
1262
|
+
logger;
|
|
1263
|
+
placement = /* @__PURE__ */ new Map();
|
|
1264
|
+
constructor(router, logger) {
|
|
1265
|
+
this.router = router;
|
|
1266
|
+
this.logger = logger;
|
|
1267
|
+
}
|
|
1268
|
+
/** Rebuild the placement map from every open file's catalog. Call once, after the files are open. */
|
|
1269
|
+
async init() {
|
|
1270
|
+
this.placement.clear();
|
|
1271
|
+
for (const file of this.router.openFiles()) {
|
|
1272
|
+
if (file.databaseId === "history") continue;
|
|
1273
|
+
const kinds = await file.records("listKinds", {});
|
|
1274
|
+
for (const k of kinds) {
|
|
1275
|
+
if (k.state === "dropped") continue;
|
|
1276
|
+
const key = keyOf(k.owner, k.kind);
|
|
1277
|
+
const other = this.placement.get(key);
|
|
1278
|
+
if (other !== void 0 && other !== file.databaseId) throw new require_dist.DeclarationRefusedError(`kind "${k.kind}" of "${k.owner}" is in both "${other}" and "${file.databaseId}"; the layout is corrupt and is not served`);
|
|
1279
|
+
this.placement.set(key, file.databaseId);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
this.logger.info("records: catalog loaded", { meta: { kinds: this.placement.size } });
|
|
1283
|
+
}
|
|
1284
|
+
fileOf(owner, kind) {
|
|
1285
|
+
const database = this.placement.get(keyOf(owner, kind));
|
|
1286
|
+
if (database === void 0) return Promise.reject(new require_dist.UnknownRecordKindError(`"${owner}" declared no kind "${kind}"`));
|
|
1287
|
+
return this.router.recordsFileFor(database);
|
|
1288
|
+
}
|
|
1289
|
+
async declareKinds(input) {
|
|
1290
|
+
const owner = recordsCallerOf(input);
|
|
1291
|
+
const byDatabase = /* @__PURE__ */ new Map();
|
|
1292
|
+
for (const [kind, raw] of Object.entries(input.kinds)) {
|
|
1293
|
+
const declaration = require_dist.RecordKindDeclarationSchema.parse(raw);
|
|
1294
|
+
const known = this.placement.get(keyOf(owner, kind));
|
|
1295
|
+
if (known !== void 0 && known !== declaration.database) throw new require_dist.DeclarationRefusedError(`kind "${kind}" of "${owner}" lives in "${known}", declared for "${declaration.database}" - the engine never moves data`);
|
|
1296
|
+
const group = byDatabase.get(declaration.database) ?? {};
|
|
1297
|
+
byDatabase.set(declaration.database, {
|
|
1298
|
+
...group,
|
|
1299
|
+
[kind]: declaration
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
const merged = {};
|
|
1303
|
+
for (const [database, kinds] of byDatabase) {
|
|
1304
|
+
const { kinds: results } = await (await this.router.recordsFileFor(database)).records("declareKinds", {
|
|
1305
|
+
owner,
|
|
1306
|
+
kinds
|
|
1307
|
+
});
|
|
1308
|
+
for (const [kind, result] of Object.entries(results)) {
|
|
1309
|
+
this.placement.set(keyOf(owner, kind), database);
|
|
1310
|
+
merged[kind] = result;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
return { kinds: await this.withAdoption(owner, input.kinds, merged) };
|
|
1314
|
+
}
|
|
1315
|
+
/** The boot guard: empty kind + a legacy table that still has rows = adoption pending. */
|
|
1316
|
+
async withAdoption(owner, declared, results) {
|
|
1317
|
+
const out = { ...results };
|
|
1318
|
+
for (const [kind, raw] of Object.entries(declared)) {
|
|
1319
|
+
const legacy = raw.adoptsFrom;
|
|
1320
|
+
const result = results[kind];
|
|
1321
|
+
if (legacy === void 0 || result === void 0) continue;
|
|
1322
|
+
if ((await (await this.fileOf(owner, kind)).records("adoptionState", {
|
|
1323
|
+
owner,
|
|
1324
|
+
kind
|
|
1325
|
+
})).adoptedAt !== null) continue;
|
|
1326
|
+
const legacyRows = await (await this.router.recordsFileFor("settings")).records("legacyRowCount", { table: legacy });
|
|
1327
|
+
if (legacyRows !== null && legacyRows > 0) out[kind] = {
|
|
1328
|
+
...result,
|
|
1329
|
+
adoptionPending: {
|
|
1330
|
+
legacyTable: legacy,
|
|
1331
|
+
legacyRows
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
return out;
|
|
1336
|
+
}
|
|
1337
|
+
async get(input) {
|
|
1338
|
+
const owner = recordsCallerOf(input);
|
|
1339
|
+
return (await this.fileOf(owner, input.kind)).records("get", {
|
|
1340
|
+
...input,
|
|
1341
|
+
owner
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
async getMany(input) {
|
|
1345
|
+
const owner = recordsCallerOf(input);
|
|
1346
|
+
return (await this.fileOf(owner, input.kind)).records("getMany", {
|
|
1347
|
+
...input,
|
|
1348
|
+
owner
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
async secretRefs(input) {
|
|
1352
|
+
const owner = recordsCallerOf(input);
|
|
1353
|
+
return (await this.fileOf(owner, input.kind)).records("secretRefs", {
|
|
1354
|
+
...input,
|
|
1355
|
+
owner
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
async put(input) {
|
|
1359
|
+
const owner = recordsCallerOf(input);
|
|
1360
|
+
return (await this.fileOf(owner, input.kind)).records("put", {
|
|
1361
|
+
...input,
|
|
1362
|
+
owner
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
async putMany(input) {
|
|
1366
|
+
const owner = recordsCallerOf(input);
|
|
1367
|
+
return (await this.fileOf(owner, input.kind)).records("putMany", {
|
|
1368
|
+
...input,
|
|
1369
|
+
owner
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
async patch(input) {
|
|
1373
|
+
const owner = recordsCallerOf(input);
|
|
1374
|
+
return (await this.fileOf(owner, input.kind)).records("patch", {
|
|
1375
|
+
...input,
|
|
1376
|
+
owner
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
async delete(input) {
|
|
1380
|
+
const owner = recordsCallerOf(input);
|
|
1381
|
+
return (await this.fileOf(owner, input.kind)).records("delete", {
|
|
1382
|
+
...input,
|
|
1383
|
+
owner
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
async deleteMany(input) {
|
|
1387
|
+
const owner = recordsCallerOf(input);
|
|
1388
|
+
return (await this.fileOf(owner, input.kind)).records("deleteMany", {
|
|
1389
|
+
...input,
|
|
1390
|
+
owner
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
async query(input) {
|
|
1394
|
+
const owner = recordsCallerOf(input);
|
|
1395
|
+
return (await this.fileOf(owner, input.kind)).records("query", {
|
|
1396
|
+
...input,
|
|
1397
|
+
owner
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
async count(input) {
|
|
1401
|
+
const owner = recordsCallerOf(input);
|
|
1402
|
+
return (await this.fileOf(owner, input.kind)).records("count", {
|
|
1403
|
+
...input,
|
|
1404
|
+
owner
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
async histogram(input) {
|
|
1408
|
+
const owner = recordsCallerOf(input);
|
|
1409
|
+
return (await this.fileOf(owner, input.kind)).records("histogram", {
|
|
1410
|
+
...input,
|
|
1411
|
+
owner
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
async aggregate(input) {
|
|
1415
|
+
const owner = recordsCallerOf(input);
|
|
1416
|
+
return (await this.fileOf(owner, input.kind)).records("aggregate", {
|
|
1417
|
+
...input,
|
|
1418
|
+
owner
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
async deleteWhere(input) {
|
|
1422
|
+
const owner = recordsCallerOf(input);
|
|
1423
|
+
return (await this.fileOf(owner, input.kind)).records("deleteWhere", {
|
|
1424
|
+
...input,
|
|
1425
|
+
owner
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
async allocateId(input) {
|
|
1429
|
+
const owner = recordsCallerOf(input);
|
|
1430
|
+
return (await this.fileOf(owner, input.kind)).records("allocateId", {
|
|
1431
|
+
...input,
|
|
1432
|
+
owner
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
/** The D865 hook body: every file that holds kinds of this owner. */
|
|
1436
|
+
async deleteDevice(input) {
|
|
1437
|
+
const owner = recordsCallerOf(input);
|
|
1438
|
+
const deleted = {};
|
|
1439
|
+
const secretRefs = [];
|
|
1440
|
+
const databases = new Set([...this.placement.entries()].filter(([key]) => key.startsWith(`${owner}\u0000`)).map(([, database]) => database));
|
|
1441
|
+
for (const database of databases) {
|
|
1442
|
+
const result = await (await this.router.recordsFileFor(database)).records("deleteDevice", {
|
|
1443
|
+
...input,
|
|
1444
|
+
owner
|
|
1445
|
+
});
|
|
1446
|
+
Object.assign(deleted, result.deleted);
|
|
1447
|
+
secretRefs.push(...result.secretRefs);
|
|
1448
|
+
}
|
|
1449
|
+
return {
|
|
1450
|
+
deleted,
|
|
1451
|
+
secretRefs
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
async listKinds(input) {
|
|
1455
|
+
const kinds = [];
|
|
1456
|
+
for (const file of this.router.openFiles()) {
|
|
1457
|
+
if (file.databaseId === "history") continue;
|
|
1458
|
+
kinds.push(...await file.records("listKinds", input));
|
|
1459
|
+
}
|
|
1460
|
+
return { kinds };
|
|
1461
|
+
}
|
|
1462
|
+
async readRecords(input) {
|
|
1463
|
+
this.logger.info("records: admin read", { meta: {
|
|
1464
|
+
owner: input.owner,
|
|
1465
|
+
kind: input.kind,
|
|
1466
|
+
limit: input.limit
|
|
1467
|
+
} });
|
|
1468
|
+
return (await this.fileOf(input.owner, input.kind)).records("query", input);
|
|
1469
|
+
}
|
|
1470
|
+
async adoptRecords(input) {
|
|
1471
|
+
const file = await this.fileOf(input.owner, input.kind);
|
|
1472
|
+
const result = await file.records("putMany", input);
|
|
1473
|
+
if (input.complete === true) await file.records("markAdopted", {
|
|
1474
|
+
owner: input.owner,
|
|
1475
|
+
kind: input.kind
|
|
1476
|
+
});
|
|
1477
|
+
this.logger.warn("records: ADOPTED rows as their declared owner", { meta: {
|
|
1478
|
+
owner: input.owner,
|
|
1479
|
+
kind: input.kind,
|
|
1480
|
+
count: result.count,
|
|
1481
|
+
complete: input.complete === true
|
|
1482
|
+
} });
|
|
1483
|
+
return { adopted: result.count };
|
|
1484
|
+
}
|
|
1485
|
+
/** Housekeeping: delete rows past `expires_at` in every file that hosts kinds. */
|
|
1486
|
+
async sweepExpired() {
|
|
1487
|
+
let deleted = 0;
|
|
1488
|
+
for (const file of this.router.openFiles()) {
|
|
1489
|
+
if (file.databaseId === "history") continue;
|
|
1490
|
+
deleted += (await file.records("sweepExpired", {})).deleted;
|
|
1491
|
+
}
|
|
1492
|
+
return deleted;
|
|
1493
|
+
}
|
|
1494
|
+
};
|
|
1495
|
+
//#endregion
|
|
1207
1496
|
//#region src/builtins/sqlite-storage/storage-admin-provider.ts
|
|
1208
1497
|
/**
|
|
1209
1498
|
* The `storage-admin` provider of the SQLite engine (D870): the operator's
|
|
@@ -1217,10 +1506,21 @@ var StorageAdminProvider = class {
|
|
|
1217
1506
|
backend;
|
|
1218
1507
|
logger;
|
|
1219
1508
|
installedOwners;
|
|
1220
|
-
|
|
1509
|
+
records;
|
|
1510
|
+
constructor(backend, logger, installedOwners, records) {
|
|
1221
1511
|
this.backend = backend;
|
|
1222
1512
|
this.logger = logger;
|
|
1223
1513
|
this.installedOwners = installedOwners;
|
|
1514
|
+
this.records = records;
|
|
1515
|
+
}
|
|
1516
|
+
listKinds(input) {
|
|
1517
|
+
return this.records.listKinds(input);
|
|
1518
|
+
}
|
|
1519
|
+
readRecords(input) {
|
|
1520
|
+
return this.records.readRecords(input);
|
|
1521
|
+
}
|
|
1522
|
+
adoptRecords(input) {
|
|
1523
|
+
return this.records.adoptRecords(input);
|
|
1224
1524
|
}
|
|
1225
1525
|
/** May this table be dropped AT ALL? Throws with the reason when not. */
|
|
1226
1526
|
async assertDroppable(collection) {
|
|
@@ -1413,6 +1713,8 @@ var DATABASE_FILE_NAMES = {
|
|
|
1413
1713
|
var SqliteSettingsAddon = class extends require_dist.BaseAddon {
|
|
1414
1714
|
settingsFile = null;
|
|
1415
1715
|
router = null;
|
|
1716
|
+
sweepTimer = null;
|
|
1717
|
+
sweepStart = null;
|
|
1416
1718
|
constructor() {
|
|
1417
1719
|
super({});
|
|
1418
1720
|
}
|
|
@@ -1469,12 +1771,19 @@ var SqliteSettingsAddon = class extends require_dist.BaseAddon {
|
|
|
1469
1771
|
this.router = router;
|
|
1470
1772
|
const vectorIndex = settings.getVectorIndex();
|
|
1471
1773
|
if (vectorIndex === null) throw new Error("vector-store: the settings file has no vector index");
|
|
1774
|
+
const records = new RecordsProvider(router, this.ctx.logger.child("Records"));
|
|
1775
|
+
await records.init();
|
|
1776
|
+
this.startRecordsSweep(records);
|
|
1472
1777
|
this.ctx.logger.info("Initialized successfully");
|
|
1473
1778
|
return [
|
|
1474
1779
|
{
|
|
1475
1780
|
capability: require_dist.dataStoreProviderCapability,
|
|
1476
1781
|
provider: router
|
|
1477
1782
|
},
|
|
1783
|
+
{
|
|
1784
|
+
capability: require_dist.recordsCapability,
|
|
1785
|
+
provider: records
|
|
1786
|
+
},
|
|
1478
1787
|
{
|
|
1479
1788
|
capability: require_dist.vectorStoreCapability,
|
|
1480
1789
|
provider: require_wal_maintenance.vectorProviderOf(vectorIndex)
|
|
@@ -1485,7 +1794,7 @@ var SqliteSettingsAddon = class extends require_dist.BaseAddon {
|
|
|
1485
1794
|
},
|
|
1486
1795
|
{
|
|
1487
1796
|
capability: require_dist.storageAdminCapability,
|
|
1488
|
-
provider: new StorageAdminProvider(settings.backend, this.ctx.logger.child("StorageAdmin"), async () => new Set((await this.ctx.api.addons.list.query()).map((addon) => addon.manifest.id)))
|
|
1797
|
+
provider: new StorageAdminProvider(settings.backend, this.ctx.logger.child("StorageAdmin"), async () => new Set((await this.ctx.api.addons.list.query()).map((addon) => addon.manifest.id)), records)
|
|
1489
1798
|
}
|
|
1490
1799
|
];
|
|
1491
1800
|
}
|
|
@@ -1502,7 +1811,31 @@ var SqliteSettingsAddon = class extends require_dist.BaseAddon {
|
|
|
1502
1811
|
}
|
|
1503
1812
|
await purgeRetiredCollections(retiredCollectionStoreOfFile(file), this.ctx.logger.child("RetiredCollections").withTags({ database: file.databaseId }));
|
|
1504
1813
|
}
|
|
1814
|
+
/**
|
|
1815
|
+
* The engine's TTL sweep (D881): every 10 minutes, off the boot path (the
|
|
1816
|
+
* first run a minute after boot), batched and yielding. A failed pass is
|
|
1817
|
+
* warned about and the next one retries; it never blocks anything.
|
|
1818
|
+
*/
|
|
1819
|
+
startRecordsSweep(records) {
|
|
1820
|
+
const run = () => {
|
|
1821
|
+
records.sweepExpired().then((deleted) => {
|
|
1822
|
+
if (deleted > 0) this.ctx.logger.info("records: expired rows swept", { meta: { deleted } });
|
|
1823
|
+
}).catch((err) => {
|
|
1824
|
+
this.ctx.logger.warn("records: expiry sweep failed", { meta: { error: require_dist.errMsg(err) } });
|
|
1825
|
+
});
|
|
1826
|
+
};
|
|
1827
|
+
this.sweepStart = setTimeout(() => {
|
|
1828
|
+
run();
|
|
1829
|
+
this.sweepTimer = setInterval(run, require_dist.RECORD_SWEEP_INTERVAL_MS);
|
|
1830
|
+
this.sweepTimer.unref();
|
|
1831
|
+
}, 6e4);
|
|
1832
|
+
this.sweepStart.unref();
|
|
1833
|
+
}
|
|
1505
1834
|
async onShutdown() {
|
|
1835
|
+
if (this.sweepStart !== null) clearTimeout(this.sweepStart);
|
|
1836
|
+
if (this.sweepTimer !== null) clearInterval(this.sweepTimer);
|
|
1837
|
+
this.sweepStart = null;
|
|
1838
|
+
this.sweepTimer = null;
|
|
1506
1839
|
const files = this.router?.openFiles() ?? [];
|
|
1507
1840
|
for (const file of files.toReversed()) try {
|
|
1508
1841
|
await file.stop();
|