@minnowdb/core 0.2.1 → 0.4.0
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/README.md +23 -32
- package/dist/block-format/block.d.ts +32 -13
- package/dist/block-format/block.js +179 -55
- package/dist/block-format/checksum.d.ts +2 -1
- package/dist/block-format/checksum.js +5 -2
- package/dist/block-format/codecs.d.ts +7 -2
- package/dist/block-format/codecs.js +53 -12
- package/dist/block-format/column.d.ts +3 -2
- package/dist/block-format/column.js +96 -30
- package/dist/block-format/index.d.ts +2 -2
- package/dist/block-format/index.js +2 -2
- package/dist/block-format/physical.d.ts +8 -2
- package/dist/block-format/physical.js +14 -6
- package/dist/block-format/types.d.ts +7 -3
- package/dist/block-format/types.js +0 -1
- package/dist/block-format/unicode.d.ts +11 -0
- package/dist/block-format/unicode.js +46 -0
- package/dist/date-value.d.ts +15 -0
- package/dist/date-value.js +64 -0
- package/dist/engine/artifact-cache.d.ts +2 -1
- package/dist/engine/artifact-cache.js +5 -1
- package/dist/engine/batch.d.ts +11 -3
- package/dist/engine/batch.js +17 -7
- package/dist/engine/buffered-writer.d.ts +2 -1
- package/dist/engine/buffered-writer.js +34 -9
- package/dist/engine/cache-limits.d.ts +25 -0
- package/dist/engine/cache-limits.js +25 -0
- package/dist/engine/catalog.d.ts +24 -5
- package/dist/engine/catalog.js +34 -7
- package/dist/engine/client.d.ts +29 -7
- package/dist/engine/client.js +216 -40
- package/dist/engine/database.d.ts +224 -39
- package/dist/engine/database.js +7475 -1539
- package/dist/engine/defaults.d.ts +4 -8
- package/dist/engine/defaults.js +46 -22
- package/dist/engine/errors.d.ts +19 -1
- package/dist/engine/errors.js +32 -2
- package/dist/engine/fts.d.ts +0 -6
- package/dist/engine/fts.js +41 -14
- package/dist/engine/group-index.d.ts +0 -1
- package/dist/engine/group-index.js +6 -11
- package/dist/engine/index.d.ts +16 -10
- package/dist/engine/index.js +12 -9
- package/dist/engine/join-index.d.ts +0 -1
- package/dist/engine/join-index.js +2 -2
- package/dist/engine/keyed-live.d.ts +57 -0
- package/dist/engine/keyed-live.js +226 -0
- package/dist/engine/live-api.d.ts +4 -0
- package/dist/engine/live-api.js +4 -0
- package/dist/engine/live.d.ts +43 -26
- package/dist/engine/live.js +504 -126
- package/dist/engine/memory.d.ts +2 -1
- package/dist/engine/memory.js +3 -2
- package/dist/engine/optimizer.d.ts +0 -1
- package/dist/engine/optimizer.js +262 -27
- package/dist/engine/query-api.d.ts +3 -0
- package/dist/engine/query-api.js +3 -0
- package/dist/engine/query-cache.d.ts +1 -2
- package/dist/engine/query-cache.js +7 -5
- package/dist/engine/query.d.ts +134 -29
- package/dist/engine/query.js +1668 -372
- package/dist/engine/result-wire.d.ts +0 -1
- package/dist/engine/result-wire.js +2 -2
- package/dist/engine/schema-wire.d.ts +6 -3
- package/dist/engine/schema-wire.js +40 -34
- package/dist/engine/schema.d.ts +156 -80
- package/dist/engine/schema.js +570 -108
- package/dist/engine/sort-keys.d.ts +4 -4
- package/dist/engine/sort-keys.js +44 -29
- package/dist/engine/sql-domains.d.ts +31 -0
- package/dist/engine/sql-domains.js +585 -0
- package/dist/engine/sql-driver.d.ts +19 -0
- package/dist/engine/sql-driver.js +1 -0
- package/dist/engine/sql-json.d.ts +7 -9
- package/dist/engine/sql-json.js +75 -15
- package/dist/engine/sql-semantics.d.ts +8 -3
- package/dist/engine/sql-semantics.js +458 -30
- package/dist/engine/typed-live.d.ts +67 -0
- package/dist/engine/typed-live.js +349 -0
- package/dist/engine/vector.d.ts +12 -2
- package/dist/engine/vector.js +635 -119
- package/dist/engine/worker-host.d.ts +9 -2
- package/dist/engine/worker-host.js +620 -152
- package/dist/engine/worker.d.ts +0 -1
- package/dist/engine/worker.js +3 -3
- package/dist/engine/write-block-planner.d.ts +18 -0
- package/dist/engine/write-block-planner.js +112 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/plan/index.d.ts +3 -4
- package/dist/plan/index.js +3 -4
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/storage/indexeddb.d.ts +99 -51
- package/dist/storage/indexeddb.js +13448 -2660
- package/dist/storage/memory.d.ts +64 -57
- package/dist/storage/memory.js +1042 -128
- package/dist/storage/opfs/files.d.ts +18 -7
- package/dist/storage/opfs/files.js +115 -28
- package/dist/storage/opfs/index.d.ts +1 -1
- package/dist/storage/opfs/index.js +1 -1
- package/dist/storage/opfs/leader.d.ts +409 -75
- package/dist/storage/opfs/leader.js +4621 -650
- package/dist/storage/opfs/rpc.d.ts +15 -3
- package/dist/storage/opfs/rpc.js +224 -2
- package/dist/storage/opfs/snapshot-ledger.d.ts +40 -0
- package/dist/storage/opfs/snapshot-ledger.js +281 -0
- package/dist/storage/opfs/store.d.ts +33 -99
- package/dist/storage/opfs/store.js +453 -364
- package/dist/storage/persistence.d.ts +37 -0
- package/dist/storage/persistence.js +78 -0
- package/dist/storage/snapshot-stream.d.ts +24 -0
- package/dist/storage/snapshot-stream.js +897 -0
- package/dist/storage/snapshot.d.ts +9 -85
- package/dist/storage/snapshot.js +33 -265
- package/dist/storage/toolkit/extents.d.ts +41 -7
- package/dist/storage/toolkit/extents.js +402 -39
- package/dist/storage/toolkit/index.d.ts +4 -5
- package/dist/storage/toolkit/index.js +28 -4
- package/dist/storage/toolkit/record-core.d.ts +182 -55
- package/dist/storage/toolkit/record-core.js +6158 -1331
- package/dist/storage/toolkit/sync-file.d.ts +10 -1
- package/dist/storage/toolkit/sync-file.js +50 -2
- package/dist/storage/toolkit/wal.d.ts +23 -5
- package/dist/storage/toolkit/wal.js +89 -27
- package/dist/storage/toolkit/wire.d.ts +15 -2
- package/dist/storage/toolkit/wire.js +199 -10
- package/dist/storage/types.d.ts +1439 -204
- package/dist/storage/types.js +1745 -141
- package/dist/testing/block-store-conformance.d.ts +0 -1
- package/dist/testing/block-store-conformance.js +1009 -119
- package/dist/testing/index.d.ts +46 -26
- package/dist/testing/index.js +112 -57
- package/dist/testing/opfs-shim.d.ts +13 -3
- package/dist/testing/opfs-shim.js +40 -6
- package/dist/testing/simulator.d.ts +97 -0
- package/dist/testing/simulator.js +591 -0
- package/dist/testing/sqllogictest.d.ts +89 -0
- package/dist/testing/sqllogictest.js +434 -0
- package/dist/transactions/index.d.ts +92 -16
- package/dist/transactions/index.js +1074 -236
- package/dist/worker-protocol/index.d.ts +3 -2
- package/dist/worker-protocol/index.js +2 -5
- package/package.json +53 -3
- package/postgres-feature-profile.json +223 -0
- package/sql-feature-matrix.json +172 -252
- package/dist/block-format/block.d.ts.map +0 -1
- package/dist/block-format/block.js.map +0 -1
- package/dist/block-format/checksum.d.ts.map +0 -1
- package/dist/block-format/checksum.js.map +0 -1
- package/dist/block-format/codecs.d.ts.map +0 -1
- package/dist/block-format/codecs.js.map +0 -1
- package/dist/block-format/column.d.ts.map +0 -1
- package/dist/block-format/column.js.map +0 -1
- package/dist/block-format/index.d.ts.map +0 -1
- package/dist/block-format/index.js.map +0 -1
- package/dist/block-format/physical.d.ts.map +0 -1
- package/dist/block-format/physical.js.map +0 -1
- package/dist/block-format/types.d.ts.map +0 -1
- package/dist/block-format/types.js.map +0 -1
- package/dist/engine/artifact-cache.d.ts.map +0 -1
- package/dist/engine/artifact-cache.js.map +0 -1
- package/dist/engine/batch.d.ts.map +0 -1
- package/dist/engine/batch.js.map +0 -1
- package/dist/engine/buffered-writer.d.ts.map +0 -1
- package/dist/engine/buffered-writer.js.map +0 -1
- package/dist/engine/catalog.d.ts.map +0 -1
- package/dist/engine/catalog.js.map +0 -1
- package/dist/engine/client.d.ts.map +0 -1
- package/dist/engine/client.js.map +0 -1
- package/dist/engine/coordinator.d.ts +0 -17
- package/dist/engine/coordinator.d.ts.map +0 -1
- package/dist/engine/coordinator.js +0 -60
- package/dist/engine/coordinator.js.map +0 -1
- package/dist/engine/database.d.ts.map +0 -1
- package/dist/engine/database.js.map +0 -1
- package/dist/engine/defaults.d.ts.map +0 -1
- package/dist/engine/defaults.js.map +0 -1
- package/dist/engine/errors.d.ts.map +0 -1
- package/dist/engine/errors.js.map +0 -1
- package/dist/engine/fts.d.ts.map +0 -1
- package/dist/engine/fts.js.map +0 -1
- package/dist/engine/group-index.d.ts.map +0 -1
- package/dist/engine/group-index.js.map +0 -1
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js.map +0 -1
- package/dist/engine/join-index.d.ts.map +0 -1
- package/dist/engine/join-index.js.map +0 -1
- package/dist/engine/live.d.ts.map +0 -1
- package/dist/engine/live.js.map +0 -1
- package/dist/engine/memory.d.ts.map +0 -1
- package/dist/engine/memory.js.map +0 -1
- package/dist/engine/optimizer.d.ts.map +0 -1
- package/dist/engine/optimizer.js.map +0 -1
- package/dist/engine/query-cache.d.ts.map +0 -1
- package/dist/engine/query-cache.js.map +0 -1
- package/dist/engine/query.d.ts.map +0 -1
- package/dist/engine/query.js.map +0 -1
- package/dist/engine/result-wire.d.ts.map +0 -1
- package/dist/engine/result-wire.js.map +0 -1
- package/dist/engine/schema-wire.d.ts.map +0 -1
- package/dist/engine/schema-wire.js.map +0 -1
- package/dist/engine/schema.d.ts.map +0 -1
- package/dist/engine/schema.js.map +0 -1
- package/dist/engine/sort-keys.d.ts.map +0 -1
- package/dist/engine/sort-keys.js.map +0 -1
- package/dist/engine/sql-json.d.ts.map +0 -1
- package/dist/engine/sql-json.js.map +0 -1
- package/dist/engine/sql-semantics.d.ts.map +0 -1
- package/dist/engine/sql-semantics.js.map +0 -1
- package/dist/engine/vector.d.ts.map +0 -1
- package/dist/engine/vector.js.map +0 -1
- package/dist/engine/worker-host.d.ts.map +0 -1
- package/dist/engine/worker-host.js.map +0 -1
- package/dist/engine/worker.d.ts.map +0 -1
- package/dist/engine/worker.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/plan/index.d.ts.map +0 -1
- package/dist/plan/index.js.map +0 -1
- package/dist/storage/fixture-shape.d.ts +0 -42
- package/dist/storage/fixture-shape.d.ts.map +0 -1
- package/dist/storage/fixture-shape.js +0 -146
- package/dist/storage/fixture-shape.js.map +0 -1
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/indexeddb.d.ts.map +0 -1
- package/dist/storage/indexeddb.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/storage/opfs/files.d.ts.map +0 -1
- package/dist/storage/opfs/files.js.map +0 -1
- package/dist/storage/opfs/index.d.ts.map +0 -1
- package/dist/storage/opfs/index.js.map +0 -1
- package/dist/storage/opfs/leader.d.ts.map +0 -1
- package/dist/storage/opfs/leader.js.map +0 -1
- package/dist/storage/opfs/rpc.d.ts.map +0 -1
- package/dist/storage/opfs/rpc.js.map +0 -1
- package/dist/storage/opfs/store.d.ts.map +0 -1
- package/dist/storage/opfs/store.js.map +0 -1
- package/dist/storage/snapshot.d.ts.map +0 -1
- package/dist/storage/snapshot.js.map +0 -1
- package/dist/storage/toolkit/extents.d.ts.map +0 -1
- package/dist/storage/toolkit/extents.js.map +0 -1
- package/dist/storage/toolkit/index.d.ts.map +0 -1
- package/dist/storage/toolkit/index.js.map +0 -1
- package/dist/storage/toolkit/record-core.d.ts.map +0 -1
- package/dist/storage/toolkit/record-core.js.map +0 -1
- package/dist/storage/toolkit/sync-file.d.ts.map +0 -1
- package/dist/storage/toolkit/sync-file.js.map +0 -1
- package/dist/storage/toolkit/wal.d.ts.map +0 -1
- package/dist/storage/toolkit/wal.js.map +0 -1
- package/dist/storage/toolkit/wire.d.ts.map +0 -1
- package/dist/storage/toolkit/wire.js.map +0 -1
- package/dist/storage/types.d.ts.map +0 -1
- package/dist/storage/types.js.map +0 -1
- package/dist/testing/block-store-conformance.d.ts.map +0 -1
- package/dist/testing/block-store-conformance.js.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/opfs-shim.d.ts.map +0 -1
- package/dist/testing/opfs-shim.js.map +0 -1
- package/dist/testing/seeds.d.ts +0 -11
- package/dist/testing/seeds.d.ts.map +0 -1
- package/dist/testing/seeds.js +0 -50
- package/dist/testing/seeds.js.map +0 -1
- package/dist/transactions/index.d.ts.map +0 -1
- package/dist/transactions/index.js.map +0 -1
- package/dist/worker-protocol/index.d.ts.map +0 -1
- package/dist/worker-protocol/index.js.map +0 -1
package/dist/storage/types.d.ts
CHANGED
|
@@ -1,60 +1,138 @@
|
|
|
1
|
-
import type { DatabaseSnapshot, SnapshotLoadProgress } from "./snapshot.js";
|
|
2
1
|
export declare const storeNames: readonly ["catalog", "manifests", "segments", "blocks", "transactions", "leases", "statistics", "temp", "gc"];
|
|
3
|
-
|
|
2
|
+
export declare const MAX_MANIFEST_CHANGED_TABLE_IDS = 1024;
|
|
3
|
+
export declare function canonicalManifestChangedTableIds(ids: readonly string[]): string[];
|
|
4
|
+
export declare function validateCanonicalManifestChangedTableIds(ids: readonly string[]): string[];
|
|
5
|
+
/**
|
|
6
|
+
* The bounded manifest record every commit publishes. Block membership is paged separately;
|
|
7
|
+
* reading this record must never materialize a database-sized ID array.
|
|
8
|
+
*/
|
|
4
9
|
export interface ManifestSummary {
|
|
5
10
|
version: number;
|
|
6
11
|
previousVersion: number | null;
|
|
7
12
|
createdAt: string;
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
changedTableIds
|
|
13
|
+
/** Exact live payload membership cardinality at this version. */
|
|
14
|
+
liveBlockCount: number;
|
|
15
|
+
/** Exact sum of stored payload bytes in the live membership at this version. */
|
|
16
|
+
liveBlockBytes: number;
|
|
17
|
+
/** Table IDs whose logical content changed; empty means compaction or another logical no-op. */
|
|
18
|
+
changedTableIds: string[];
|
|
14
19
|
/** A pruned descriptor remains readable for commit reconciliation but cannot be pinned. */
|
|
15
20
|
prunedAt?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Commit-local maintenance hints, not persisted in manifest history. A ready full-text
|
|
23
|
+
* column reports its durable delta-tail length so the committing engine can rebuild before
|
|
24
|
+
* metadata grows with every later commit, even when nobody searches the column again.
|
|
25
|
+
*/
|
|
26
|
+
ftsDeltaCounts?: Array<{
|
|
27
|
+
tableId: string;
|
|
28
|
+
columnId: string;
|
|
29
|
+
count: number;
|
|
30
|
+
}>;
|
|
16
31
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
32
|
+
/** Public/cold manifest inspection is bounded metadata only. */
|
|
33
|
+
export type Manifest = ManifestSummary;
|
|
20
34
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
35
|
+
* One payload's bounded manifest-membership interval. The block is visible at version `v` iff
|
|
36
|
+
* `addedVersion <= v && (removedVersion === null || v < removedVersion)`. `byteLength` and the
|
|
37
|
+
* payload bytes are immutable while this record exists; `removedVersion`, when present, is
|
|
38
|
+
* strictly greater than `addedVersion`.
|
|
39
|
+
*
|
|
40
|
+
* A retired ID cannot be added again while this provenance record or a transaction/job that
|
|
41
|
+
* names it is retained. Once every readable/pinned version in the interval and every recovery
|
|
42
|
+
* root is gone, garbage collection removes payload and provenance together; no immortal ID
|
|
43
|
+
* tombstone is required.
|
|
27
44
|
*/
|
|
28
|
-
export interface
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
export interface ManifestBlockRecord {
|
|
46
|
+
readonly blockId: string;
|
|
47
|
+
readonly byteLength: number;
|
|
48
|
+
/** CRC-32 of the exact stored payload, computed once before the first durable write. */
|
|
49
|
+
readonly checksum: number;
|
|
50
|
+
readonly addedVersion: number;
|
|
51
|
+
readonly removedVersion: number | null;
|
|
52
|
+
}
|
|
53
|
+
export interface ListManifestBlockPageInput {
|
|
54
|
+
readonly version: number;
|
|
55
|
+
readonly afterBlockId: string | null;
|
|
56
|
+
readonly limit: number;
|
|
57
|
+
}
|
|
58
|
+
export interface ListRetiredManifestBlockPageInput {
|
|
59
|
+
/** Includes records retired at or before this published version. */
|
|
60
|
+
readonly removedThroughVersion: number;
|
|
61
|
+
readonly afterBlockId: string | null;
|
|
62
|
+
readonly limit: number;
|
|
63
|
+
}
|
|
64
|
+
export interface ManifestBlockPage {
|
|
65
|
+
readonly records: ReadonlyArray<Pick<ManifestBlockRecord, "blockId" | "byteLength" | "checksum">>;
|
|
66
|
+
readonly nextCursor: string | null;
|
|
67
|
+
}
|
|
68
|
+
/** Input for adapter-internal manifest construction; not a public store mutation. */
|
|
69
|
+
export interface CreateManifestInput {
|
|
70
|
+
changedTableIds: readonly string[];
|
|
41
71
|
expectedVersion: number | null;
|
|
42
|
-
|
|
72
|
+
liveBlockCount: number;
|
|
73
|
+
liveBlockBytes: number;
|
|
43
74
|
createdAt?: string;
|
|
44
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* The stored manifest is the same bounded summary returned publicly. Exact block membership is
|
|
78
|
+
* represented once by `ManifestBlockRecord` intervals; checkpoint/delta arrays are deliberately
|
|
79
|
+
* absent from the v1 layout.
|
|
80
|
+
*/
|
|
81
|
+
export type StoredManifestRecord = ManifestSummary;
|
|
82
|
+
/**
|
|
83
|
+
* One atomic user-table drop. The store compares both catalog and manifest revisions, derives
|
|
84
|
+
* every block that the table's segments still contribute to that exact manifest, publishes one
|
|
85
|
+
* successor without those blocks, and removes all table-owned metadata in the same durable
|
|
86
|
+
* step. Stored block payloads remain for lease-aware collection.
|
|
87
|
+
*/
|
|
88
|
+
export interface DropTableInput {
|
|
89
|
+
tableId: string;
|
|
90
|
+
expectedTableRevision: number;
|
|
91
|
+
expectedManifestVersion: number | null;
|
|
92
|
+
/** Catalog epoch of the complete dependency proof used to authorize this drop. */
|
|
93
|
+
expectedCatalogEpoch: number;
|
|
94
|
+
committedAt: string;
|
|
95
|
+
}
|
|
96
|
+
/** One atomic column retirement; see `CatalogStore.dropTableColumn`. */
|
|
97
|
+
export interface DropTableColumnInput {
|
|
98
|
+
tableId: string;
|
|
99
|
+
columnId: string;
|
|
100
|
+
expectedTableRevision: number;
|
|
101
|
+
expectedManifestVersion: number | null;
|
|
102
|
+
/** Catalog epoch of the complete dependency proof used to authorize this drop. */
|
|
103
|
+
expectedCatalogEpoch: number;
|
|
104
|
+
committedAt: string;
|
|
105
|
+
}
|
|
45
106
|
export declare const simpleDataTypes: readonly ["boolean", "number", "string", "datetime"];
|
|
46
107
|
export type SimpleDataType = (typeof simpleDataTypes)[number];
|
|
108
|
+
/** PostgreSQL logical domains layered over the four stable physical block encodings. */
|
|
109
|
+
export type SqlDomain = {
|
|
110
|
+
kind: "numeric";
|
|
111
|
+
precision?: number;
|
|
112
|
+
scale?: number;
|
|
113
|
+
} | {
|
|
114
|
+
kind: "json" | "jsonb" | "uuid" | "time" | "interval";
|
|
115
|
+
} | {
|
|
116
|
+
kind: "array";
|
|
117
|
+
element: string;
|
|
118
|
+
} | {
|
|
119
|
+
kind: "enum";
|
|
120
|
+
name: string;
|
|
121
|
+
values: string[];
|
|
122
|
+
};
|
|
123
|
+
/** Validates the logical metadata shared by SQL DDL, the schema DSL, and restored catalogs. */
|
|
124
|
+
export declare function validateSqlDomain(domain: SqlDomain, context: string): SqlDomain;
|
|
47
125
|
/**
|
|
48
|
-
* Declarative write-time default.
|
|
49
|
-
* worker
|
|
50
|
-
*
|
|
51
|
-
* and the typed facade fills them before a batch reaches the engine.
|
|
126
|
+
* Declarative SQL write-time default. The spec is structured-clone-safe because it crosses the
|
|
127
|
+
* worker boundary and persists in the catalog. Expressions are parsed and type-checked by the
|
|
128
|
+
* engine before the catalog is changed, then evaluated once for every omitted insert slot.
|
|
52
129
|
*/
|
|
53
130
|
export type ColumnDefault = {
|
|
54
|
-
kind: "now";
|
|
55
|
-
} | {
|
|
56
131
|
kind: "literal";
|
|
57
|
-
value: boolean | number | string;
|
|
132
|
+
value: boolean | number | string | Date;
|
|
133
|
+
} | {
|
|
134
|
+
kind: "expression";
|
|
135
|
+
sql: string;
|
|
58
136
|
} | {
|
|
59
137
|
kind: "autoincrement";
|
|
60
138
|
};
|
|
@@ -62,8 +140,17 @@ export interface TableColumnRecord {
|
|
|
62
140
|
id: string;
|
|
63
141
|
name: string;
|
|
64
142
|
type: SimpleDataType;
|
|
143
|
+
/**
|
|
144
|
+
* SQL INTEGER/SMALLINT/BIGINT columns use the number physical type, but only accept exact
|
|
145
|
+
* JavaScript safe integers. Absent for the public `number` type and SQL floating-point types.
|
|
146
|
+
* Keeping the domain in catalog metadata prevents a declared integer from silently rounding
|
|
147
|
+
* before it reaches storage while preserving the released Float64 block encoding.
|
|
148
|
+
*/
|
|
149
|
+
integer?: true;
|
|
150
|
+
/** SQL-level semantics for a value physically encoded in this column's primitive type. */
|
|
151
|
+
sqlDomain?: SqlDomain;
|
|
65
152
|
nullable: boolean;
|
|
66
|
-
/** Fills
|
|
153
|
+
/** Fills omitted or SQL `DEFAULT` slots at insert time; explicit NULL is never replaced. */
|
|
67
154
|
defaultValue?: ColumnDefault;
|
|
68
155
|
/**
|
|
69
156
|
* What rows written before this column existed read as, instead of NULL.
|
|
@@ -85,22 +172,40 @@ export interface TableColumnRecord {
|
|
|
85
172
|
* dropping it) is catalog-only while narrowing it is rejected by migration planning.
|
|
86
173
|
*/
|
|
87
174
|
enumValues?: string[];
|
|
88
|
-
|
|
175
|
+
/** Engine-generated row-addressing column; stored and indexed, never exposed as SQL schema. */
|
|
176
|
+
hidden?: true;
|
|
177
|
+
}
|
|
178
|
+
export declare const MAX_TABLE_COLUMNS = 1024;
|
|
179
|
+
export declare const MAX_ENUM_VALUES = 4096;
|
|
180
|
+
export declare const MAX_SECONDARY_INDEXES = 1024;
|
|
181
|
+
export declare const MAX_TABLE_TRIGGERS = 256;
|
|
182
|
+
export declare const MAX_TRIGGER_STATEMENTS = 256;
|
|
183
|
+
export declare const MAX_TABLE_CONSTRAINTS = 1024;
|
|
184
|
+
export declare const MAX_TABLE_RECORD_CHARACTERS = 1048576;
|
|
185
|
+
export declare const MAX_TABLE_RECORD_ENTRIES = 65536;
|
|
89
186
|
/**
|
|
90
187
|
* The single authority on which enum declarations are legal, shared by the schema DSL's
|
|
91
188
|
* `column.enum()` and the engine's `createTable`: at least one value, every value a non-empty
|
|
92
189
|
* string, no duplicates. Returns a defensive copy.
|
|
93
190
|
*/
|
|
94
191
|
export declare function validateEnumValues(values: readonly string[], context: string): string[];
|
|
192
|
+
/**
|
|
193
|
+
* Validates the catalog invariants owned by a table's column list. Storage adapters call this
|
|
194
|
+
* for ordinary catalog writes and before restoring snapshots or checkpoints, so malformed
|
|
195
|
+
* metadata cannot enter through a less common persistence path.
|
|
196
|
+
*/
|
|
197
|
+
export declare function validateTableColumns(columns: readonly TableColumnRecord[]): void;
|
|
95
198
|
/**
|
|
96
199
|
* The single authority on which default declarations are legal, shared by the schema DSL's
|
|
97
200
|
* `table()` and the engine's `createTable` so the two entry points (and the wire path between
|
|
98
|
-
* them) can never drift
|
|
99
|
-
*
|
|
201
|
+
* them) can never drift. Storage owns structural and literal validation; the engine additionally
|
|
202
|
+
* parses and type-checks SQL expressions before catalog mutation.
|
|
100
203
|
*/
|
|
101
204
|
export declare function validateColumnDefault(column: {
|
|
102
205
|
name: string;
|
|
103
206
|
type: SimpleDataType;
|
|
207
|
+
integer?: true;
|
|
208
|
+
sqlDomain?: SqlDomain;
|
|
104
209
|
nullable: boolean;
|
|
105
210
|
isUniqueKey: boolean;
|
|
106
211
|
enumValues?: readonly string[];
|
|
@@ -118,26 +223,67 @@ export interface FtsColumnIndexRecord {
|
|
|
118
223
|
/** Manifest version the base build covers; commit deltas above it merge at read time. */
|
|
119
224
|
buildFromVersion: number;
|
|
120
225
|
}
|
|
226
|
+
export type SecondaryIndexState = "building" | "ready" | "invalid";
|
|
227
|
+
export type SecondaryIndexDirection = "asc" | "desc";
|
|
228
|
+
/**
|
|
229
|
+
* One durable secondary index. The physical postings live in the same bounded, immutable
|
|
230
|
+
* base-plus-delta substrate as full-text postings, under `storageColumnId`; keeping the storage
|
|
231
|
+
* identity separate from the catalog column IDs lets one postings generation represent a
|
|
232
|
+
* composite key.
|
|
233
|
+
*
|
|
234
|
+
* Postings are a pruning accelerator, never truth. A keyed table stores a deterministic hash of
|
|
235
|
+
* its immutable unique key (collisions only add false positives); an append-only keyless table
|
|
236
|
+
* stores its hidden row ID. Every scan re-evaluates the SQL predicate against the row.
|
|
237
|
+
*/
|
|
238
|
+
export interface SecondaryIndexRecord {
|
|
239
|
+
name: string;
|
|
240
|
+
/** First indexed column, repeated for constant-time scalar catalog access. */
|
|
241
|
+
columnId: string;
|
|
242
|
+
/** Ordered key columns. */
|
|
243
|
+
columnIds: string[];
|
|
244
|
+
/** Declared key direction per column. */
|
|
245
|
+
directions: SecondaryIndexDirection[];
|
|
246
|
+
/** SQL UNIQUE: enforced through an atomic, separately namespaced membership set. */
|
|
247
|
+
unique?: true;
|
|
248
|
+
/** The membership set has been seeded and must be enforced, independent of postings state. */
|
|
249
|
+
uniqueEnforced?: true;
|
|
250
|
+
/** Prefix-free composite encoding used by every v1 secondary index. */
|
|
251
|
+
termEncoding: "tuple-v1";
|
|
252
|
+
storage: "postings-v1";
|
|
253
|
+
storageColumnId: string;
|
|
254
|
+
locator: "row-id" | "key-hash-v1";
|
|
255
|
+
state: SecondaryIndexState;
|
|
256
|
+
/** Identifies the builder allowed to publish a `building` record; omitted otherwise. */
|
|
257
|
+
buildId?: string;
|
|
258
|
+
/** Manifest version the base build covers; commit deltas above it merge at read time. */
|
|
259
|
+
buildFromVersion: number;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Whether a secondary-index replacement changes the contract a staged writer must honor.
|
|
263
|
+
* Physical posting-build state is deliberately excluded: postings are only a reverified pruning
|
|
264
|
+
* accelerator. Index identity, key shape, and UNIQUE enforcement are structural.
|
|
265
|
+
*/
|
|
266
|
+
export declare function secondaryIndexWriteContractChanged(previous: Readonly<Record<string, SecondaryIndexRecord>> | null | undefined, next: Readonly<Record<string, SecondaryIndexRecord>> | null | undefined): boolean;
|
|
121
267
|
export interface TableRecord {
|
|
122
268
|
id: string;
|
|
123
269
|
name: string;
|
|
124
270
|
columns: TableColumnRecord[];
|
|
125
271
|
uniqueKeyColumnId?: string;
|
|
272
|
+
/** Declared PRIMARY KEY columns. More than one uses the hidden scalar row-addressing key. */
|
|
273
|
+
primaryKeyColumnIds?: string[];
|
|
126
274
|
uniqueKeyLookupReady?: boolean;
|
|
127
275
|
/** Full-text index state per column ID. Writers that see this emit commit deltas. */
|
|
128
276
|
ftsColumns?: Record<string, FtsColumnIndexRecord>;
|
|
129
|
-
/**
|
|
277
|
+
/** Durable secondary indexes keyed by stable index ID. */
|
|
278
|
+
secondaryIndexes?: Record<string, SecondaryIndexRecord>;
|
|
279
|
+
/** BEFORE/AFTER triggers on this table, fired by the committing writer in its transaction. */
|
|
130
280
|
triggers?: TriggerRecord[];
|
|
131
|
-
/**
|
|
132
|
-
* Single-column FOREIGN KEY constraints (E141-04). The referenced column is the parent's
|
|
133
|
-
* unique key, which is what the engine can probe for existence and what its keyed write paths
|
|
134
|
-
* address rows by; a parent key never changes, so only ON DELETE has an action to take.
|
|
135
|
-
*/
|
|
281
|
+
/** FOREIGN KEY constraints. Column tuples are always explicit, including scalar keys. */
|
|
136
282
|
foreignKeys?: Array<{
|
|
137
283
|
name: string;
|
|
138
|
-
|
|
284
|
+
columns: string[];
|
|
139
285
|
parentTable: string;
|
|
140
|
-
|
|
286
|
+
parentColumns: string[];
|
|
141
287
|
onDelete: "restrict" | "cascade" | "set null";
|
|
142
288
|
}>;
|
|
143
289
|
/**
|
|
@@ -151,12 +297,10 @@ export interface TableRecord {
|
|
|
151
297
|
}>;
|
|
152
298
|
/**
|
|
153
299
|
* True when `migrate()` created this table from a schema declaration, which makes the schema
|
|
154
|
-
* authoritative over it: dropping the declaration may drop the table.
|
|
155
|
-
*
|
|
156
|
-
* migration removes it — the same rule views follow, and it matters more here because a
|
|
157
|
-
* table holds rows.
|
|
300
|
+
* authoritative over it: dropping the declaration may drop the table. `CREATE TABLE` records
|
|
301
|
+
* false explicitly.
|
|
158
302
|
*/
|
|
159
|
-
managed
|
|
303
|
+
managed: boolean;
|
|
160
304
|
/**
|
|
161
305
|
* A view rather than a table: the query text it stands for, and no segments of its own. The
|
|
162
306
|
* `columns` are the query's inferred output schema, so a view answers the same catalog
|
|
@@ -165,23 +309,53 @@ export interface TableRecord {
|
|
|
165
309
|
view?: {
|
|
166
310
|
sql: string;
|
|
167
311
|
/**
|
|
168
|
-
* True when `migrate()` created this view from a schema declaration
|
|
169
|
-
*
|
|
170
|
-
* `CREATE VIEW`, or one written before this field existed, is absent-or-false and no
|
|
171
|
-
* migration will remove it.
|
|
312
|
+
* True when `migrate()` created this view from a schema declaration. `CREATE VIEW` records
|
|
313
|
+
* false explicitly.
|
|
172
314
|
*/
|
|
173
|
-
managed
|
|
315
|
+
managed: boolean;
|
|
316
|
+
};
|
|
317
|
+
/** Internal catalog object backing CREATE TYPE ... AS ENUM; never exposed as a table. */
|
|
318
|
+
enumType?: {
|
|
319
|
+
name: string;
|
|
320
|
+
values: string[];
|
|
321
|
+
};
|
|
322
|
+
/** Internal catalog object backing a durable PostgreSQL sequence. */
|
|
323
|
+
sequence?: {
|
|
324
|
+
name: string;
|
|
325
|
+
start: number;
|
|
326
|
+
columnId: string;
|
|
174
327
|
};
|
|
175
328
|
createdAt: string;
|
|
176
|
-
/** Compare-and-swap revision for catalog evolution
|
|
177
|
-
revision
|
|
329
|
+
/** Compare-and-swap revision for catalog evolution. */
|
|
330
|
+
revision: number;
|
|
178
331
|
}
|
|
332
|
+
/** Exact UTF-8 bytes used when the canonical record-wire JSON codec persists a table record. */
|
|
333
|
+
export declare function catalogRecordRetainedBytes(record: TableRecord): number;
|
|
334
|
+
export declare function manifestRecordRetainedBytes(record: Manifest): number;
|
|
179
335
|
/**
|
|
180
|
-
*
|
|
336
|
+
* Admission charge for one manifest summary, including the exact canonical tombstone bytes that
|
|
337
|
+
* later reclamation may add. Reserving them up front prevents quota deadlock at the byte ceiling.
|
|
338
|
+
*/
|
|
339
|
+
export declare function manifestRecordRetainedReservationBytes(record: Manifest): number;
|
|
340
|
+
export declare function segmentRecordRetainedBytes(record: SegmentRecord): number;
|
|
341
|
+
/** Hard catalog cardinality/text bounds shared by engine, adapters, checkpoints, and snapshots. */
|
|
342
|
+
export declare function validateTableRecordBounds(record: TableRecord): void;
|
|
343
|
+
/** Validates the durable identities and ownership rules of one table's secondary indexes. */
|
|
344
|
+
export declare function validateSecondaryIndexes(record: TableRecord): void;
|
|
345
|
+
/** Ordered catalog column IDs for one canonical secondary-index record. */
|
|
346
|
+
export declare function secondaryIndexColumnIds(index: SecondaryIndexRecord): readonly string[];
|
|
347
|
+
/** Declared directions for one canonical secondary-index record. */
|
|
348
|
+
export declare function secondaryIndexDirections(index: SecondaryIndexRecord): readonly SecondaryIndexDirection[];
|
|
349
|
+
/** Unique-membership namespace owned by one physical secondary index. */
|
|
350
|
+
export declare function secondaryUniqueKeyNamespace(tableId: string, indexId: string): string;
|
|
351
|
+
/**
|
|
352
|
+
* One row trigger: catalog-persisted on its table record so the catalog epoch makes it
|
|
181
353
|
* visible to every tab immediately, and executed by the committing writer inside the same
|
|
182
354
|
* transaction as the triggering write — the write and its derivations publish atomically.
|
|
183
355
|
*/
|
|
184
356
|
export interface TriggerRecord {
|
|
357
|
+
/** Immutable durable identity. Names may be reused only after this trigger is gone. */
|
|
358
|
+
id: string;
|
|
185
359
|
name: string;
|
|
186
360
|
event: "insert" | "update" | "delete";
|
|
187
361
|
/**
|
|
@@ -210,7 +384,25 @@ export declare class TableRecordConflictError extends Error {
|
|
|
210
384
|
readonly name = "TableRecordConflictError";
|
|
211
385
|
constructor(tableId: string, expectedRevision: number, actualRevision: number | null);
|
|
212
386
|
}
|
|
387
|
+
/** A catalog drop lost a race with durable work that still owns records for the table. */
|
|
388
|
+
export declare class TableInUseError extends Error {
|
|
389
|
+
readonly tableId: string;
|
|
390
|
+
readonly ownerKind: "transaction" | "compaction job" | "foreign key" | "pending foreign key" | "accelerator build";
|
|
391
|
+
readonly ownerId: string;
|
|
392
|
+
readonly name = "TableInUseError";
|
|
393
|
+
constructor(tableId: string, ownerKind: "transaction" | "compaction job" | "foreign key" | "pending foreign key" | "accelerator build", ownerId: string);
|
|
394
|
+
}
|
|
395
|
+
/** Refuses a commit that would cross the persisted level-zero fragmentation safety ceiling. */
|
|
396
|
+
export declare class CompactionBacklogError extends Error {
|
|
397
|
+
readonly tableName: string;
|
|
398
|
+
readonly levelZeroSegments: number;
|
|
399
|
+
readonly limit: number;
|
|
400
|
+
readonly name = "CompactionBacklogError";
|
|
401
|
+
constructor(tableName: string, levelZeroSegments: number, limit: number);
|
|
402
|
+
}
|
|
213
403
|
export type SegmentKind = "insert" | "upsert" | "update" | "delete" | "base";
|
|
404
|
+
/** Absolute visible level-zero ceiling; every commit that adds L0 must enforce this or lower. */
|
|
405
|
+
export declare const MAX_LEVEL_ZERO_SEGMENTS = 4096;
|
|
214
406
|
/** Maps a contiguous segment-row run to its immutable hidden row IDs. */
|
|
215
407
|
export interface RowIdSpan {
|
|
216
408
|
readonly rowStart: number;
|
|
@@ -225,20 +417,17 @@ export interface SegmentRecord {
|
|
|
225
417
|
rowIdStart: bigint;
|
|
226
418
|
rowIdEndExclusive: bigint;
|
|
227
419
|
columnBlockIds: Record<string, string[]>;
|
|
228
|
-
kind
|
|
420
|
+
kind: SegmentKind;
|
|
229
421
|
keyColumnId?: string;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
/** Missing on legacy records, where commit order supplies the logical order. */
|
|
233
|
-
logicalOrder?: number;
|
|
422
|
+
level: number;
|
|
423
|
+
logicalOrder: number;
|
|
234
424
|
/**
|
|
235
425
|
* Staging position inside the owning transaction. Orders segments of one commit relative
|
|
236
|
-
* to each other (an in-scope update must fold after the in-scope insert it patches)
|
|
237
|
-
* missing on legacy records, which never shared a key within one commit.
|
|
426
|
+
* to each other (an in-scope update must fold after the in-scope insert it patches).
|
|
238
427
|
*/
|
|
239
|
-
commitOrdinal
|
|
240
|
-
/**
|
|
241
|
-
rowIdSpans
|
|
428
|
+
commitOrdinal: number;
|
|
429
|
+
/** Empty for a contiguous row-ID envelope; merged bases record every retained range. */
|
|
430
|
+
rowIdSpans: readonly RowIdSpan[];
|
|
242
431
|
/** Monotone policy ordinal for an immutable append-row-range level-two partition. */
|
|
243
432
|
readonly partitionOrdinal?: number;
|
|
244
433
|
createdAt: string;
|
|
@@ -247,15 +436,82 @@ export interface RowIdRange {
|
|
|
247
436
|
start: bigint;
|
|
248
437
|
endExclusive: bigint;
|
|
249
438
|
}
|
|
439
|
+
/** Largest persisted row ID/posting value; the wire format is canonical unsigned 64-bit. */
|
|
440
|
+
export declare const MAX_ROW_ID: bigint;
|
|
441
|
+
/** One past `MAX_ROW_ID`, allowed only for exclusive range/counter ends. */
|
|
442
|
+
export declare const MAX_ROW_ID_EXCLUSIVE_END: bigint;
|
|
443
|
+
/** Auto-increment values are exposed as exact JavaScript numbers and therefore stop here. */
|
|
444
|
+
export declare const MAX_AUTO_INCREMENT_VALUE: bigint;
|
|
445
|
+
export declare const MAX_AUTO_INCREMENT_EXCLUSIVE_END: bigint;
|
|
250
446
|
export type LeaseKind = "reader" | "backup";
|
|
447
|
+
/** A live owner renews; an abandoned durable pin expires within one hour. */
|
|
448
|
+
export declare const MAX_LEASE_TTL_MS: number;
|
|
449
|
+
/** Durable resource ceilings; adapters sweep expired owners before atomically refusing creation. */
|
|
450
|
+
export declare const MAX_ACTIVE_LEASES = 4096;
|
|
451
|
+
export declare const MAX_ACTIVE_TEMP_OWNERS = 1024;
|
|
452
|
+
export declare const MAX_TEMP_RUNS_PER_OWNER = 1024;
|
|
453
|
+
export declare const MAX_TEMP_PAGES_PER_OWNER = 16384;
|
|
454
|
+
export declare const MAX_TEMP_RUNS_TOTAL = 65536;
|
|
455
|
+
export declare const MAX_TEMP_PAGES_TOTAL = 262144;
|
|
456
|
+
export declare const MAX_TEMP_BYTES_PER_OWNER: number;
|
|
457
|
+
export declare const MAX_TEMP_BYTES_TOTAL: number;
|
|
458
|
+
export declare const MAX_ACTIVE_COMPACTION_JOBS = 1024;
|
|
459
|
+
export declare const MAX_ACTIVE_GARBAGE_COLLECTION_JOBS = 1;
|
|
460
|
+
export declare const MAX_ACTIVE_UNIQUE_KEY_BUILDS = 1024;
|
|
461
|
+
export declare const MAX_ACTIVE_FTS_BASE_BUILDS = 128;
|
|
462
|
+
export declare const MAX_ACTIVE_SECONDARY_INDEX_BUILDS = 128;
|
|
463
|
+
export declare const MAX_ACCELERATOR_BUILD_STAGED_BYTES_TOTAL: number;
|
|
464
|
+
export declare const MAX_ACCELERATOR_BUILD_STAGED_ENTRIES_TOTAL = 16777216;
|
|
465
|
+
export declare const MAX_ACTIVE_TRANSACTIONS = 4096;
|
|
466
|
+
export declare const MAX_GLOBAL_STAGED_ARTIFACT_BYTES: number;
|
|
467
|
+
export declare const MAX_GLOBAL_STAGED_BLOCKS = 65536;
|
|
468
|
+
export declare const MAX_GLOBAL_STAGED_SEGMENTS = 65536;
|
|
469
|
+
/** Catalog enumeration remains bounded even for cold public inspection APIs. */
|
|
470
|
+
export declare const MAX_CATALOG_RECORDS = 4096;
|
|
471
|
+
/** Total canonical UTF-8 record-wire bytes retained by the durable catalog. */
|
|
472
|
+
export declare const MAX_CATALOG_RETAINED_BYTES: number;
|
|
473
|
+
export declare const MAX_MANIFEST_RECORDS = 65536;
|
|
474
|
+
export declare const MAX_MANIFEST_RETAINED_BYTES: number;
|
|
475
|
+
export declare const MAX_SEGMENT_RECORDS = 1048576;
|
|
476
|
+
export declare const MAX_SEGMENT_RETAINED_BYTES: number;
|
|
477
|
+
/** Durable diagnostic/provenance tails are pruned before admitting more terminal records. */
|
|
478
|
+
export declare const MAX_TERMINAL_TRANSACTION_RECORDS = 65536;
|
|
479
|
+
export declare const MAX_TERMINAL_COMPACTION_JOB_RECORDS = 4096;
|
|
480
|
+
export declare const MAX_COMPLETED_GARBAGE_COLLECTION_JOB_RECORDS = 1024;
|
|
481
|
+
/** An old renewable pin may not force unbounded history retention while writes continue. */
|
|
482
|
+
export declare const MAX_PINNED_MANIFEST_VERSION_LAG = 4096;
|
|
483
|
+
export declare const MAX_PINNED_RETIRED_BLOCKS = 65536;
|
|
484
|
+
export declare const MAX_PINNED_RETIRED_BYTES: number;
|
|
485
|
+
/** Total obsolete physical history is refused before it can consume an origin indefinitely. */
|
|
486
|
+
export declare const MAX_RETIRED_HISTORY_BYTES: number;
|
|
487
|
+
/** A durable resource family reached its fixed corruption/growth safety ceiling. */
|
|
488
|
+
export declare class StorageResourceLimitError extends Error {
|
|
489
|
+
readonly resource: "lease" | "temp owner" | "temp run" | "temp page" | "temporary run total" | "temporary page total" | "temp owner byte" | "temporary byte" | "compaction job" | "garbage collection job" | "unique-key build" | "full-text build" | "secondary-index build" | "accelerator build byte" | "accelerator build entry" | "transaction" | "staged artifact byte" | "staged block" | "staged segment" | "catalog record" | "catalog byte" | "manifest record" | "manifest byte" | "segment record" | "segment byte" | "terminal transaction" | "terminal compaction job" | "completed garbage collection job" | "pinned manifest version lag" | "pinned retired block" | "pinned retired byte" | "snapshot accelerator byte" | "snapshot accelerator entry" | "retired history byte";
|
|
490
|
+
readonly count: number;
|
|
491
|
+
readonly limit: number;
|
|
492
|
+
readonly name = "StorageResourceLimitError";
|
|
493
|
+
constructor(resource: "lease" | "temp owner" | "temp run" | "temp page" | "temporary run total" | "temporary page total" | "temp owner byte" | "temporary byte" | "compaction job" | "garbage collection job" | "unique-key build" | "full-text build" | "secondary-index build" | "accelerator build byte" | "accelerator build entry" | "transaction" | "staged artifact byte" | "staged block" | "staged segment" | "catalog record" | "catalog byte" | "manifest record" | "manifest byte" | "segment record" | "segment byte" | "terminal transaction" | "terminal compaction job" | "completed garbage collection job" | "pinned manifest version lag" | "pinned retired block" | "pinned retired byte" | "snapshot accelerator byte" | "snapshot accelerator entry" | "retired history byte", count: number, limit: number);
|
|
494
|
+
}
|
|
251
495
|
export interface LeaseRecord {
|
|
252
496
|
id: string;
|
|
253
497
|
kind: LeaseKind;
|
|
254
498
|
manifestVersion: number | null;
|
|
255
499
|
ownerId: string;
|
|
500
|
+
/** Issuance cutoff used to prove the initial expiry is bounded. */
|
|
501
|
+
createdAt: string;
|
|
256
502
|
expiresAt: string;
|
|
257
503
|
revision: number;
|
|
258
504
|
}
|
|
505
|
+
export interface RenewLeaseInput {
|
|
506
|
+
id: string;
|
|
507
|
+
expectedRevision: number;
|
|
508
|
+
/** A persisted expiry at or before this boundary is irrevocably expired. */
|
|
509
|
+
expiresAtCutoff: string;
|
|
510
|
+
expiresAt: string;
|
|
511
|
+
}
|
|
512
|
+
export interface MoveLeaseInput extends RenewLeaseInput {
|
|
513
|
+
manifestVersion: number | null;
|
|
514
|
+
}
|
|
259
515
|
export declare const compactionJobStates: readonly ["planned", "running", "ready", "published", "cancelled", "aborted"];
|
|
260
516
|
export type CompactionJobState = (typeof compactionJobStates)[number];
|
|
261
517
|
export interface CompactionJobCursor {
|
|
@@ -399,19 +655,18 @@ export interface CompactionJobRecord {
|
|
|
399
655
|
sourceStoredBytes: number;
|
|
400
656
|
outputStoredBytes: number;
|
|
401
657
|
logicalBytes: number;
|
|
402
|
-
|
|
403
|
-
readonly rewritePlan?: CompactionRewritePlan;
|
|
658
|
+
readonly rewritePlan: CompactionRewritePlan;
|
|
404
659
|
/** Null for copy-v1; points at the next output for rechunk-v1. */
|
|
405
|
-
outputCursor
|
|
660
|
+
outputCursor: CompactionOutputCursor | null;
|
|
406
661
|
/** Immutable execution budget. Zero for copy-v1 jobs. */
|
|
407
|
-
readonly memoryBudgetBytes
|
|
662
|
+
readonly memoryBudgetBytes: number;
|
|
408
663
|
/** Immutable planner estimate. Zero for copy-v1 jobs. */
|
|
409
|
-
readonly minimumMemoryBytes
|
|
410
|
-
/** Immutable stored bytes from newly promoted level-zero sources.
|
|
411
|
-
readonly level0SourceStoredBytes
|
|
412
|
-
/** Immutable stored bytes from the retained level-one anchor.
|
|
413
|
-
readonly anchorSourceStoredBytes
|
|
414
|
-
/** Output partition assigned by the append-row-range L2 policy.
|
|
664
|
+
readonly minimumMemoryBytes: number;
|
|
665
|
+
/** Immutable stored bytes from newly promoted level-zero sources. */
|
|
666
|
+
readonly level0SourceStoredBytes: number;
|
|
667
|
+
/** Immutable stored bytes from the retained level-one anchor. */
|
|
668
|
+
readonly anchorSourceStoredBytes: number;
|
|
669
|
+
/** Output partition assigned by the append-row-range L2 policy. */
|
|
415
670
|
readonly outputPartitionOrdinal?: number;
|
|
416
671
|
/** Immutable maximum compaction output bytes per newly promoted L0 byte. */
|
|
417
672
|
readonly maxWriteAmplification?: number;
|
|
@@ -425,8 +680,8 @@ export interface CompactionJobRecord {
|
|
|
425
680
|
* write-amplification budget.
|
|
426
681
|
*/
|
|
427
682
|
readonly priorAttemptOutputStoredBytes?: number;
|
|
428
|
-
peakWorkingBytes
|
|
429
|
-
outputLogicalBytes
|
|
683
|
+
peakWorkingBytes: number;
|
|
684
|
+
outputLogicalBytes: number;
|
|
430
685
|
targetLevel: number;
|
|
431
686
|
state: CompactionJobState;
|
|
432
687
|
transactionId: string | null;
|
|
@@ -454,6 +709,16 @@ export interface CompactionJobRecordUpdate {
|
|
|
454
709
|
updatedAt: string;
|
|
455
710
|
error?: string | null;
|
|
456
711
|
}
|
|
712
|
+
/** Every segment ID owned by a compaction job, including merge partition outputs. */
|
|
713
|
+
export declare function compactionOutputSegmentIds(job: Pick<CompactionJobRecord, "outputSegmentId" | "rewritePlan">): string[];
|
|
714
|
+
/**
|
|
715
|
+
* Proves that a compaction transaction stages exactly the immutable job output. This is kept in
|
|
716
|
+
* the storage contract (rather than only in the engine) so adapters reject forged, reordered, or
|
|
717
|
+
* partially journaled output before publication and while loading durable state.
|
|
718
|
+
*/
|
|
719
|
+
export declare function assertCompactionOutputProvenance(job: CompactionJobRecord, table: TableRecord, transaction: Pick<TransactionRecord, "id" | "pendingBlockIds" | "pendingSegmentIds">, sourceSegments: readonly SegmentRecord[], outputSegments: readonly SegmentRecord[], options?: {
|
|
720
|
+
readonly allowOutputPrefix?: boolean;
|
|
721
|
+
}): void;
|
|
457
722
|
export declare class CompactionJobConflictError extends Error {
|
|
458
723
|
readonly jobId: string;
|
|
459
724
|
readonly expectedRevision: number;
|
|
@@ -489,6 +754,52 @@ export interface CreateGarbageCollectionJobInput {
|
|
|
489
754
|
/** Fixed cutoff used to decide which persisted leases protect a manifest for this job. */
|
|
490
755
|
leaseCutoff: string;
|
|
491
756
|
createdAt: string;
|
|
757
|
+
/** Present while bounded discovery is still paging durable metadata. */
|
|
758
|
+
discovery?: GarbageCollectionDiscovery;
|
|
759
|
+
}
|
|
760
|
+
export type GarbageCollectionDiscoveryPhase = "manifests" | "manifest-blocks" | "segments" | "transactions" | "compactions" | "complete";
|
|
761
|
+
export interface GarbageCollectionDiscovery {
|
|
762
|
+
phase: GarbageCollectionDiscoveryPhase;
|
|
763
|
+
currentManifestVersion: number | null;
|
|
764
|
+
retainAboveVersion: number;
|
|
765
|
+
retainAfter: number;
|
|
766
|
+
maxPlanningItems: number;
|
|
767
|
+
manifestCursor: number | null;
|
|
768
|
+
segmentCursor: string | null;
|
|
769
|
+
transactionCursor: string | null;
|
|
770
|
+
compactionCursor: string | null;
|
|
771
|
+
visitedRecords: number;
|
|
772
|
+
/**
|
|
773
|
+
* When a bounded candidate array fills, reclamation completes this job and the next job
|
|
774
|
+
* resumes this discovery phase instead of restarting at the beginning.
|
|
775
|
+
*/
|
|
776
|
+
resumePhase?: Exclude<GarbageCollectionDiscoveryPhase, "complete"> | null;
|
|
777
|
+
/** Older continuation resumed only after this job first discovers newly eligible manifests. */
|
|
778
|
+
postManifestPhase?: Exclude<GarbageCollectionDiscoveryPhase, "complete" | "manifests"> | null;
|
|
779
|
+
/** Exact within-record provenance offset; every named artifact is examined at most once. */
|
|
780
|
+
artifactCursor?: GarbageCollectionArtifactCursor | null;
|
|
781
|
+
}
|
|
782
|
+
export interface GarbageCollectionArtifactCursor {
|
|
783
|
+
family: "manifest" | "transaction" | "compaction";
|
|
784
|
+
/** Decimal manifest version for `manifest`; durable record ID for the other families. */
|
|
785
|
+
recordId: string;
|
|
786
|
+
/** Exact lexical manifest-membership cursor; null for transaction/compaction arrays. */
|
|
787
|
+
blockId: string | null;
|
|
788
|
+
blockIndex: number;
|
|
789
|
+
segmentIndex: number;
|
|
790
|
+
}
|
|
791
|
+
/** Absolute per-call bound for durable maintenance candidate arrays and storage transactions. */
|
|
792
|
+
export declare const MAX_MAINTENANCE_BATCH_ITEMS = 1024;
|
|
793
|
+
export declare function boundedMaintenanceBatchItems(value: number, label: string): number;
|
|
794
|
+
export interface UpdateGarbageCollectionPlanningInput {
|
|
795
|
+
jobId: string;
|
|
796
|
+
expectedRevision: number;
|
|
797
|
+
candidateManifestVersions?: readonly number[];
|
|
798
|
+
candidateSegmentIds?: readonly string[];
|
|
799
|
+
candidateBlockIds?: readonly string[];
|
|
800
|
+
candidateTransactionIds?: readonly string[];
|
|
801
|
+
discovery: GarbageCollectionDiscovery;
|
|
802
|
+
updatedAt: string;
|
|
492
803
|
}
|
|
493
804
|
export interface GarbageCollectionJobRecord {
|
|
494
805
|
id: string;
|
|
@@ -516,6 +827,8 @@ export interface GarbageCollectionJobRecord {
|
|
|
516
827
|
leaseCutoff: string;
|
|
517
828
|
createdAt: string;
|
|
518
829
|
updatedAt: string;
|
|
830
|
+
/** Omitted only for explicitly supplied bounded candidate jobs; no discovery scan is needed. */
|
|
831
|
+
discovery?: GarbageCollectionDiscovery;
|
|
519
832
|
}
|
|
520
833
|
export interface RunGarbageCollectionStepInput {
|
|
521
834
|
jobId: string;
|
|
@@ -584,9 +897,29 @@ export declare class LeaseConflictError extends Error {
|
|
|
584
897
|
readonly name = "LeaseConflictError";
|
|
585
898
|
constructor(leaseId: string, expectedRevision: number, actualRevision: number | null);
|
|
586
899
|
}
|
|
900
|
+
/** A renewal/move cutoff reached the persisted expiry; expiry is irrevocable. */
|
|
901
|
+
export declare class LeaseExpiredError extends Error {
|
|
902
|
+
readonly leaseId: string;
|
|
903
|
+
readonly expiresAt: string;
|
|
904
|
+
readonly expiresAtCutoff: string;
|
|
905
|
+
readonly name = "LeaseExpiredError";
|
|
906
|
+
constructor(leaseId: string, expiresAt: string, expiresAtCutoff: string);
|
|
907
|
+
}
|
|
908
|
+
/** Refuses a lease release from a different durable owner. */
|
|
909
|
+
export declare class LeaseOwnerConflictError extends Error {
|
|
910
|
+
readonly leaseId: string;
|
|
911
|
+
readonly expectedOwnerId: string;
|
|
912
|
+
readonly actualOwnerId: string;
|
|
913
|
+
readonly name = "LeaseOwnerConflictError";
|
|
914
|
+
constructor(leaseId: string, expectedOwnerId: string, actualOwnerId: string);
|
|
915
|
+
}
|
|
587
916
|
export type TransactionStatus = "active" | "committed" | "aborted";
|
|
588
917
|
export interface TransactionRecord {
|
|
589
918
|
id: string;
|
|
919
|
+
/** Stable writer identity; liveness renewals never contend on the data revision. */
|
|
920
|
+
ownerId: string;
|
|
921
|
+
/** Durable writer liveness deadline. Expired active records are atomically aborted by GC. */
|
|
922
|
+
expiresAt: string;
|
|
590
923
|
snapshotVersion: number | null;
|
|
591
924
|
pendingBlockIds: string[];
|
|
592
925
|
pendingSegmentIds: string[];
|
|
@@ -595,6 +928,33 @@ export interface TransactionRecord {
|
|
|
595
928
|
startedAt: string;
|
|
596
929
|
updatedAt: string;
|
|
597
930
|
committedVersion: number | null;
|
|
931
|
+
/**
|
|
932
|
+
* Structural catalog epoch captured atomically with the transaction snapshot. Every active
|
|
933
|
+
* transaction carries this storage-owned guard; commit rejects it if DDL changed the schema
|
|
934
|
+
* used to prepare the staged artifacts. Terminal records drop the guard.
|
|
935
|
+
*/
|
|
936
|
+
schemaEpochGuard?: number;
|
|
937
|
+
/**
|
|
938
|
+
* Catalog record owned exclusively by this active transaction. It is invisible to catalog
|
|
939
|
+
* reads until commit; abort/expiry discards the reservation with the transaction.
|
|
940
|
+
*/
|
|
941
|
+
pendingTable?: TableRecord;
|
|
942
|
+
/** Next row id for the pending table, advanced atomically as insert artifacts stage. */
|
|
943
|
+
pendingTableNextRowId?: bigint;
|
|
944
|
+
/** Catalog epoch captured atomically when the pending table was admitted. */
|
|
945
|
+
catalogEpochGuard?: number;
|
|
946
|
+
}
|
|
947
|
+
export interface AbortTransactionIfExpiredInput {
|
|
948
|
+
transactionId: string;
|
|
949
|
+
expectedOwnerId: string;
|
|
950
|
+
expiresAtCutoff: string;
|
|
951
|
+
updatedAt: string;
|
|
952
|
+
}
|
|
953
|
+
export interface RenewTransactionInput {
|
|
954
|
+
transactionId: string;
|
|
955
|
+
ownerId: string;
|
|
956
|
+
expiresAtCutoff: string;
|
|
957
|
+
expiresAt: string;
|
|
598
958
|
}
|
|
599
959
|
export interface TransactionRecordUpdate {
|
|
600
960
|
snapshotVersion?: number | null;
|
|
@@ -603,10 +963,15 @@ export interface TransactionRecordUpdate {
|
|
|
603
963
|
status?: TransactionStatus;
|
|
604
964
|
updatedAt: string;
|
|
605
965
|
committedVersion?: number | null;
|
|
966
|
+
/** Storage-owned advancement while staging rows for a pending table. */
|
|
967
|
+
pendingTableNextRowId?: bigint;
|
|
606
968
|
}
|
|
607
969
|
export interface BeginTransactionInput {
|
|
608
|
-
/**
|
|
609
|
-
|
|
970
|
+
/**
|
|
971
|
+
* Record to create; the store atomically stamps both `snapshotVersion` and
|
|
972
|
+
* `schemaEpochGuard` from its current state.
|
|
973
|
+
*/
|
|
974
|
+
record: Omit<TransactionRecord, "snapshotVersion" | "schemaEpochGuard">;
|
|
610
975
|
/** Reserve this many row ids for the table in the same atomic step. */
|
|
611
976
|
reserveRowIds?: {
|
|
612
977
|
tableId: string;
|
|
@@ -622,6 +987,15 @@ export interface BeginTransactionInput {
|
|
|
622
987
|
count: number;
|
|
623
988
|
atLeast?: bigint;
|
|
624
989
|
};
|
|
990
|
+
/**
|
|
991
|
+
* Reserves one invisible catalog record and its initial row-id state in the same atomic step.
|
|
992
|
+
* The expected epoch closes schema/FK races between planning and begin; commit rechecks it.
|
|
993
|
+
*/
|
|
994
|
+
pendingTable?: {
|
|
995
|
+
record: TableRecord;
|
|
996
|
+
nextRowId: bigint;
|
|
997
|
+
expectedCatalogEpoch: number;
|
|
998
|
+
};
|
|
625
999
|
}
|
|
626
1000
|
export interface BeginTransactionResult {
|
|
627
1001
|
record: TransactionRecord;
|
|
@@ -635,6 +1009,332 @@ export interface StageTransactionArtifactsInput {
|
|
|
635
1009
|
segments: readonly SegmentRecord[];
|
|
636
1010
|
updatedAt: string;
|
|
637
1011
|
}
|
|
1012
|
+
/** Maximum immutable payloads accepted by one atomic staging/WAL operation. */
|
|
1013
|
+
export declare const MAX_TRANSACTION_STAGE_BLOCKS = 64;
|
|
1014
|
+
/** Maximum segment records accepted by one atomic staging/WAL operation. */
|
|
1015
|
+
export declare const MAX_TRANSACTION_STAGE_SEGMENTS = 64;
|
|
1016
|
+
/**
|
|
1017
|
+
* Maximum block bytes accepted by one atomic staging/WAL operation. The limit still admits one
|
|
1018
|
+
* maximum-size physical block; callers split collections of smaller blocks into bounded calls.
|
|
1019
|
+
*/
|
|
1020
|
+
export declare const MAX_TRANSACTION_STAGE_BYTES: number;
|
|
1021
|
+
/** Durable journal ceilings prevent a forgotten or hostile transaction growing without bound. */
|
|
1022
|
+
export declare const MAX_TRANSACTION_PENDING_BLOCKS = 4096;
|
|
1023
|
+
export declare const MAX_TRANSACTION_PENDING_SEGMENTS = 4096;
|
|
1024
|
+
/** Storage-boundary preflight shared by staging and single-shot write implementations. */
|
|
1025
|
+
export declare function assertTransactionArtifactBatchLimits(blocks: readonly BlockWrite[], segments: readonly SegmentRecord[]): void;
|
|
1026
|
+
/** Preflight for the complete persisted journal after a bounded staging operation. */
|
|
1027
|
+
export declare function assertTransactionArtifactJournalLimits(pendingBlockIds: readonly string[], pendingSegmentIds: readonly string[]): void;
|
|
1028
|
+
/**
|
|
1029
|
+
* Atomically rewinds one active transaction's artifact journal to an earlier set and removes
|
|
1030
|
+
* exactly the artifacts that are no longer reachable. Journals are canonically sorted, so an
|
|
1031
|
+
* adapter validates the retained and removed lists as a duplicate-free, disjoint, exact
|
|
1032
|
+
* partition of its current journal before changing records or bytes.
|
|
1033
|
+
*/
|
|
1034
|
+
export interface RollbackTransactionArtifactsInput {
|
|
1035
|
+
transactionId: string;
|
|
1036
|
+
expectedRevision: number;
|
|
1037
|
+
pendingBlockIds: readonly string[];
|
|
1038
|
+
pendingSegmentIds: readonly string[];
|
|
1039
|
+
removeBlockIds: readonly string[];
|
|
1040
|
+
removeSegmentIds: readonly string[];
|
|
1041
|
+
updatedAt: string;
|
|
1042
|
+
}
|
|
1043
|
+
export type StorageIntegrityMode = "metadata" | "full";
|
|
1044
|
+
export interface StorageIntegrityIssue {
|
|
1045
|
+
readonly code: string;
|
|
1046
|
+
readonly location: string;
|
|
1047
|
+
readonly message: string;
|
|
1048
|
+
}
|
|
1049
|
+
export interface StorageIntegrityReport {
|
|
1050
|
+
readonly mode: StorageIntegrityMode;
|
|
1051
|
+
readonly ok: boolean;
|
|
1052
|
+
readonly checkedRecords: number;
|
|
1053
|
+
readonly checkedBlocks: number;
|
|
1054
|
+
readonly checkedBytes: number;
|
|
1055
|
+
/** Total findings; `issues` itself is bounded by `maxIssues`. */
|
|
1056
|
+
readonly issueCount: number;
|
|
1057
|
+
readonly issues: readonly StorageIntegrityIssue[];
|
|
1058
|
+
}
|
|
1059
|
+
export interface StorageStats {
|
|
1060
|
+
readonly backend: string;
|
|
1061
|
+
/** Bytes reachable as current database records or payloads. */
|
|
1062
|
+
readonly logicalBytes: number;
|
|
1063
|
+
/** Actual substrate allocation where available; IndexedDB cannot report this per database. */
|
|
1064
|
+
readonly physicalBytes: number | null;
|
|
1065
|
+
readonly liveBlockCount: number;
|
|
1066
|
+
/** Stored payloads outside the current manifest, including staged and retired bytes. */
|
|
1067
|
+
readonly obsoleteBlockCount: number;
|
|
1068
|
+
readonly liveBlockBytes: number;
|
|
1069
|
+
readonly obsoleteBlockBytes: number;
|
|
1070
|
+
readonly temporaryBytes: number;
|
|
1071
|
+
readonly walBytes: number | null;
|
|
1072
|
+
readonly checkpointBytes: number | null;
|
|
1073
|
+
readonly orphanBytes: number | null;
|
|
1074
|
+
readonly manifestCount: number;
|
|
1075
|
+
readonly transactionCount: number;
|
|
1076
|
+
readonly segmentCount: number;
|
|
1077
|
+
readonly maintenance?: {
|
|
1078
|
+
readonly degraded: boolean;
|
|
1079
|
+
readonly consecutiveFailures: number;
|
|
1080
|
+
readonly lastError: string | null;
|
|
1081
|
+
readonly walLimitBytes: number | null;
|
|
1082
|
+
/** Durable garbage awaiting safe physical deletion, when the substrate separates the two. */
|
|
1083
|
+
readonly cleanupDebtBytes: number | null;
|
|
1084
|
+
/** Refusal/backpressure ceiling for cleanup debt, or null when the substrate has no debt. */
|
|
1085
|
+
readonly cleanupLimitBytes: number | null;
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
export interface InterruptedSnapshotImport {
|
|
1089
|
+
readonly identity: string;
|
|
1090
|
+
readonly version: number;
|
|
1091
|
+
readonly createdAt: string;
|
|
1092
|
+
readonly stagedBlockCount: number;
|
|
1093
|
+
readonly stagedBytes: number;
|
|
1094
|
+
}
|
|
1095
|
+
export interface InterruptedSnapshotImportAbortResult {
|
|
1096
|
+
readonly identity: string;
|
|
1097
|
+
readonly removedBlockCount: number;
|
|
1098
|
+
readonly removedBytes: number;
|
|
1099
|
+
}
|
|
1100
|
+
/** A snapshot session is renewable but can never pin storage for more than one hour unattended. */
|
|
1101
|
+
export declare const MAX_SNAPSHOT_SESSION_TTL_MS: number;
|
|
1102
|
+
/** Snapshot v1 is an ordered bounded record stream; no database-sized collection is in header. */
|
|
1103
|
+
export declare const SNAPSHOT_FRAME_KINDS: readonly ["catalog-page", "segment-page", "transaction-page", "unique-page", "posting-page", "block"];
|
|
1104
|
+
export type SnapshotFrameKind = (typeof SNAPSHOT_FRAME_KINDS)[number];
|
|
1105
|
+
export declare const MAX_SNAPSHOT_FRAME_ITEMS = 1024;
|
|
1106
|
+
export declare const MAX_SNAPSHOT_METADATA_FRAME_BYTES: number;
|
|
1107
|
+
export declare const MAX_SNAPSHOT_FRAME_BATCH_ITEMS = 64;
|
|
1108
|
+
export declare const MAX_SNAPSHOT_METADATA_BATCH_BYTES: number;
|
|
1109
|
+
/** One block frame is permitted; metadata frames still use MAX_SNAPSHOT_METADATA_BATCH_BYTES. */
|
|
1110
|
+
export declare const MAX_SNAPSHOT_FRAME_BATCH_BYTES: number;
|
|
1111
|
+
/**
|
|
1112
|
+
* Framed restore builds accelerator generations in a disposable core before one atomic publish.
|
|
1113
|
+
* These aggregate ceilings keep that validation heap bounded until generations become a native
|
|
1114
|
+
* chunk-backed structure rather than one materialized in-memory collection.
|
|
1115
|
+
*/
|
|
1116
|
+
export declare const MAX_SNAPSHOT_IMPORT_ACCELERATOR_RETAINED_BYTES: number;
|
|
1117
|
+
export declare const MAX_SNAPSHOT_IMPORT_ACCELERATOR_RETAINED_ENTRIES = 16777216;
|
|
1118
|
+
export interface SnapshotKindSummary {
|
|
1119
|
+
readonly frameCount: number;
|
|
1120
|
+
readonly itemCount: number;
|
|
1121
|
+
readonly storedBytes: number;
|
|
1122
|
+
}
|
|
1123
|
+
/** One table plus its durable allocation counters; memberships/postings are separate pages. */
|
|
1124
|
+
export interface SnapshotCatalogItem {
|
|
1125
|
+
readonly kind: "table";
|
|
1126
|
+
readonly record: TableRecord;
|
|
1127
|
+
readonly nextRowId: bigint;
|
|
1128
|
+
readonly autoIncrement: ReadonlyArray<{
|
|
1129
|
+
readonly columnId: string;
|
|
1130
|
+
readonly next: bigint;
|
|
1131
|
+
}>;
|
|
1132
|
+
}
|
|
1133
|
+
export interface SnapshotSegmentItem {
|
|
1134
|
+
readonly kind: "segment";
|
|
1135
|
+
readonly record: SegmentRecord;
|
|
1136
|
+
}
|
|
1137
|
+
export interface SnapshotTransactionItem {
|
|
1138
|
+
readonly kind: "transaction";
|
|
1139
|
+
readonly record: TransactionRecord;
|
|
1140
|
+
}
|
|
1141
|
+
/** Descriptor precedes this generation's chunks; tokens are globally strict lexical order. */
|
|
1142
|
+
export interface SnapshotUniqueGenerationItem {
|
|
1143
|
+
readonly kind: "unique-generation";
|
|
1144
|
+
readonly tableId: string;
|
|
1145
|
+
readonly indexId: string | null;
|
|
1146
|
+
readonly namespaceId: string;
|
|
1147
|
+
readonly generationId: string;
|
|
1148
|
+
readonly chunkCount: number;
|
|
1149
|
+
readonly tokenCount: number;
|
|
1150
|
+
}
|
|
1151
|
+
export interface SnapshotUniqueChunkItem {
|
|
1152
|
+
readonly kind: "unique-chunk";
|
|
1153
|
+
readonly namespaceId: string;
|
|
1154
|
+
readonly generationId: string;
|
|
1155
|
+
readonly ordinal: number;
|
|
1156
|
+
readonly keyTokens: readonly string[];
|
|
1157
|
+
}
|
|
1158
|
+
export type SnapshotUniqueItem = SnapshotUniqueGenerationItem | SnapshotUniqueChunkItem;
|
|
1159
|
+
/**
|
|
1160
|
+
* Complete canonical postings generation at the captured version. Both full-text and scalar
|
|
1161
|
+
* secondary accelerators use this base format; deltas are merged during bounded export, so a
|
|
1162
|
+
* restore never needs pre-snapshot history.
|
|
1163
|
+
*/
|
|
1164
|
+
export interface SnapshotPostingGenerationItem {
|
|
1165
|
+
readonly kind: "posting-generation";
|
|
1166
|
+
readonly tableId: string;
|
|
1167
|
+
readonly ownerKind: "fts-column" | "secondary-index";
|
|
1168
|
+
readonly ownerId: string;
|
|
1169
|
+
readonly storageColumnId: string;
|
|
1170
|
+
readonly generationId: string;
|
|
1171
|
+
readonly coversVersion: number;
|
|
1172
|
+
readonly chunkCount: number;
|
|
1173
|
+
/** Exact safe sum of every posting frequency; secondary-index frequencies are always one. */
|
|
1174
|
+
readonly totalTokens: number;
|
|
1175
|
+
}
|
|
1176
|
+
export interface SnapshotPostingChunkItem {
|
|
1177
|
+
readonly kind: "posting-chunk";
|
|
1178
|
+
readonly storageColumnId: string;
|
|
1179
|
+
readonly generationId: string;
|
|
1180
|
+
readonly ordinal: number;
|
|
1181
|
+
readonly postings: readonly FtsPosting[];
|
|
1182
|
+
}
|
|
1183
|
+
export type SnapshotPostingItem = SnapshotPostingGenerationItem | SnapshotPostingChunkItem;
|
|
1184
|
+
export type SnapshotMetadataItem = SnapshotCatalogItem | SnapshotSegmentItem | SnapshotTransactionItem | SnapshotUniqueItem | SnapshotPostingItem;
|
|
1185
|
+
/** Modeled heap retained by one framed accelerator chunk during atomic snapshot validation. */
|
|
1186
|
+
export declare function snapshotAcceleratorItemRetainedUsage(item: SnapshotUniqueChunkItem | SnapshotPostingChunkItem): {
|
|
1187
|
+
bytes: number;
|
|
1188
|
+
entries: number;
|
|
1189
|
+
};
|
|
1190
|
+
/** Shared arithmetic boundary used by streaming adapters and allocation-free cap tests. */
|
|
1191
|
+
export declare function assertSnapshotImportAcceleratorUsage(bytes: number, entries: number): void;
|
|
1192
|
+
/**
|
|
1193
|
+
* Canonical compressed container header. It remains O(1) with database size: the six entries
|
|
1194
|
+
* below contain counts and byte totals only, never record descriptors, keys, or postings.
|
|
1195
|
+
*/
|
|
1196
|
+
export interface SnapshotFrameStreamHeader {
|
|
1197
|
+
readonly formatVersion: 1;
|
|
1198
|
+
readonly databaseVersion: number;
|
|
1199
|
+
readonly createdAt: string;
|
|
1200
|
+
readonly kinds: Readonly<Record<SnapshotFrameKind, SnapshotKindSummary>>;
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* One exact body frame. Frames are globally contiguous by `sequence` and grouped in
|
|
1204
|
+
* `SNAPSHOT_FRAME_KINDS` order. Within kinds, tables/segments/transactions/blocks order by ID;
|
|
1205
|
+
* UNIQUE generations order by namespace (descriptor, then contiguous chunk ordinals), and
|
|
1206
|
+
* posting generations by storageColumnId using the same descriptor/chunk rule. Metadata
|
|
1207
|
+
* payloads use canonical adapter encoding and contain at
|
|
1208
|
+
* most MAX_SNAPSHOT_FRAME_ITEMS/MAX_SNAPSHOT_METADATA_FRAME_BYTES; a block frame contains one
|
|
1209
|
+
* ID plus one stored block and may use MAX_STORED_BLOCK_BYTE_LENGTH. `checksum` covers the exact
|
|
1210
|
+
* payload. Metadata payloads use the single core-owned snapshot wire codec; adapters must not
|
|
1211
|
+
* substitute substrate encodings. Lost-ack replay must additionally compare the complete
|
|
1212
|
+
* persisted bytes.
|
|
1213
|
+
*/
|
|
1214
|
+
export interface SnapshotFrame {
|
|
1215
|
+
readonly sequence: number;
|
|
1216
|
+
readonly kind: SnapshotFrameKind;
|
|
1217
|
+
readonly itemCount: number;
|
|
1218
|
+
/** Block ID for a block frame; null for core-wire-encoded metadata pages. */
|
|
1219
|
+
readonly key: string | null;
|
|
1220
|
+
readonly payload: Uint8Array;
|
|
1221
|
+
readonly checksum: number;
|
|
1222
|
+
}
|
|
1223
|
+
export interface SnapshotFrameFooter {
|
|
1224
|
+
readonly frameCount: number;
|
|
1225
|
+
readonly itemCount: number;
|
|
1226
|
+
readonly storedBytes: number;
|
|
1227
|
+
/** Rolling checksum over every canonical frame header and payload in sequence order. */
|
|
1228
|
+
readonly checksum: number;
|
|
1229
|
+
}
|
|
1230
|
+
export interface BeginSnapshotFrameExportInput {
|
|
1231
|
+
readonly ownerId: string;
|
|
1232
|
+
readonly createdAt: string;
|
|
1233
|
+
readonly expiresAt: string;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Export begin atomically captures a frozen catalog/segment/transaction/accelerator generation
|
|
1237
|
+
* into bounded durable pages and records only an exact manifest version/cursor for blocks (it
|
|
1238
|
+
* must not copy block descriptors). It creates the backup lease in the same operation.
|
|
1239
|
+
* Catalog-only writes after begin cannot change the session.
|
|
1240
|
+
*/
|
|
1241
|
+
export interface SnapshotFrameExportSession {
|
|
1242
|
+
readonly sessionId: string;
|
|
1243
|
+
readonly ownerId: string;
|
|
1244
|
+
readonly expiresAt: string;
|
|
1245
|
+
readonly header: SnapshotFrameStreamHeader;
|
|
1246
|
+
}
|
|
1247
|
+
export interface ReadSnapshotExportFrameInput {
|
|
1248
|
+
readonly sessionId: string;
|
|
1249
|
+
readonly ownerId: string;
|
|
1250
|
+
readonly sequence: number;
|
|
1251
|
+
readonly expiresAtCutoff: string;
|
|
1252
|
+
readonly expiresAt: string;
|
|
1253
|
+
}
|
|
1254
|
+
export interface BeginSnapshotFrameImportInput {
|
|
1255
|
+
readonly identity: string;
|
|
1256
|
+
readonly ownerId: string;
|
|
1257
|
+
readonly createdAt: string;
|
|
1258
|
+
readonly expiresAt: string;
|
|
1259
|
+
readonly header: SnapshotFrameStreamHeader;
|
|
1260
|
+
}
|
|
1261
|
+
export interface SnapshotFrameImportSession {
|
|
1262
|
+
readonly identity: string;
|
|
1263
|
+
readonly ownerId: string;
|
|
1264
|
+
readonly version: number;
|
|
1265
|
+
readonly createdAt: string;
|
|
1266
|
+
readonly expiresAt: string;
|
|
1267
|
+
readonly nextSequence: number;
|
|
1268
|
+
readonly stagedBytes: number;
|
|
1269
|
+
}
|
|
1270
|
+
export interface RenewSnapshotFrameImportInput {
|
|
1271
|
+
readonly identity: string;
|
|
1272
|
+
readonly ownerId: string;
|
|
1273
|
+
readonly expiresAtCutoff: string;
|
|
1274
|
+
readonly expiresAt: string;
|
|
1275
|
+
}
|
|
1276
|
+
export interface AppendSnapshotImportFramesInput extends RenewSnapshotFrameImportInput {
|
|
1277
|
+
/** Bounded contiguous frames; replayed sequences compare complete persisted bytes. */
|
|
1278
|
+
readonly frames: readonly SnapshotFrame[];
|
|
1279
|
+
}
|
|
1280
|
+
export interface FinishSnapshotFrameImportInput {
|
|
1281
|
+
readonly identity: string;
|
|
1282
|
+
readonly ownerId: string;
|
|
1283
|
+
readonly expiresAtCutoff: string;
|
|
1284
|
+
readonly footer: SnapshotFrameFooter;
|
|
1285
|
+
}
|
|
1286
|
+
export interface CloseSnapshotExportInput {
|
|
1287
|
+
readonly sessionId: string;
|
|
1288
|
+
readonly ownerId: string;
|
|
1289
|
+
}
|
|
1290
|
+
export interface CancelSnapshotImportInput {
|
|
1291
|
+
readonly identity: string;
|
|
1292
|
+
readonly ownerId: string;
|
|
1293
|
+
}
|
|
1294
|
+
export declare class SnapshotImportConflictError extends Error {
|
|
1295
|
+
readonly identity: string;
|
|
1296
|
+
readonly ownerId: string;
|
|
1297
|
+
readonly name = "SnapshotImportConflictError";
|
|
1298
|
+
constructor(identity: string, ownerId: string, message: string);
|
|
1299
|
+
}
|
|
1300
|
+
/**
|
|
1301
|
+
* Persisted bytes belong to a recognized storage family, but not to the version this reader
|
|
1302
|
+
* supports. This is deliberately distinct from corruption: callers must not infer that repair,
|
|
1303
|
+
* recreation, or deletion is safe merely because versions differ.
|
|
1304
|
+
*/
|
|
1305
|
+
export declare class StorageFormatVersionError extends Error {
|
|
1306
|
+
readonly backend: string;
|
|
1307
|
+
readonly location: string;
|
|
1308
|
+
readonly actualVersion: number | null;
|
|
1309
|
+
readonly supportedVersion: number;
|
|
1310
|
+
readonly relation: "older" | "newer";
|
|
1311
|
+
readonly name = "StorageFormatVersionError";
|
|
1312
|
+
constructor(backend: string, location: string, actualVersion: number | null, supportedVersion: number, relation: "older" | "newer");
|
|
1313
|
+
}
|
|
1314
|
+
/** A native IndexedDB schema upgrade is waiting for another connection to close. */
|
|
1315
|
+
export declare class IndexedDbSchemaUpgradeBlockedError extends Error {
|
|
1316
|
+
readonly databaseName: string;
|
|
1317
|
+
readonly oldVersion: number;
|
|
1318
|
+
readonly requestedVersion: number;
|
|
1319
|
+
readonly name = "IndexedDbSchemaUpgradeBlockedError";
|
|
1320
|
+
constructor(databaseName: string, oldVersion: number, requestedVersion: number);
|
|
1321
|
+
}
|
|
1322
|
+
/** Persisted metadata or payload failed an adapter's fail-closed integrity checks. */
|
|
1323
|
+
export declare class StorageCorruptionError extends Error {
|
|
1324
|
+
readonly backend: string;
|
|
1325
|
+
readonly location: string;
|
|
1326
|
+
readonly name = "StorageCorruptionError";
|
|
1327
|
+
constructor(backend: string, location: string, message: string);
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* A remote OPFS leader may have committed a mutation whose acknowledgement was lost.
|
|
1331
|
+
* Reconcile stable identities or revisions before retrying the named operation.
|
|
1332
|
+
*/
|
|
1333
|
+
export declare class OpfsUncertainOutcomeError extends Error {
|
|
1334
|
+
readonly method: string;
|
|
1335
|
+
readonly name = "OpfsUncertainOutcomeError";
|
|
1336
|
+
constructor(method: string);
|
|
1337
|
+
}
|
|
638
1338
|
/**
|
|
639
1339
|
* The commit input carries only the change: added blocks are the transaction's journaled pending
|
|
640
1340
|
* blocks, removals are the superseded ids. The store derives the published manifest from its
|
|
@@ -645,7 +1345,22 @@ export interface CommitTransactionInput {
|
|
|
645
1345
|
changedTableIds?: readonly string[];
|
|
646
1346
|
expectedTransactionRevision: number;
|
|
647
1347
|
expectedManifestVersion: number | null;
|
|
1348
|
+
/**
|
|
1349
|
+
* Required when blocks are retired. The store atomically proves this ready compaction job is
|
|
1350
|
+
* owned by the transaction and that `removedBlockIds` exactly names its still-current,
|
|
1351
|
+
* unaliased source set. Ordinary commits cannot retire visible blocks.
|
|
1352
|
+
*/
|
|
1353
|
+
compactionJobId?: string;
|
|
648
1354
|
removedBlockIds?: readonly string[];
|
|
1355
|
+
/**
|
|
1356
|
+
* Atomic post-commit fragmentation ceilings. Exactly one entry is mandatory for every table
|
|
1357
|
+
* receiving a pending level-zero segment, no unrelated entry is allowed, and no limit may
|
|
1358
|
+
* exceed `MAX_LEVEL_ZERO_SEGMENTS`.
|
|
1359
|
+
*/
|
|
1360
|
+
levelZeroSegmentLimits?: ReadonlyArray<{
|
|
1361
|
+
tableId: string;
|
|
1362
|
+
limit: number;
|
|
1363
|
+
}>;
|
|
649
1364
|
/**
|
|
650
1365
|
* Per-table unique-key changes, in operation order. Multi-entry commits come from atomic
|
|
651
1366
|
* write scopes; entries for the same table apply sequentially, so in-scope conflicts
|
|
@@ -668,7 +1383,9 @@ export interface WriteTransactionInput extends Omit<CommitTransactionInput, "tra
|
|
|
668
1383
|
* auto-increment reservation); its journal is extended and its revision compare-and-swapped
|
|
669
1384
|
* (`TransactionRecordConflictError`). `{ record }` begins the transaction in the same step —
|
|
670
1385
|
* a fresh record (revision 0, empty journal) the store pins at `expectedManifestVersion` —
|
|
671
|
-
* so a write that needed no reservation costs one round trip in total.
|
|
1386
|
+
* so a write that needed no reservation costs one round trip in total. A fresh record carries
|
|
1387
|
+
* the `schemaEpochGuard` captured with its preparation; the store rejects a stale guard before
|
|
1388
|
+
* persisting any part of the write.
|
|
672
1389
|
*/
|
|
673
1390
|
transaction: {
|
|
674
1391
|
id: string;
|
|
@@ -685,12 +1402,188 @@ export interface UniqueKeyChanges {
|
|
|
685
1402
|
requireAbsent: boolean;
|
|
686
1403
|
remove?: boolean;
|
|
687
1404
|
}
|
|
1405
|
+
/** Bounded calls used to seed an arbitrarily large UNIQUE namespace without heap materialization. */
|
|
1406
|
+
export declare const MAX_UNIQUE_KEY_BUILD_TOKENS_PER_CHUNK = 4096;
|
|
1407
|
+
export declare const MAX_UNIQUE_KEY_BUILD_CHUNK_BYTES: number;
|
|
1408
|
+
export declare const MAX_UNIQUE_KEY_BUILD_TTL_MS: number;
|
|
1409
|
+
export declare const MAX_UNIQUE_KEY_BUILD_STAGED_BYTES: number;
|
|
1410
|
+
export declare const MAX_UNIQUE_KEY_BUILD_STAGED_BYTES_TOTAL: number;
|
|
1411
|
+
export interface UniqueKeyBuildRecord {
|
|
1412
|
+
buildId: string;
|
|
1413
|
+
tableId: string;
|
|
1414
|
+
indexId: string;
|
|
1415
|
+
namespaceId: string;
|
|
1416
|
+
ownerId: string;
|
|
1417
|
+
state: "active" | "completed";
|
|
1418
|
+
nextOrdinal: number;
|
|
1419
|
+
tokenCount: number;
|
|
1420
|
+
retainedBytes: number;
|
|
1421
|
+
expiresAt: string;
|
|
1422
|
+
createdAt: string;
|
|
1423
|
+
updatedAt: string;
|
|
1424
|
+
completedAt?: string;
|
|
1425
|
+
}
|
|
1426
|
+
export interface BeginUniqueKeyBuildInput {
|
|
1427
|
+
buildId: string;
|
|
1428
|
+
tableId: string;
|
|
1429
|
+
indexId: string;
|
|
1430
|
+
namespaceId: string;
|
|
1431
|
+
ownerId: string;
|
|
1432
|
+
expiresAt: string;
|
|
1433
|
+
createdAt: string;
|
|
1434
|
+
}
|
|
1435
|
+
export interface AppendUniqueKeyBuildChunkInput {
|
|
1436
|
+
buildId: string;
|
|
1437
|
+
ownerId: string;
|
|
1438
|
+
expiresAtCutoff: string;
|
|
1439
|
+
ordinal: number;
|
|
1440
|
+
keyTokens: readonly string[];
|
|
1441
|
+
updatedAt: string;
|
|
1442
|
+
}
|
|
1443
|
+
export interface FinishUniqueKeyBuildInput {
|
|
1444
|
+
buildId: string;
|
|
1445
|
+
ownerId: string;
|
|
1446
|
+
expiresAtCutoff: string;
|
|
1447
|
+
expectedTableRevision: number;
|
|
1448
|
+
expectedManifestVersion: number | null;
|
|
1449
|
+
chunkCount: number;
|
|
1450
|
+
coversVersion: number;
|
|
1451
|
+
completedAt: string;
|
|
1452
|
+
}
|
|
1453
|
+
export interface RenewUniqueKeyBuildInput {
|
|
1454
|
+
buildId: string;
|
|
1455
|
+
ownerId: string;
|
|
1456
|
+
expiresAtCutoff: string;
|
|
1457
|
+
expiresAt: string;
|
|
1458
|
+
updatedAt: string;
|
|
1459
|
+
}
|
|
1460
|
+
export interface AbortUniqueKeyBuildInput {
|
|
1461
|
+
buildId: string;
|
|
1462
|
+
ownerId: string;
|
|
1463
|
+
expiresAtCutoff: string;
|
|
1464
|
+
}
|
|
1465
|
+
/**
|
|
1466
|
+
* A bounded background fold of one already-enforced UNIQUE namespace. Begin freezes the exact
|
|
1467
|
+
* immutable base generation and delta prefix through `throughVersion`; later commits keep
|
|
1468
|
+
* appending canonical `(namespace, token, version)` add/remove records to a separate ordered
|
|
1469
|
+
* tail. Each step resolves at most one bounded lexical token window
|
|
1470
|
+
* into a new immutable generation. Finish swaps the generation and drops only the frozen tail
|
|
1471
|
+
* prefix atomically, so no commit copies database-sized membership and readers always see an
|
|
1472
|
+
* exact base+tail view.
|
|
1473
|
+
*/
|
|
1474
|
+
export interface UniqueKeyFoldRecord {
|
|
1475
|
+
foldId: string;
|
|
1476
|
+
tableId: string;
|
|
1477
|
+
indexId: string | null;
|
|
1478
|
+
namespaceId: string;
|
|
1479
|
+
ownerId: string;
|
|
1480
|
+
state: "active" | "completed";
|
|
1481
|
+
sourceGenerationId: string | null;
|
|
1482
|
+
outputGenerationId: string;
|
|
1483
|
+
throughVersion: number;
|
|
1484
|
+
afterToken: string | null;
|
|
1485
|
+
nextOrdinal: number;
|
|
1486
|
+
tokenCount: number;
|
|
1487
|
+
retainedBytes: number;
|
|
1488
|
+
createdAt: string;
|
|
1489
|
+
updatedAt: string;
|
|
1490
|
+
expiresAt: string;
|
|
1491
|
+
completedAt?: string;
|
|
1492
|
+
}
|
|
1493
|
+
export interface BeginUniqueKeyFoldInput {
|
|
1494
|
+
foldId: string;
|
|
1495
|
+
tableId: string;
|
|
1496
|
+
indexId: string | null;
|
|
1497
|
+
namespaceId: string;
|
|
1498
|
+
ownerId: string;
|
|
1499
|
+
outputGenerationId: string;
|
|
1500
|
+
expectedManifestVersion: number;
|
|
1501
|
+
createdAt: string;
|
|
1502
|
+
expiresAt: string;
|
|
1503
|
+
}
|
|
1504
|
+
export interface RunUniqueKeyFoldStepInput {
|
|
1505
|
+
foldId: string;
|
|
1506
|
+
ownerId: string;
|
|
1507
|
+
expiresAtCutoff: string;
|
|
1508
|
+
expiresAt: string;
|
|
1509
|
+
updatedAt: string;
|
|
1510
|
+
maxTokens: number;
|
|
1511
|
+
}
|
|
1512
|
+
export interface FinishUniqueKeyFoldInput {
|
|
1513
|
+
foldId: string;
|
|
1514
|
+
ownerId: string;
|
|
1515
|
+
expiresAtCutoff: string;
|
|
1516
|
+
expectedSourceGenerationId: string | null;
|
|
1517
|
+
expectedThroughVersion: number;
|
|
1518
|
+
chunkCount: number;
|
|
1519
|
+
completedAt: string;
|
|
1520
|
+
}
|
|
1521
|
+
export interface AbortUniqueKeyFoldInput {
|
|
1522
|
+
foldId: string;
|
|
1523
|
+
ownerId: string;
|
|
1524
|
+
expiresAtCutoff: string;
|
|
1525
|
+
}
|
|
1526
|
+
/** Validates one staged seed call before an adapter opens a transaction or WAL frame. */
|
|
1527
|
+
export declare function uniqueKeyBuildChunkRetainedBytes(keyTokens: readonly string[]): number;
|
|
1528
|
+
export declare class UniqueKeyBuildConflictError extends Error {
|
|
1529
|
+
readonly buildId: string;
|
|
1530
|
+
readonly reason: string;
|
|
1531
|
+
readonly name = "UniqueKeyBuildConflictError";
|
|
1532
|
+
constructor(buildId: string, reason: string);
|
|
1533
|
+
}
|
|
688
1534
|
/** One term's postings within a commit delta or base chunk: parallel rowId/tf arrays. */
|
|
689
1535
|
export interface FtsPosting {
|
|
690
1536
|
term: string;
|
|
691
1537
|
rowIds: bigint[];
|
|
692
1538
|
tf: number[];
|
|
693
1539
|
}
|
|
1540
|
+
export declare const MAX_POSTING_BUILD_TTL_MS: number;
|
|
1541
|
+
export interface BeginPostingBuildInput {
|
|
1542
|
+
tableId: string;
|
|
1543
|
+
columnId: string;
|
|
1544
|
+
buildId: string;
|
|
1545
|
+
ownerId: string;
|
|
1546
|
+
createdAt: string;
|
|
1547
|
+
expiresAt: string;
|
|
1548
|
+
}
|
|
1549
|
+
export interface RenewPostingBuildInput {
|
|
1550
|
+
tableId: string;
|
|
1551
|
+
columnId: string;
|
|
1552
|
+
buildId: string;
|
|
1553
|
+
ownerId: string;
|
|
1554
|
+
expiresAtCutoff: string;
|
|
1555
|
+
expiresAt: string;
|
|
1556
|
+
updatedAt: string;
|
|
1557
|
+
}
|
|
1558
|
+
export interface AppendPostingBuildChunkInput extends RenewPostingBuildInput {
|
|
1559
|
+
ordinal: number;
|
|
1560
|
+
chunk: readonly FtsPosting[];
|
|
1561
|
+
}
|
|
1562
|
+
export interface FinishPostingBuildInput {
|
|
1563
|
+
tableId: string;
|
|
1564
|
+
columnId: string;
|
|
1565
|
+
buildId: string;
|
|
1566
|
+
ownerId: string;
|
|
1567
|
+
expiresAtCutoff: string;
|
|
1568
|
+
coversVersion: number;
|
|
1569
|
+
chunkCount: number;
|
|
1570
|
+
totalTokens: number;
|
|
1571
|
+
completedAt: string;
|
|
1572
|
+
}
|
|
1573
|
+
export interface AbortPostingBuildInput {
|
|
1574
|
+
tableId: string;
|
|
1575
|
+
columnId: string;
|
|
1576
|
+
buildId: string;
|
|
1577
|
+
ownerId: string;
|
|
1578
|
+
expiresAtCutoff: string;
|
|
1579
|
+
}
|
|
1580
|
+
export declare class PostingBuildConflictError extends Error {
|
|
1581
|
+
readonly buildId: string;
|
|
1582
|
+
readonly ownerId: string;
|
|
1583
|
+
readonly reason: string;
|
|
1584
|
+
readonly name = "PostingBuildConflictError";
|
|
1585
|
+
constructor(buildId: string, ownerId: string, reason: string);
|
|
1586
|
+
}
|
|
694
1587
|
/** One indexed column's contribution from one commit: postings for the commit's new rows. */
|
|
695
1588
|
export interface FtsColumnDelta {
|
|
696
1589
|
columnId: string;
|
|
@@ -709,20 +1602,69 @@ export interface FtsChanges {
|
|
|
709
1602
|
tableId: string;
|
|
710
1603
|
columns: readonly FtsColumnDelta[];
|
|
711
1604
|
}
|
|
1605
|
+
/** In-memory and atomic-publish bounds for one transaction's accelerator/key deltas. */
|
|
1606
|
+
export declare const MAX_TRANSACTION_COMMIT_DELTA_BYTES: number;
|
|
1607
|
+
export declare const MAX_TRANSACTION_COMMIT_DELTA_ENTRIES = 1048576;
|
|
1608
|
+
export declare function transactionCommitDeltaRetainedBytes(uniqueKeyChanges: readonly UniqueKeyChanges[], ftsChanges: readonly FtsChanges[]): {
|
|
1609
|
+
bytes: number;
|
|
1610
|
+
entries: number;
|
|
1611
|
+
};
|
|
712
1612
|
/** The per-term candidate row IDs a full-text index lookup returns, aligned with the query. */
|
|
713
1613
|
export interface FtsCandidates {
|
|
714
1614
|
/** Per requested term: ascending unique row IDs whose indexed column contained the term. */
|
|
715
1615
|
rowIdsByTerm: bigint[][];
|
|
716
|
-
|
|
1616
|
+
/** The bounded read stopped before collecting every matching row; callers must scan. */
|
|
1617
|
+
overflow: boolean;
|
|
1618
|
+
}
|
|
1619
|
+
/** Aggregate row-id ceiling for one postings candidate read. Overflow falls back to a scan. */
|
|
1620
|
+
export declare const MAX_FTS_CANDIDATE_ROW_IDS = 65536;
|
|
1621
|
+
/** Query-term cardinality shared by the parser and every postings adapter boundary. */
|
|
1622
|
+
export declare const MAX_FTS_QUERY_TERMS = 32;
|
|
1623
|
+
/** Retained metadata/value ceiling for one ordered postings read. Overflow falls back to a scan. */
|
|
1624
|
+
export declare const MAX_FTS_ORDERED_READ_BYTES: number;
|
|
1625
|
+
/** Hard public mutation bounds for one streamed postings-build chunk. */
|
|
1626
|
+
export declare const MAX_FTS_POSTINGS_PER_CHUNK = 65536;
|
|
1627
|
+
export declare const MAX_FTS_POSTING_ROW_IDS_PER_CHUNK = 1048576;
|
|
1628
|
+
export declare const MAX_FTS_POSTING_TERM_CHARACTERS = 65536;
|
|
1629
|
+
/** Indexed string values are bounded; non-indexed block strings retain the physical block cap. */
|
|
1630
|
+
export declare const MAX_INDEXED_STRING_CHARACTERS = 16384;
|
|
1631
|
+
/** Maximum normalized tokens retained from one indexed document. */
|
|
1632
|
+
export declare const MAX_FTS_TOKENS_PER_DOCUMENT = 4096;
|
|
1633
|
+
/** Bounded catalog/TOC cardinality. Oversized accelerators invalidate and queries scan. */
|
|
1634
|
+
export declare const MAX_FTS_BASE_CHUNKS = 4096;
|
|
1635
|
+
export declare const MAX_FTS_DELTA_CHUNKS = 128;
|
|
1636
|
+
/** One exact/prefix term lookup or a lexicographic term range over a postings index. */
|
|
1637
|
+
export type FtsPostingQuery = {
|
|
1638
|
+
term: string;
|
|
1639
|
+
prefix: boolean;
|
|
1640
|
+
} | {
|
|
1641
|
+
lower?: string;
|
|
1642
|
+
lowerInclusive?: boolean;
|
|
1643
|
+
upper?: string;
|
|
1644
|
+
upperInclusive?: boolean;
|
|
1645
|
+
};
|
|
1646
|
+
/** Strict, bounded runtime validation shared by every adapter before any postings read. */
|
|
1647
|
+
export declare function validateFtsPostingQueries(value: unknown, label?: string): asserts value is readonly FtsPostingQuery[];
|
|
1648
|
+
/** Whether a stored term belongs to one exact, prefix, or range lookup. */
|
|
1649
|
+
export declare function ftsPostingQueryMatches(term: string, query: FtsPostingQuery): boolean;
|
|
717
1650
|
/**
|
|
718
1651
|
* Shared candidate-merge core for both stores: fetching chunks is store-specific, but the
|
|
719
1652
|
* term-match rule (exact, or prefix as a term range) and the sorted-unique row-id shape must
|
|
720
1653
|
* never drift between backends — pruning would silently differ per store.
|
|
721
1654
|
*/
|
|
722
|
-
export declare function collectFtsCandidates(chunkLists: Iterable<readonly FtsPosting[]>, terms:
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
1655
|
+
export declare function collectFtsCandidates(chunkLists: Iterable<readonly FtsPosting[]>, terms: readonly FtsPostingQuery[], maxRowIds?: number): FtsCandidates;
|
|
1656
|
+
/** Validates the fixed memory ceilings accepted by one ordered postings read. */
|
|
1657
|
+
export declare function validateFtsOrderedReadLimits(maxRowIds?: number, maxRetainedBytes?: number): void;
|
|
1658
|
+
/**
|
|
1659
|
+
* K-way merges sorted base/delta chunks into canonical term order. Only one term's row map and
|
|
1660
|
+
* one cursor per chunk stay live beyond the returned postings, avoiding a second index-sized map.
|
|
1661
|
+
*/
|
|
1662
|
+
export declare function collectFtsPostings(chunkLists: Iterable<readonly FtsPosting[]>): FtsPosting[];
|
|
1663
|
+
/** Bounded ordered merge; overflow deliberately returns no partial authoritative answer. */
|
|
1664
|
+
export declare function collectFtsPostingsBounded(chunkLists: Iterable<readonly FtsPosting[]>, maxRowIds?: number, maxRetainedBytes?: number): {
|
|
1665
|
+
postings: FtsPosting[];
|
|
1666
|
+
overflow: boolean;
|
|
1667
|
+
};
|
|
726
1668
|
/**
|
|
727
1669
|
* Shared stale-writer policy for both stores' commit steps: a commit that adds segments to a
|
|
728
1670
|
* table with active full-text columns but no covering delta flips the uncovered columns to
|
|
@@ -730,18 +1672,40 @@ export declare function collectFtsCandidates(chunkLists: Iterable<readonly FtsPo
|
|
|
730
1672
|
* Returns the updated record, or undefined when nothing changes.
|
|
731
1673
|
*/
|
|
732
1674
|
export declare function invalidateUncoveredFtsColumns(record: TableRecord, coveredColumnIds: ReadonlySet<string>): TableRecord | undefined;
|
|
1675
|
+
/**
|
|
1676
|
+
* Scalar-index half of the stale-writer rule. A writer that staged table data from catalog
|
|
1677
|
+
* metadata older than a newly building/ready index cannot provide its postings, so the commit
|
|
1678
|
+
* invalidates that index atomically. Readers then scan until a rebuild closes the gap.
|
|
1679
|
+
*/
|
|
1680
|
+
export declare function invalidateUncoveredSecondaryIndexes(record: TableRecord, coveredStorageColumnIds: ReadonlySet<string>): TableRecord | undefined;
|
|
1681
|
+
/** Physical posting IDs a current catalog record authorizes a commit to write. */
|
|
1682
|
+
export declare function activePostingStorageColumnIds(record: TableRecord): Set<string>;
|
|
733
1683
|
export declare class UniqueKeyConflictError extends Error {
|
|
734
1684
|
readonly tableId: string;
|
|
735
1685
|
readonly keyToken: string;
|
|
736
1686
|
readonly name = "UniqueKeyConflictError";
|
|
737
1687
|
constructor(tableId: string, keyToken: string);
|
|
738
1688
|
}
|
|
1689
|
+
/** A writer prepared before an enforced UNIQUE index existed and therefore cannot enforce it. */
|
|
1690
|
+
export declare class UniqueIndexCoverageError extends Error {
|
|
1691
|
+
readonly tableId: string;
|
|
1692
|
+
readonly indexName: string;
|
|
1693
|
+
readonly name = "UniqueIndexCoverageError";
|
|
1694
|
+
constructor(tableId: string, indexName: string);
|
|
1695
|
+
}
|
|
739
1696
|
export declare class WriteConflictError extends Error {
|
|
740
1697
|
readonly expectedVersion: number | null;
|
|
741
1698
|
readonly actualVersion: number | null;
|
|
742
1699
|
readonly name = "WriteConflictError";
|
|
743
1700
|
constructor(expectedVersion: number | null, actualVersion: number | null);
|
|
744
1701
|
}
|
|
1702
|
+
/** Staged write artifacts were prepared against a structurally different catalog. */
|
|
1703
|
+
export declare class SchemaConflictError extends Error {
|
|
1704
|
+
readonly expectedEpoch: number;
|
|
1705
|
+
readonly actualEpoch: number;
|
|
1706
|
+
readonly name = "SchemaConflictError";
|
|
1707
|
+
constructor(expectedEpoch: number, actualEpoch: number);
|
|
1708
|
+
}
|
|
745
1709
|
export declare class TransactionRecordConflictError extends Error {
|
|
746
1710
|
readonly transactionId: string;
|
|
747
1711
|
readonly expectedRevision: number;
|
|
@@ -759,11 +1723,45 @@ export interface TempRunPage {
|
|
|
759
1723
|
pageIndex: number;
|
|
760
1724
|
bytes: Uint8Array;
|
|
761
1725
|
}
|
|
1726
|
+
/**
|
|
1727
|
+
* Atomically adopts an unpublished compaction output left by an aborted attempt. The adapter
|
|
1728
|
+
* verifies that `segment` exactly matches the stored immutable record apart from its owner,
|
|
1729
|
+
* that the old owner is the expected aborted revision, and that the replacement is the active
|
|
1730
|
+
* transaction linked to `compactionJobId`. It then retags the segment and moves its journal
|
|
1731
|
+
* membership from the old owner to the replacement while advancing both transaction revisions.
|
|
1732
|
+
*/
|
|
1733
|
+
export interface AdoptAbortedSegmentInput {
|
|
1734
|
+
segment: SegmentRecord;
|
|
1735
|
+
expectedAbortedTransactionId: string;
|
|
1736
|
+
expectedAbortedTransactionRevision: number;
|
|
1737
|
+
replacementTransactionId: string;
|
|
1738
|
+
expectedReplacementTransactionRevision: number;
|
|
1739
|
+
compactionJobId: string;
|
|
1740
|
+
updatedAt: string;
|
|
1741
|
+
}
|
|
1742
|
+
/** Hard storage-boundary limits for one scratch-page write. */
|
|
1743
|
+
export declare const MAX_TEMP_RUN_PAGES_PER_BATCH = 64;
|
|
1744
|
+
export declare const MAX_TEMP_RUN_PAGE_BYTES: number;
|
|
1745
|
+
export declare const MAX_TEMP_RUN_BATCH_BYTES: number;
|
|
1746
|
+
/**
|
|
1747
|
+
* Refuses an oversized scratch write before an adapter starts a transaction or appends a WAL
|
|
1748
|
+
* record. Query execution splits pages and batches to these limits, so the limits bound atomic
|
|
1749
|
+
* storage work without limiting the total size of a spill.
|
|
1750
|
+
*/
|
|
1751
|
+
export declare function assertTempRunPageBatchLimits(pages: readonly TempRunPage[]): void;
|
|
762
1752
|
export interface TempOwnerRecord {
|
|
763
1753
|
ownerId: string;
|
|
1754
|
+
createdAt: string;
|
|
764
1755
|
expiresAt: string;
|
|
765
1756
|
revision: number;
|
|
766
1757
|
}
|
|
1758
|
+
export declare const MAX_TEMP_OWNER_TTL_MS: number;
|
|
1759
|
+
export interface RenewTempOwnerInput {
|
|
1760
|
+
ownerId: string;
|
|
1761
|
+
expectedRevision: number;
|
|
1762
|
+
expiresAtCutoff: string;
|
|
1763
|
+
expiresAt: string;
|
|
1764
|
+
}
|
|
767
1765
|
export declare class TempOwnerConflictError extends Error {
|
|
768
1766
|
readonly ownerId: string;
|
|
769
1767
|
readonly expectedRevision: number;
|
|
@@ -773,16 +1771,15 @@ export declare class TempOwnerConflictError extends Error {
|
|
|
773
1771
|
}
|
|
774
1772
|
/**
|
|
775
1773
|
* One coherent read of everything query preparation needs before touching blocks: the
|
|
776
|
-
* current manifest version, the named table records,
|
|
777
|
-
* and the transaction records those segments reference. Stores that can produce this in
|
|
778
|
-
*
|
|
779
|
-
* otherwise issue.
|
|
1774
|
+
* current manifest version, the named table records, current segments of the found tables,
|
|
1775
|
+
* and the transaction records those segments reference. Stores that can produce this in one
|
|
1776
|
+
* atomic read collapse the sequential per-record round trips a prepare would otherwise issue.
|
|
780
1777
|
*/
|
|
781
1778
|
export interface QueryCatalogState {
|
|
782
1779
|
manifestVersion: number | null;
|
|
783
1780
|
/** Positional per requested name; undefined where the table does not exist. */
|
|
784
1781
|
tables: Array<TableRecord | undefined>;
|
|
785
|
-
/**
|
|
1782
|
+
/** Current-manifest segments of the found tables, sorted by id. */
|
|
786
1783
|
segments: SegmentRecord[];
|
|
787
1784
|
/** Records for the segments' transaction ids; missing records are omitted. */
|
|
788
1785
|
transactions: TransactionRecord[];
|
|
@@ -794,41 +1791,106 @@ export interface QueryCatalogState {
|
|
|
794
1791
|
catalogEpoch?: number;
|
|
795
1792
|
}
|
|
796
1793
|
/**
|
|
797
|
-
* The
|
|
798
|
-
*
|
|
1794
|
+
* The change counters a reader or writer needs, read together in one atomic storage
|
|
1795
|
+
* transaction. `manifestVersion` moves on
|
|
799
1796
|
* every data commit. `catalogEpoch` moves on every catalog mutation — table creation, table
|
|
800
1797
|
* record updates (schema migration, full-text index stamps), and every manifest publish —
|
|
801
1798
|
* so an unchanged epoch proves cached catalog state is byte-identical to a fresh read.
|
|
802
1799
|
* Physical garbage collection does not move the epoch: it only deletes records that are
|
|
803
1800
|
* already invisible at every leased version, so cached state stays result-equivalent.
|
|
1801
|
+
* `schemaEpoch` is deliberately narrower: it moves only for structural catalog changes, so
|
|
1802
|
+
* writers can reject old-schema artifacts without making concurrent ordinary writes conflict.
|
|
804
1803
|
*/
|
|
805
1804
|
export interface CatalogProbe {
|
|
806
1805
|
manifestVersion: number | null;
|
|
807
1806
|
catalogEpoch: number;
|
|
1807
|
+
/** Advances only when structural catalog state changes, never for an ordinary data commit. */
|
|
1808
|
+
schemaEpoch: number;
|
|
1809
|
+
}
|
|
1810
|
+
/** Optional serializable guard for a catalog mutation whose proof read multiple records. */
|
|
1811
|
+
export interface CatalogMutationOptions {
|
|
1812
|
+
/** Reject unless the complete catalog is still at this epoch. */
|
|
1813
|
+
expectedCatalogEpoch?: number;
|
|
1814
|
+
}
|
|
1815
|
+
/** Atomic replacement fields for one catalog record. */
|
|
1816
|
+
export interface TableRecordUpdate extends CatalogMutationOptions {
|
|
1817
|
+
columns?: TableColumnRecord[];
|
|
1818
|
+
/** Replaces the full-text index state map; null clears it. */
|
|
1819
|
+
ftsColumns?: Record<string, FtsColumnIndexRecord> | null;
|
|
1820
|
+
/** Replaces the secondary-index state map; null clears it. */
|
|
1821
|
+
secondaryIndexes?: Record<string, SecondaryIndexRecord> | null;
|
|
1822
|
+
/** Additional manifest CAS used when publishing a UNIQUE build from a stable snapshot. */
|
|
1823
|
+
expectedManifestVersion?: {
|
|
1824
|
+
value: number | null;
|
|
1825
|
+
};
|
|
1826
|
+
/** Atomically seeds one secondary UNIQUE membership namespace while activating enforcement. */
|
|
1827
|
+
uniqueKeySeed?: {
|
|
1828
|
+
namespaceId: string;
|
|
1829
|
+
keyTokens: readonly string[];
|
|
1830
|
+
};
|
|
1831
|
+
/** Atomically advances a newly declared auto-increment column's durable counter. */
|
|
1832
|
+
autoIncrementSeed?: {
|
|
1833
|
+
columnId: string;
|
|
1834
|
+
atLeast: bigint;
|
|
1835
|
+
};
|
|
1836
|
+
/** Replaces the trigger list; null clears it. */
|
|
1837
|
+
triggers?: TriggerRecord[] | null;
|
|
1838
|
+
/** Replaces a view definition in place; null converts the record back to a table. */
|
|
1839
|
+
view?: TableRecord["view"] | null;
|
|
808
1840
|
}
|
|
809
1841
|
/**
|
|
810
1842
|
* Bulk payload storage: immutable, opaque byte blobs keyed by structured ids.
|
|
811
1843
|
*
|
|
812
|
-
* Blocks are
|
|
813
|
-
*
|
|
1844
|
+
* Blocks are written only through transaction staging, which creates their durable provenance
|
|
1845
|
+
* in the same atomic step and rejects duplicate ids without a partial write. Ids contain `/` separators
|
|
814
1846
|
* (`table/<uuid>/segment/<uuid>/part/000001`) and sort lexically; treat them as opaque keys.
|
|
815
1847
|
* Reads MUST return bytes the caller may mutate freely (a fresh copy or freshly deserialized
|
|
816
1848
|
* buffer), and writes MUST NOT alias the caller's buffer — the engine may reuse it.
|
|
817
1849
|
*
|
|
818
|
-
* Published blocks are retired by superseding them in a commit
|
|
819
|
-
* lease-aware
|
|
1850
|
+
* Published blocks are retired by superseding them in a commit; only the store's atomic
|
|
1851
|
+
* lease-aware collection step can physically delete payloads once no reader can reach them.
|
|
820
1852
|
*/
|
|
1853
|
+
/** Maximum manifest-membership ids accepted by one storage call. */
|
|
1854
|
+
export declare const MAX_MANIFEST_BLOCK_PRESENCE_IDS = 1024;
|
|
1855
|
+
/** Maximum UTF-16 code units in any opaque storage identity. */
|
|
1856
|
+
export declare const MAX_STORAGE_ID_CHARACTERS = 1024;
|
|
1857
|
+
/** Maximum UTF-16 code units in a persisted catalog name. */
|
|
1858
|
+
export declare const MAX_CATALOG_NAME_CHARACTERS = 1024;
|
|
1859
|
+
/** Public adapter database-name bound; names commonly become substrate keys or path segments. */
|
|
1860
|
+
export declare const MAX_STORAGE_DATABASE_NAME_CHARACTERS = 256;
|
|
1861
|
+
/** Maximum positional items accepted by one public bulk-read operation. */
|
|
1862
|
+
export declare const MAX_STORAGE_BULK_READ_ITEMS = 1024;
|
|
1863
|
+
/** Maximum aggregate payload bytes returned by one getBlocks call. */
|
|
1864
|
+
export declare const MAX_BLOCK_READ_BATCH_BYTES: number;
|
|
1865
|
+
export declare class BlockReadBatchTooLargeError extends RangeError {
|
|
1866
|
+
readonly requestedBytes: number;
|
|
1867
|
+
readonly limitBytes: number;
|
|
1868
|
+
readonly name = "BlockReadBatchTooLargeError";
|
|
1869
|
+
constructor(requestedBytes: number, limitBytes?: number);
|
|
1870
|
+
}
|
|
1871
|
+
export declare function assertStorageBulkReadItems(items: readonly unknown[], label: string): void;
|
|
1872
|
+
export declare function validateStorageId(value: unknown, label?: string): string;
|
|
1873
|
+
export declare function validateCatalogName(value: unknown, label?: string): string;
|
|
1874
|
+
export declare function validateStorageDatabaseName(value: unknown): string;
|
|
821
1875
|
export interface BlockPayloadStore {
|
|
822
|
-
addBlock(id: string, bytes: Uint8Array): Promise<void>;
|
|
823
|
-
/** All or nothing: an internal or existing duplicate id fails the whole batch unwritten. */
|
|
824
|
-
addBlocks(blocks: readonly BlockWrite[]): Promise<void>;
|
|
825
1876
|
getBlock(id: string): Promise<Uint8Array | undefined>;
|
|
826
1877
|
/** Positional per requested id; undefined where a block does not exist. */
|
|
827
1878
|
getBlocks(ids: readonly string[]): Promise<Array<Uint8Array | undefined>>;
|
|
828
|
-
/**
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
1879
|
+
/**
|
|
1880
|
+
* Reads one block only when it belongs to the exact readable manifest version. The membership
|
|
1881
|
+
* check and payload read are one storage operation: callers must never fetch a block first and
|
|
1882
|
+
* then race a separate manifest check. A missing/pruned manifest or non-member id returns
|
|
1883
|
+
* undefined. A readable member whose payload is missing or unreadable is corruption and MUST
|
|
1884
|
+
* throw StorageCorruptionError. Reader leases keep a selected version from being pruned while
|
|
1885
|
+
* it is in use.
|
|
1886
|
+
*/
|
|
1887
|
+
readManifestBlock(version: number | null, id: string): Promise<Uint8Array | undefined>;
|
|
1888
|
+
/**
|
|
1889
|
+
* Positional membership in the exact readable manifest version. Implementations must bound the
|
|
1890
|
+
* input at MAX_MANIFEST_BLOCK_PRESENCE_IDS; callers window larger sets. A missing/pruned
|
|
1891
|
+
* manifest returns false for every id.
|
|
1892
|
+
*/
|
|
1893
|
+
hasManifestBlocks(version: number | null, ids: readonly string[]): Promise<boolean[]>;
|
|
832
1894
|
}
|
|
833
1895
|
/**
|
|
834
1896
|
* The table catalog: schema records, the counters that keep writes collision-free, and
|
|
@@ -843,30 +1905,40 @@ export interface BlockPayloadStore {
|
|
|
843
1905
|
*/
|
|
844
1906
|
export interface CatalogStore {
|
|
845
1907
|
/** Fails on a duplicate id or name. Advances the catalog epoch. */
|
|
846
|
-
addTable(record: TableRecord): Promise<void>;
|
|
1908
|
+
addTable(record: TableRecord, options?: CatalogMutationOptions): Promise<void>;
|
|
847
1909
|
getTable(id: string): Promise<TableRecord | undefined>;
|
|
848
1910
|
getTableByName(name: string): Promise<TableRecord | undefined>;
|
|
849
|
-
/** Sorted by table name. */
|
|
1911
|
+
/** Sorted by table name; MAX_CATALOG_RECORDS makes this array globally bounded. */
|
|
850
1912
|
listTables(): Promise<TableRecord[]>;
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
*
|
|
1913
|
+
/**
|
|
1914
|
+
* Replaces catalog metadata atomically. When `columns` removes a column, the same operation
|
|
1915
|
+
* must also discard that column's full-text catalog entry, base chunks, and commit deltas.
|
|
1916
|
+
*/
|
|
1917
|
+
updateTable(id: string, expectedRevision: number, update: TableRecordUpdate): Promise<TableRecord>;
|
|
1918
|
+
/**
|
|
1919
|
+
* Removes a segment-free catalog object such as a view. Must refuse when any segment names the
|
|
1920
|
+
* record; populated tables use `dropTable`, whose manifest retirement and catalog removal are
|
|
1921
|
+
* inseparable. Advances the catalog epoch and fails with `TableRecordConflictError` on a stale
|
|
1922
|
+
* revision.
|
|
1923
|
+
*/
|
|
1924
|
+
removeTable(id: string, expectedRevision: number, options?: CatalogMutationOptions): Promise<void>;
|
|
1925
|
+
/**
|
|
1926
|
+
* Atomically retires all live table blocks, removes the catalog/segments/counters/indexes,
|
|
1927
|
+
* and publishes the successor manifest. A table revision mismatch throws
|
|
1928
|
+
* `TableRecordConflictError`; a manifest mismatch throws `WriteConflictError`; an active
|
|
1929
|
+
* transaction or nonterminal compaction owner throws `TableInUseError`. Any rejection leaves
|
|
1930
|
+
* the catalog, manifest, jobs, transaction journals, segments, counters, indexes, and payloads
|
|
1931
|
+
* unchanged. A success returns the one manifest summary it published.
|
|
868
1932
|
*/
|
|
869
|
-
|
|
1933
|
+
dropTable(input: DropTableInput): Promise<ManifestSummary>;
|
|
1934
|
+
/**
|
|
1935
|
+
* Atomically removes one safe non-key column from catalog metadata and every table segment,
|
|
1936
|
+
* removes its posting accelerator, and publishes a successor retiring only removed column
|
|
1937
|
+
* blocks that no remaining segment reference owns. CAS/busy errors match `dropTable`; any
|
|
1938
|
+
* rejection changes nothing, payload bytes stay available to pinned historical readers, and
|
|
1939
|
+
* success returns the exactly one published manifest summary.
|
|
1940
|
+
*/
|
|
1941
|
+
dropTableColumn(input: DropTableColumnInput): Promise<ManifestSummary>;
|
|
870
1942
|
reserveRowIds(tableId: string, count: number): Promise<RowIdRange>;
|
|
871
1943
|
/**
|
|
872
1944
|
* Atomically reserves `count` auto-increment values for the column, first bumping the
|
|
@@ -875,6 +1947,36 @@ export interface CatalogStore {
|
|
|
875
1947
|
reserveAutoIncrement(tableId: string, columnId: string, count: number, atLeast?: bigint): Promise<RowIdRange>;
|
|
876
1948
|
/** Which of the given key tokens already exist for the table, deduplicated and sorted. */
|
|
877
1949
|
getExistingUniqueKeys(tableId: string, keyTokens: readonly string[]): Promise<string[]>;
|
|
1950
|
+
/**
|
|
1951
|
+
* Starts or takes over the exact catalog-owned UNIQUE builder. One active session per namespace
|
|
1952
|
+
* and MAX_ACTIVE_UNIQUE_KEY_BUILDS globally are enforced atomically. Repeating the same active
|
|
1953
|
+
* owner/header is idempotent; an expired owner is irrevocably replaced with an empty stage.
|
|
1954
|
+
*/
|
|
1955
|
+
beginUniqueKeyBuild(input: BeginUniqueKeyBuildInput): Promise<UniqueKeyBuildRecord>;
|
|
1956
|
+
getUniqueKeyBuild(buildId: string): Promise<UniqueKeyBuildRecord | undefined>;
|
|
1957
|
+
/** Refuses at/past the cutoff, so a dead builder can never be resurrected. */
|
|
1958
|
+
renewUniqueKeyBuild(input: RenewUniqueKeyBuildInput): Promise<UniqueKeyBuildRecord>;
|
|
1959
|
+
/**
|
|
1960
|
+
* Appends the exact next ordinal. Same-ordinal lost-ack replay compares the persisted tokens
|
|
1961
|
+
* byte-for-byte; a changed replay or duplicate within/across chunks refuses without mutation.
|
|
1962
|
+
*/
|
|
1963
|
+
appendUniqueKeyBuildChunk(input: AppendUniqueKeyBuildChunkInput): Promise<UniqueKeyBuildRecord>;
|
|
1964
|
+
/**
|
|
1965
|
+
* Atomically verifies the exact building catalog owner, table+manifest CAS, completed chunk
|
|
1966
|
+
* count, and then publishes both the durable membership namespace and ready catalog state.
|
|
1967
|
+
* A same-build completed retry is a no-op; no catalog/membership intermediate state exists.
|
|
1968
|
+
*/
|
|
1969
|
+
finishUniqueKeyBuild(input: FinishUniqueKeyBuildInput): Promise<TableRecord>;
|
|
1970
|
+
/** Exact owner may abort; after expiry any caller may reclaim. Returns false when absent. */
|
|
1971
|
+
abortUniqueKeyBuild(input: AbortUniqueKeyBuildInput): Promise<boolean>;
|
|
1972
|
+
/** Starts or takes over a bounded base+tail membership fold; see `UniqueKeyFoldRecord`. */
|
|
1973
|
+
beginUniqueKeyFold?(input: BeginUniqueKeyFoldInput): Promise<UniqueKeyFoldRecord>;
|
|
1974
|
+
getUniqueKeyFold?(foldId: string): Promise<UniqueKeyFoldRecord | undefined>;
|
|
1975
|
+
/** Advances at most `maxTokens` lexical keys and renews the exact live owner. */
|
|
1976
|
+
runUniqueKeyFoldStep?(input: RunUniqueKeyFoldStepInput): Promise<UniqueKeyFoldRecord>;
|
|
1977
|
+
/** Atomically promotes the output generation and removes only the frozen delta prefix. */
|
|
1978
|
+
finishUniqueKeyFold?(input: FinishUniqueKeyFoldInput): Promise<UniqueKeyFoldRecord>;
|
|
1979
|
+
abortUniqueKeyFold?(input: AbortUniqueKeyFoldInput): Promise<boolean>;
|
|
878
1980
|
}
|
|
879
1981
|
/**
|
|
880
1982
|
* Versions and visibility: manifests (the set of live block ids at each version), segments
|
|
@@ -883,12 +1985,14 @@ export interface CatalogStore {
|
|
|
883
1985
|
*
|
|
884
1986
|
* This is where the whole consistency story lives. `commitTransaction` is THE atomic step of
|
|
885
1987
|
* the database: in one durable, all-or-nothing action it validates the transaction record's
|
|
886
|
-
* revision and active status, compare-and-swaps the
|
|
1988
|
+
* revision and active status, verifies its structural `schemaEpochGuard`, compare-and-swaps the
|
|
1989
|
+
* current manifest version, publishes the
|
|
887
1990
|
* next manifest, finalizes the transaction's segments, applies unique-key changes (failing
|
|
888
1991
|
* with `UniqueKeyConflictError` on a `requireAbsent` violation), applies full-text deltas,
|
|
889
1992
|
* and flips the transaction record to committed. No intermediate state may ever be
|
|
890
|
-
* observable, including after a crash at any moment.
|
|
891
|
-
* `
|
|
1993
|
+
* observable, including after a crash at any moment. Schema conflicts MUST be
|
|
1994
|
+
* `SchemaConflictError`, version conflicts `WriteConflictError`, and revision conflicts
|
|
1995
|
+
* `TransactionRecordConflictError` — the exact
|
|
892
1996
|
* exported classes; the engine's retry and rebase loops match on them, and the worker client
|
|
893
1997
|
* rehydrates them by name across the thread boundary.
|
|
894
1998
|
*/
|
|
@@ -897,21 +2001,30 @@ export interface TransactionStore {
|
|
|
897
2001
|
/** The current version alone, without materializing the manifest's block list. */
|
|
898
2002
|
getCurrentManifestVersion(): Promise<number | null>;
|
|
899
2003
|
getManifest(version: number): Promise<Manifest | undefined>;
|
|
900
|
-
|
|
2004
|
+
/**
|
|
2005
|
+
* Exact ID-ordered membership at one historically published version. Implementations resolve
|
|
2006
|
+
* this from interval provenance without reconstructing or cloning a complete manifest. It must
|
|
2007
|
+
* remain pageable after the summary tombstone is removed so bounded maintenance can drain the
|
|
2008
|
+
* retired payload interval; callers separately use `getManifest`/leases to authorize reads.
|
|
2009
|
+
* A version newer than the current database returns an empty page. `limit` is storage-bounded.
|
|
2010
|
+
*/
|
|
2011
|
+
listManifestBlockPage(input: ListManifestBlockPageInput): Promise<ManifestBlockPage>;
|
|
2012
|
+
/**
|
|
2013
|
+
* ID-ordered retired provenance, independent of bounded manifest-summary tombstones. This is
|
|
2014
|
+
* the durable garbage-discovery index: every record whose non-null `removedVersion` is at most
|
|
2015
|
+
* `removedThroughVersion` appears exactly once in a full cursor traversal.
|
|
2016
|
+
*/
|
|
2017
|
+
listRetiredManifestBlockPage(input: ListRetiredManifestBlockPageInput): Promise<ManifestBlockPage>;
|
|
901
2018
|
listManifestPage(afterVersion: number | null, limit: number): Promise<StoragePage<Manifest, number>>;
|
|
902
2019
|
/**
|
|
903
|
-
*
|
|
904
|
-
*
|
|
905
|
-
*
|
|
2020
|
+
* Fails on a duplicate id; the record's snapshot version and pending ids must be valid. When
|
|
2021
|
+
* an active record omits `schemaEpochGuard`, the store stamps its current structural epoch in
|
|
2022
|
+
* the same atomic creation step. A supplied stale guard throws `SchemaConflictError`.
|
|
906
2023
|
*/
|
|
907
|
-
publishManifest(input: PublishManifestInput): Promise<Manifest>;
|
|
908
|
-
/** Fails on a duplicate id; the record's snapshot version and pending ids must be valid. */
|
|
909
2024
|
createTransaction(record: TransactionRecord): Promise<void>;
|
|
910
2025
|
getTransaction(id: string): Promise<TransactionRecord | undefined>;
|
|
911
2026
|
/** Positional per requested id; undefined where a record does not exist. */
|
|
912
2027
|
getTransactions(ids: readonly string[]): Promise<Array<TransactionRecord | undefined>>;
|
|
913
|
-
/** Sorted by startedAt, then id. */
|
|
914
|
-
listTransactions(): Promise<TransactionRecord[]>;
|
|
915
2028
|
listTransactionPage(afterId: string | null, limit: number): Promise<StoragePage<TransactionRecord, string>>;
|
|
916
2029
|
/**
|
|
917
2030
|
* Compare-and-swap on `expectedRevision` (`TransactionRecordConflictError` on a mismatch).
|
|
@@ -919,13 +2032,35 @@ export interface TransactionStore {
|
|
|
919
2032
|
* committed.
|
|
920
2033
|
*/
|
|
921
2034
|
updateTransaction(id: string, expectedRevision: number, update: TransactionRecordUpdate): Promise<TransactionRecord>;
|
|
2035
|
+
/**
|
|
2036
|
+
* Extends a matching active writer's durable deadline without changing its data revision.
|
|
2037
|
+
* Returns false after ownership is lost or the transaction becomes terminal.
|
|
2038
|
+
*/
|
|
2039
|
+
renewTransaction(input: RenewTransactionInput): Promise<boolean>;
|
|
2040
|
+
/**
|
|
2041
|
+
* Atomically aborts an active transaction only when both its owner still matches and its
|
|
2042
|
+
* durable deadline is at or before the cutoff. A concurrent renewal wins by returning
|
|
2043
|
+
* undefined; a successful abort preserves artifact provenance and advances the data revision.
|
|
2044
|
+
*/
|
|
2045
|
+
abortTransactionIfExpired(input: AbortTransactionIfExpiredInput): Promise<TransactionRecord | undefined>;
|
|
922
2046
|
/** Publishes the next version; the summary omits the block list, which commits never need. */
|
|
923
2047
|
commitTransaction(input: CommitTransactionInput): Promise<ManifestSummary>;
|
|
924
|
-
addSegment(record: SegmentRecord): Promise<void>;
|
|
925
2048
|
getSegment(id: string): Promise<SegmentRecord | undefined>;
|
|
926
|
-
/** Sorted by id;
|
|
927
|
-
|
|
928
|
-
|
|
2049
|
+
/** Sorted by id, after the exclusive cursor; bounded for maintenance scans. */
|
|
2050
|
+
listSegmentPage(afterId: string | null, limit: number): Promise<StoragePage<SegmentRecord, string>>;
|
|
2051
|
+
/** Table-indexed ID page; query/compaction paths never scan unrelated segment history. */
|
|
2052
|
+
listTableSegmentPage(tableId: string, afterId: string | null, limit: number): Promise<StoragePage<SegmentRecord, string>>;
|
|
2053
|
+
/**
|
|
2054
|
+
* Removes an unpublished segment left by the exact aborted owner and unjournals it from that
|
|
2055
|
+
* transaction in the same atomic step. Returns false when the segment is already absent.
|
|
2056
|
+
* Any owner mismatch, non-aborted/missing owner, readable-manifest block reference, active
|
|
2057
|
+
* transaction pending-segment reference, or nonterminal compaction reference rejects without
|
|
2058
|
+
* mutation. A block alias in another journal is safe: this operation deletes segment metadata,
|
|
2059
|
+
* never payload bytes.
|
|
2060
|
+
*/
|
|
2061
|
+
removeAbortedSegment(id: string, expectedTransactionId: string): Promise<boolean>;
|
|
2062
|
+
/** See `AdoptAbortedSegmentInput`; returns the updated replacement transaction journal. */
|
|
2063
|
+
adoptAbortedSegment(input: AdoptAbortedSegmentInput): Promise<TransactionRecord>;
|
|
929
2064
|
}
|
|
930
2065
|
/**
|
|
931
2066
|
* Reader pins. A lease is a stored record with an expiry that protects one manifest version
|
|
@@ -935,15 +2070,28 @@ export interface TransactionStore {
|
|
|
935
2070
|
* tabs safe.
|
|
936
2071
|
*/
|
|
937
2072
|
export interface LeaseStore {
|
|
938
|
-
/**
|
|
2073
|
+
/**
|
|
2074
|
+
* Fails on a duplicate id or unavailable manifest. Before enforcing MAX_ACTIVE_LEASES, an
|
|
2075
|
+
* adapter sweeps a bounded expired page; creation and the final count check are atomic.
|
|
2076
|
+
*/
|
|
939
2077
|
createLease(record: LeaseRecord): Promise<void>;
|
|
940
2078
|
getLease(id: string): Promise<LeaseRecord | undefined>;
|
|
941
|
-
/** Sorted by id. */
|
|
2079
|
+
/** Sorted by id; MAX_ACTIVE_LEASES makes this array globally bounded. */
|
|
942
2080
|
listLeases(): Promise<LeaseRecord[]>;
|
|
943
|
-
|
|
2081
|
+
/** Bounded expiry/id-ordered page containing only records expired at the fixed cutoff. */
|
|
2082
|
+
listExpiredLeasePage(expiresAtCutoff: string, afterCursor: string | null, limit: number): Promise<StoragePage<LeaseRecord, string>>;
|
|
2083
|
+
renewLease(input: RenewLeaseInput): Promise<LeaseRecord>;
|
|
944
2084
|
/** True when removed; false (without removing) when the lease has not yet expired. */
|
|
945
2085
|
removeLeaseIfExpired(id: string, expectedRevision: number, expiresAtCutoff: string): Promise<boolean>;
|
|
946
|
-
|
|
2086
|
+
/**
|
|
2087
|
+
* Releases an existing lease only for its durable owner. A concurrent same-owner renewal may
|
|
2088
|
+
* still be removed safely; a different owner throws `LeaseOwnerConflictError` without change.
|
|
2089
|
+
* Returns false when the lease is already absent.
|
|
2090
|
+
*/
|
|
2091
|
+
removeLease(input: {
|
|
2092
|
+
id: string;
|
|
2093
|
+
ownerId: string;
|
|
2094
|
+
}): Promise<boolean>;
|
|
947
2095
|
}
|
|
948
2096
|
/**
|
|
949
2097
|
* Background-maintenance bookkeeping: the resumable job records that let compaction and
|
|
@@ -959,9 +2107,16 @@ export interface LeaseStore {
|
|
|
959
2107
|
* needs.
|
|
960
2108
|
*/
|
|
961
2109
|
export interface MaintenanceStore {
|
|
2110
|
+
/**
|
|
2111
|
+
* Atomically enforces one nonterminal job per table and MAX_ACTIVE_COMPACTION_JOBS globally;
|
|
2112
|
+
* terminal history does not count and is pruned separately.
|
|
2113
|
+
*/
|
|
962
2114
|
createCompactionJob(record: CompactionJobRecord): Promise<void>;
|
|
963
2115
|
getCompactionJob(id: string): Promise<CompactionJobRecord | undefined>;
|
|
964
|
-
/**
|
|
2116
|
+
/**
|
|
2117
|
+
* Sorted by createdAt, then id; `tableId` filters. The returned array is bounded by the
|
|
2118
|
+
* enforced active and terminal compaction-job record quotas above.
|
|
2119
|
+
*/
|
|
965
2120
|
listCompactionJobs(tableId?: string): Promise<CompactionJobRecord[]>;
|
|
966
2121
|
listCompactionJobPage(afterId: string | null, limit: number): Promise<StoragePage<CompactionJobRecord, string>>;
|
|
967
2122
|
updateCompactionJob(id: string, expectedRevision: number, update: CompactionJobRecordUpdate): Promise<CompactionJobRecord>;
|
|
@@ -971,19 +2126,33 @@ export interface MaintenanceStore {
|
|
|
971
2126
|
* cancelled and its active transaction aborted — atomically.
|
|
972
2127
|
*/
|
|
973
2128
|
cancelCompactionJob(id: string, expectedRevision: number, cancelledAt: string): Promise<CompactionJobRecord>;
|
|
974
|
-
|
|
2129
|
+
/**
|
|
2130
|
+
* Removes only published, cancelled, or aborted diagnostics. Returns false when missing or
|
|
2131
|
+
* when an existing source/output block or segment would lose its last durable provenance/root;
|
|
2132
|
+
* collection can remove that payload first. Nonterminal removal throws without mutation.
|
|
2133
|
+
*/
|
|
2134
|
+
removeCompactionJob(id: string): Promise<boolean>;
|
|
975
2135
|
/** Validates candidate provenance against persisted records before accepting the job. */
|
|
976
2136
|
createGarbageCollectionJob(input: CreateGarbageCollectionJobInput): Promise<GarbageCollectionJobRecord>;
|
|
2137
|
+
/** CAS-appends one bounded discovery page; no payload or catalog data is changed. */
|
|
2138
|
+
updateGarbageCollectionPlanning(input: UpdateGarbageCollectionPlanningInput): Promise<GarbageCollectionJobRecord>;
|
|
977
2139
|
getGarbageCollectionJob(id: string): Promise<GarbageCollectionJobRecord | undefined>;
|
|
978
|
-
/**
|
|
2140
|
+
/**
|
|
2141
|
+
* Sorted by createdAt, then id. The returned array is bounded by the enforced active and
|
|
2142
|
+
* completed garbage-collection record quotas above.
|
|
2143
|
+
*/
|
|
979
2144
|
listGarbageCollectionJobs(): Promise<GarbageCollectionJobRecord[]>;
|
|
2145
|
+
/** Bounded page sorted by id; maintenance paths use this instead of materializing history. */
|
|
2146
|
+
listGarbageCollectionJobPage(afterId: string | null, limit: number): Promise<StoragePage<GarbageCollectionJobRecord, string>>;
|
|
980
2147
|
runGarbageCollectionStep(input: RunGarbageCollectionStepInput): Promise<GarbageCollectionStepResult>;
|
|
981
2148
|
/**
|
|
982
|
-
*
|
|
983
|
-
*
|
|
984
|
-
*
|
|
2149
|
+
* Removes at most `maxItems` obsolete summary tombstones while retaining the checkpoint prefix
|
|
2150
|
+
* readable deltas need. Retired block provenance, not the summary, is durable garbage
|
|
2151
|
+
* discovery; `runGarbageCollectionStep` removes each payload and its provenance atomically, so
|
|
2152
|
+
* deleting a summary cannot strand an undiscoverable block.
|
|
985
2153
|
*/
|
|
986
|
-
removePrunedManifestRecords(): Promise<number>;
|
|
2154
|
+
removePrunedManifestRecords(maxItems: number): Promise<number>;
|
|
2155
|
+
/** Removes only a completed diagnostic; planned/running collection is refused. */
|
|
987
2156
|
removeGarbageCollectionJob(id: string): Promise<void>;
|
|
988
2157
|
}
|
|
989
2158
|
/**
|
|
@@ -993,6 +2162,12 @@ export interface MaintenanceStore {
|
|
|
993
2162
|
* indexed columns as `invalid`.
|
|
994
2163
|
*/
|
|
995
2164
|
export interface FtsIndexStore {
|
|
2165
|
+
/** Removes every base chunk and commit delta owned by one column. */
|
|
2166
|
+
/**
|
|
2167
|
+
* Removes posting storage only when the current catalog no longer owns it as a ready/building
|
|
2168
|
+
* accelerator (absent or invalid is safe). Refusal leaves catalog and postings unchanged.
|
|
2169
|
+
*/
|
|
2170
|
+
removeFtsColumn(tableId: string, columnId: string): Promise<void>;
|
|
996
2171
|
/**
|
|
997
2172
|
* Replaces one column's full-text base chunks (term-range partitioned, term-sorted within
|
|
998
2173
|
* each chunk) and deletes commit deltas the new base covers. The caller flips the catalog
|
|
@@ -1008,18 +2183,29 @@ export interface FtsIndexStore {
|
|
|
1008
2183
|
* Per-term candidate row IDs from the base chunks plus every commit delta at or below
|
|
1009
2184
|
* `upToVersion`, with the column's merged token total for exact BM25 statistics. Prefix
|
|
1010
2185
|
* terms match the term range [term, term + "\uffff"). Reports the merged delta-chunk count
|
|
1011
|
-
* so callers can schedule a rebuild when the tail grows,
|
|
2186
|
+
* so callers can schedule a rebuild when the tail grows, whether a published base exists,
|
|
2187
|
+
* and the base's covered version —
|
|
1012
2188
|
* a concurrent rebuild can publish a base ahead of a reader's snapshot, and a caller
|
|
1013
2189
|
* needing snapshot-exact statistics must detect `coversVersion > upToVersion` and fall
|
|
1014
2190
|
* back (candidates stay a safe superset either way).
|
|
1015
2191
|
*/
|
|
1016
|
-
readFtsCandidates(tableId: string, columnId: string, terms:
|
|
1017
|
-
term: string;
|
|
1018
|
-
prefix: boolean;
|
|
1019
|
-
}>, upToVersion: number): Promise<FtsCandidates & {
|
|
2192
|
+
readFtsCandidates(tableId: string, columnId: string, terms: readonly FtsPostingQuery[], upToVersion: number, maxRowIds?: number): Promise<FtsCandidates & {
|
|
1020
2193
|
deltaChunkCount: number;
|
|
1021
2194
|
totalTokens: number;
|
|
1022
2195
|
coversVersion: number;
|
|
2196
|
+
hasBase: boolean;
|
|
2197
|
+
}>;
|
|
2198
|
+
/**
|
|
2199
|
+
* Canonical term/posting order from the same snapshot-bounded base-plus-delta view. This is a
|
|
2200
|
+
* materialized cold path for ordered and covering scans; callers must not retain the result.
|
|
2201
|
+
*/
|
|
2202
|
+
readFtsPostings(tableId: string, columnId: string, upToVersion: number, maxRowIds?: number, maxRetainedBytes?: number): Promise<{
|
|
2203
|
+
postings: FtsPosting[];
|
|
2204
|
+
/** The bounded merge stopped early; callers must scan and may rebuild the accelerator. */
|
|
2205
|
+
overflow: boolean;
|
|
2206
|
+
deltaChunkCount: number;
|
|
2207
|
+
coversVersion: number;
|
|
2208
|
+
hasBase: boolean;
|
|
1023
2209
|
}>;
|
|
1024
2210
|
}
|
|
1025
2211
|
/**
|
|
@@ -1029,6 +2215,7 @@ export interface FtsIndexStore {
|
|
|
1029
2215
|
* records are real records with the usual compare-and-swap (`TempOwnerConflictError`).
|
|
1030
2216
|
*/
|
|
1031
2217
|
export interface TempSpillStore {
|
|
2218
|
+
/** Atomically enforces the per-owner run/page ceilings before storing payload bytes. */
|
|
1032
2219
|
putTempRunPage(page: TempRunPage): Promise<void>;
|
|
1033
2220
|
/**
|
|
1034
2221
|
* Optional: writes a batch of pages in one storage round trip. Callers fall back to
|
|
@@ -1040,13 +2227,16 @@ export interface TempSpillStore {
|
|
|
1040
2227
|
removeTempRun(ownerId: string, runId: string): Promise<void>;
|
|
1041
2228
|
/** Removes the owner record and every page under the owner. */
|
|
1042
2229
|
removeTempOwner(ownerId: string): Promise<void>;
|
|
2230
|
+
/** Sweeps a bounded expired page before atomically enforcing MAX_ACTIVE_TEMP_OWNERS. */
|
|
1043
2231
|
createTempOwner(record: TempOwnerRecord): Promise<void>;
|
|
1044
2232
|
getTempOwner(ownerId: string): Promise<TempOwnerRecord | undefined>;
|
|
1045
|
-
renewTempOwner(
|
|
2233
|
+
renewTempOwner(input: RenewTempOwnerInput): Promise<TempOwnerRecord>;
|
|
1046
2234
|
/** Sweeps pages too when it removes; owners found only via orphaned pages count as expired. */
|
|
1047
2235
|
removeTempOwnerIfExpired(ownerId: string, expiresAtCutoff: string): Promise<boolean>;
|
|
1048
2236
|
/** Owner ids from records and from orphaned pages alike, deduplicated, sorted, paged. */
|
|
1049
2237
|
listTempOwnerIdsPage(afterOwnerId: string | null, limit: number): Promise<StoragePage<string, string>>;
|
|
2238
|
+
/** Actual expired candidates only, ordered by expiry then owner id. */
|
|
2239
|
+
listExpiredTempOwnerPage(expiresAtCutoff: string, afterCursor: string | null, limit: number): Promise<StoragePage<string, string>>;
|
|
1050
2240
|
}
|
|
1051
2241
|
/**
|
|
1052
2242
|
* The complete storage contract: a database is `MinnowDatabase` plus one implementation of
|
|
@@ -1061,8 +2251,10 @@ export interface TempSpillStore {
|
|
|
1061
2251
|
*
|
|
1062
2252
|
* - **Atomicity.** Every method is all-or-nothing, including after a crash at any moment.
|
|
1063
2253
|
* `commitTransaction` and `runGarbageCollectionStep` mutate several record families in one
|
|
1064
|
-
* durable step. A method that resolves has happened;
|
|
1065
|
-
*
|
|
2254
|
+
* durable step. A local adapter method that resolves has happened; one that rejects has not
|
|
2255
|
+
* happened. The narrow transport-loss exception is an OPFS follower call that throws
|
|
2256
|
+
* `OpfsUncertainOutcomeError`: its prior leader may have committed the named mutation before
|
|
2257
|
+
* losing the reply, so callers must inspect/reopen instead of blindly repeating it.
|
|
1066
2258
|
* - **Conflicts are typed, by exact class.** Compare-and-swap failures throw the exported
|
|
1067
2259
|
* error classes (`WriteConflictError`, `TransactionRecordConflictError`,
|
|
1068
2260
|
* `TableRecordConflictError`, `LeaseConflictError`, `CompactionJobConflictError`,
|
|
@@ -1076,10 +2268,10 @@ export interface TempSpillStore {
|
|
|
1076
2268
|
* received records and bytes must be copied or serialized before the call resolves.
|
|
1077
2269
|
* - **Deterministic ordering.** List methods sort as documented on each capability interface;
|
|
1078
2270
|
* pagination cursors are stable under concurrent writes.
|
|
1079
|
-
* - **Optional means atomic.**
|
|
1080
|
-
* in one atomic step may say so; callers trust a present method completely and fall
|
|
1081
|
-
*
|
|
1082
|
-
* trench coat.
|
|
2271
|
+
* - **Optional means atomic.** Optional accelerator methods exist so an adapter that can do
|
|
2272
|
+
* something in one atomic step may say so; callers trust a present method completely and fall
|
|
2273
|
+
* back to safe sequential calls when it is absent. Never implement one as sequential calls in
|
|
2274
|
+
* a trench coat.
|
|
1083
2275
|
* - **Multiple connections are normal.** Several instances (tabs) may open one database.
|
|
1084
2276
|
* Readers must never block writers; competing writers must resolve through the typed
|
|
1085
2277
|
* conflicts. How is the adapter's business — storage transactions, a write-ahead log behind
|
|
@@ -1093,36 +2285,57 @@ export interface TempSpillStore {
|
|
|
1093
2285
|
*/
|
|
1094
2286
|
export interface BlockStore extends BlockPayloadStore, CatalogStore, TransactionStore, LeaseStore, MaintenanceStore, FtsIndexStore, TempSpillStore {
|
|
1095
2287
|
/**
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1098
|
-
*
|
|
2288
|
+
* Bounded builder for a postings base. Chunks stage under `buildId`; finish swaps the complete
|
|
2289
|
+
* generation into view atomically and prunes covered deltas. Beginning another build for the
|
|
2290
|
+
* same physical column reclaims an abandoned generation, so tab death cannot leak one
|
|
2291
|
+
* generation per retry. Required because an index build must never materialize one
|
|
2292
|
+
* database-sized storage value as a fallback.
|
|
2293
|
+
*/
|
|
2294
|
+
beginFtsBaseBuild(input: BeginPostingBuildInput): Promise<void>;
|
|
2295
|
+
renewFtsBaseBuild(input: RenewPostingBuildInput): Promise<void>;
|
|
2296
|
+
writeFtsBaseBuildChunk(input: AppendPostingBuildChunkInput): Promise<void>;
|
|
2297
|
+
finishFtsBaseBuild(input: FinishPostingBuildInput): Promise<void>;
|
|
2298
|
+
abortFtsBaseBuild(input: AbortPostingBuildInput): Promise<void>;
|
|
2299
|
+
/**
|
|
2300
|
+
* The current manifest version, catalog epoch, and structural schema epoch in one atomic read.
|
|
2301
|
+
* An unchanged manifest/catalog pair proves cached query state is current; the schema epoch is
|
|
2302
|
+
* the narrower write-serialization guard and does not move for ordinary commits.
|
|
2303
|
+
*/
|
|
2304
|
+
getCatalogProbe(): Promise<CatalogProbe>;
|
|
2305
|
+
/**
|
|
2306
|
+
* Optional atomic query-catalog read. The returned tables, segments, transaction owners, and
|
|
2307
|
+
* probe epoch must come from one storage snapshot; engines use the sequential stable-epoch
|
|
2308
|
+
* fallback when an adapter does not provide it.
|
|
1099
2309
|
*/
|
|
1100
|
-
|
|
2310
|
+
getQueryCatalogState?(names: readonly string[]): Promise<QueryCatalogState>;
|
|
1101
2311
|
/**
|
|
1102
|
-
*
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
2312
|
+
* Reads the current manifest and schema epoch, creates the transaction record pinned to both,
|
|
2313
|
+
* and optionally reserves row ids or an invisible pending table in one atomic storage
|
|
2314
|
+
* transaction. Required because these reservations cannot be emulated safely by sequential
|
|
2315
|
+
* calls.
|
|
1105
2316
|
*/
|
|
1106
|
-
|
|
2317
|
+
beginTransaction(input: BeginTransactionInput): Promise<BeginTransactionResult>;
|
|
1107
2318
|
/**
|
|
1108
|
-
*
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
2319
|
+
* Required atomic staging boundary: saves blocks and segments and appends their ids to the
|
|
2320
|
+
* active transaction journal in one durable operation. It is equivalent to addBlocks +
|
|
2321
|
+
* addSegment(s) + one updateTransaction only when those changes commit atomically; there is no
|
|
2322
|
+
* sequential fallback because a crash could otherwise strand bytes or publish a dangling id.
|
|
2323
|
+
* A local refusal has no effect; the documented OPFS follower uncertain-outcome error means
|
|
2324
|
+
* the complete operation may have happened and must never be converted to an ordinary error.
|
|
1111
2325
|
*/
|
|
1112
|
-
|
|
2326
|
+
stageTransactionArtifacts(input: StageTransactionArtifactsInput): Promise<TransactionRecord>;
|
|
1113
2327
|
/**
|
|
1114
|
-
*
|
|
1115
|
-
*
|
|
1116
|
-
*
|
|
1117
|
-
* crash. Callers fall back to those calls when this is absent.
|
|
2328
|
+
* Required atomic savepoint rewind. Compare-and-swaps the journal, validates retained and
|
|
2329
|
+
* removed ids as its exact duplicate-free partition, and removes only the unreachable removed
|
|
2330
|
+
* artifacts in the same durable operation. A refusal leaves both journal and bytes unchanged.
|
|
1118
2331
|
*/
|
|
1119
|
-
|
|
2332
|
+
rollbackTransactionArtifacts(input: RollbackTransactionArtifactsInput): Promise<TransactionRecord>;
|
|
1120
2333
|
/**
|
|
1121
2334
|
* Optional: the single-shot write — begin (or continue) a transaction, stage its blocks and
|
|
1122
2335
|
* segments, and commit, all in one atomic storage transaction. Must be exactly equivalent to
|
|
1123
2336
|
* `stageTransactionArtifacts` followed by `commitTransaction` (preceded by `createTransaction`
|
|
1124
2337
|
* at `expectedManifestVersion` when the input carries a fresh record): the same validation,
|
|
1125
|
-
* the same typed conflicts (`WriteConflictError`, `TransactionRecordConflictError`,
|
|
2338
|
+
* the same typed conflicts (`SchemaConflictError`, `WriteConflictError`, `TransactionRecordConflictError`,
|
|
1126
2339
|
* `UniqueKeyConflictError`), the same finalized records afterwards — and nothing at all
|
|
1127
2340
|
* written when any part refuses, including the fresh record. This is what lets a simple
|
|
1128
2341
|
* write cost one durable storage commit instead of three; callers fall back to the sequence
|
|
@@ -1133,29 +2346,52 @@ export interface BlockStore extends BlockPayloadStore, CatalogStore, Transaction
|
|
|
1133
2346
|
* Optional: re-pins a lease to another manifest version and renews it, in one atomic step —
|
|
1134
2347
|
* `createLease` at the new version plus `removeLease` of the old pin, as one round trip that
|
|
1135
2348
|
* keeps the record and its id. Compare-and-swap on `expectedRevision` (`LeaseConflictError`);
|
|
1136
|
-
* the target version's manifest must be available (`SnapshotManifestMissingError`), and a
|
|
1137
|
-
*
|
|
2349
|
+
* the target version's manifest must be available (`SnapshotManifestMissingError`), and a refused
|
|
2350
|
+
* move leaves the lease exactly as it was. An already-expired pin cannot be moved or renewed,
|
|
2351
|
+
* and the new expiry is capped by `MAX_LEASE_TTL_MS`. The engine uses it to carry its shared
|
|
1138
2352
|
* reader pin forward after each commit; callers fall back to create + remove when absent.
|
|
1139
2353
|
*/
|
|
1140
|
-
moveLease?(
|
|
2354
|
+
moveLease?(input: MoveLeaseInput): Promise<LeaseRecord>;
|
|
1141
2355
|
/**
|
|
1142
|
-
*
|
|
1143
|
-
*
|
|
1144
|
-
*
|
|
2356
|
+
* Native bounded snapshot v1. Built-in adapters implement this complete family together.
|
|
2357
|
+
* Export reads exactly one globally ordered frame at a time from a durable frozen generation;
|
|
2358
|
+
* close releases that generation and its lease. No method returns a database-sized array.
|
|
1145
2359
|
*/
|
|
1146
|
-
|
|
2360
|
+
beginSnapshotFrameExport?(input: BeginSnapshotFrameExportInput): Promise<SnapshotFrameExportSession>;
|
|
2361
|
+
readSnapshotExportFrame?(input: ReadSnapshotExportFrameInput): Promise<SnapshotFrame | undefined>;
|
|
2362
|
+
closeSnapshotFrameExport?(input: CloseSnapshotExportInput): Promise<boolean>;
|
|
1147
2363
|
/**
|
|
1148
|
-
*
|
|
1149
|
-
*
|
|
2364
|
+
* Native bounded import. Append atomically accepts only contiguous bounded frames and exact
|
|
2365
|
+
* lost-ack replay bytes. Finish validates header/footer counts, order, checksums, complete
|
|
2366
|
+
* catalog/segment/transaction/index cross-references, and atomically promotes all staged
|
|
2367
|
+
* generations; rejection leaves the current database unchanged.
|
|
1150
2368
|
*/
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
2369
|
+
beginSnapshotFrameImport?(input: BeginSnapshotFrameImportInput): Promise<SnapshotFrameImportSession>;
|
|
2370
|
+
renewSnapshotFrameImport?(input: RenewSnapshotFrameImportInput): Promise<SnapshotFrameImportSession>;
|
|
2371
|
+
appendSnapshotImportFrames?(input: AppendSnapshotImportFramesInput): Promise<SnapshotFrameImportSession>;
|
|
2372
|
+
finishSnapshotFrameImport?(input: FinishSnapshotFrameImportInput): Promise<void>;
|
|
2373
|
+
cancelSnapshotFrameImport?(input: CancelSnapshotImportInput): Promise<InterruptedSnapshotImportAbortResult>;
|
|
2374
|
+
/** Bounded, fail-closed verification of control records and optionally every live block. */
|
|
2375
|
+
checkIntegrity?(options?: {
|
|
2376
|
+
mode?: StorageIntegrityMode;
|
|
2377
|
+
maxIssues?: number;
|
|
2378
|
+
}): Promise<StorageIntegrityReport>;
|
|
2379
|
+
/** Explicit storage accounting; adapters do not run this on query or write hot paths. */
|
|
2380
|
+
getStorageStats?(): Promise<StorageStats>;
|
|
2381
|
+
/** Returns the durable marker for an unpublished snapshot import, if this adapter has one. */
|
|
2382
|
+
inspectInterruptedImport?(): Promise<InterruptedSnapshotImport | null>;
|
|
2383
|
+
/** Atomically abandons the named unpublished import and removes all staged state. */
|
|
2384
|
+
abortInterruptedImport?(identity: string): Promise<InterruptedSnapshotImportAbortResult>;
|
|
1154
2385
|
/**
|
|
1155
2386
|
* Optional: what this database's data occupies in its substrate, in bytes — the number an
|
|
1156
2387
|
* application shows a user next to the quota, and what the benchmarks report.
|
|
1157
2388
|
*/
|
|
1158
2389
|
getLogicalStorageBytes?(): Promise<number>;
|
|
2390
|
+
/**
|
|
2391
|
+
* Optional deterministic channel for commit hints between connections to the same durable
|
|
2392
|
+
* database. The engine creates the BroadcastChannel; stores only expose identity.
|
|
2393
|
+
*/
|
|
2394
|
+
readonly liveQueryChannelName?: string;
|
|
1159
2395
|
/**
|
|
1160
2396
|
* Releases whatever the connection holds (open handles, channels, timers) without flushing
|
|
1161
2397
|
* or deleting anything. Synchronous; safe to call twice. Data durability must never depend
|
|
@@ -1163,17 +2399,16 @@ export interface BlockStore extends BlockPayloadStore, CatalogStore, Transaction
|
|
|
1163
2399
|
*/
|
|
1164
2400
|
close(): void;
|
|
1165
2401
|
}
|
|
1166
|
-
export declare function createManifest(input:
|
|
1167
|
-
/**
|
|
1168
|
-
* Normalizes the additive L2 partition metadata while preserving legacy segment records verbatim.
|
|
1169
|
-
*/
|
|
2402
|
+
export declare function createManifest(input: CreateManifestInput): Manifest;
|
|
2403
|
+
/** Strictly clones the one canonical v1 segment shape. */
|
|
1170
2404
|
export declare function normalizeSegmentRecord(record: SegmentRecord): SegmentRecord;
|
|
1171
2405
|
export declare function updateTransactionRecord(record: TransactionRecord, update: TransactionRecordUpdate): TransactionRecord;
|
|
1172
2406
|
export declare function createGarbageCollectionJobRecord(input: CreateGarbageCollectionJobInput): GarbageCollectionJobRecord;
|
|
2407
|
+
export declare function normalizeGarbageCollectionDiscovery(discovery: GarbageCollectionDiscovery): GarbageCollectionDiscovery;
|
|
2408
|
+
export declare function updateGarbageCollectionPlanningRecord(record: GarbageCollectionJobRecord, input: UpdateGarbageCollectionPlanningInput): GarbageCollectionJobRecord;
|
|
1173
2409
|
export declare function normalizeGarbageCollectionJobRecord(record: GarbageCollectionJobRecord): GarbageCollectionJobRecord;
|
|
1174
2410
|
export declare function advanceGarbageCollectionJobRecord(record: GarbageCollectionJobRecord, accounting: GarbageCollectionStepAccounting): GarbageCollectionJobRecord;
|
|
1175
2411
|
export declare function normalizeCompactionJobRecord(record: CompactionJobRecord): CompactionJobRecord;
|
|
1176
2412
|
export declare function updateCompactionJobRecord(record: CompactionJobRecord, update: CompactionJobRecordUpdate): CompactionJobRecord;
|
|
1177
2413
|
/** Floors an integer-times-double product without rounding the binary double upward. */
|
|
1178
2414
|
export declare function floorWholeNumberProduct(left: number, right: number, label: string): number;
|
|
1179
|
-
//# sourceMappingURL=types.d.ts.map
|