@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/testing/index.d.ts
CHANGED
|
@@ -1,67 +1,85 @@
|
|
|
1
|
-
import type { BlockStore,
|
|
2
|
-
export declare const faultPoints: readonly ["beforeBlockWrite", "afterBlockWrite", "beforeBlockRead", "afterBlockRead", "
|
|
1
|
+
import type { BlockStore, AdoptAbortedSegmentInput, AbortTransactionIfExpiredInput, CompactionJobRecord, CompactionJobRecordUpdate, CreateGarbageCollectionJobInput, GarbageCollectionJobRecord, GarbageCollectionStepResult, CommitTransactionInput, LeaseRecord, Manifest, ManifestSummary, CatalogProbe, RowIdRange, RenewTransactionInput, RunGarbageCollectionStepInput, RollbackTransactionArtifactsInput, SegmentRecord, StageTransactionArtifactsInput, StoragePage, TableRecord, TempOwnerRecord, TempRunPage, TransactionRecord, TransactionRecordUpdate } from "../storage/index.js";
|
|
2
|
+
export declare const faultPoints: readonly ["beforeBlockWrite", "afterBlockWrite", "beforeBlockRead", "afterBlockRead", "beforeTransactionCommit", "afterTransactionCommit"];
|
|
3
3
|
export type FaultPoint = (typeof faultPoints)[number];
|
|
4
4
|
export type FaultInjector = (point: FaultPoint) => void | Promise<void>;
|
|
5
5
|
export declare class FaultInjectingBlockStore implements BlockStore {
|
|
6
6
|
private readonly inner;
|
|
7
7
|
private readonly inject;
|
|
8
|
-
/** Present only when the inner store implements it, so callers' fallbacks stay honest. */
|
|
9
|
-
getQueryCatalogState?: (tableNames: readonly string[]) => Promise<QueryCatalogState>;
|
|
10
|
-
/** Present only when the inner store implements it, so callers' fallbacks stay honest. */
|
|
11
|
-
getCatalogProbe?: () => Promise<CatalogProbe>;
|
|
12
8
|
constructor(inner: BlockStore, inject: FaultInjector);
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
getCatalogProbe(): Promise<CatalogProbe>;
|
|
10
|
+
beginTransaction(input: Parameters<BlockStore["beginTransaction"]>[0]): ReturnType<BlockStore["beginTransaction"]>;
|
|
15
11
|
getBlock(id: string): Promise<Uint8Array | undefined>;
|
|
16
12
|
getBlocks(ids: readonly string[]): Promise<Array<Uint8Array | undefined>>;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
addTable(record: TableRecord): Promise<void>;
|
|
13
|
+
readManifestBlock(version: number | null, id: string): Promise<Uint8Array | undefined>;
|
|
14
|
+
hasManifestBlocks(version: number | null, ids: readonly string[]): Promise<boolean[]>;
|
|
15
|
+
addTable(record: TableRecord, options?: Parameters<BlockStore["addTable"]>[1]): Promise<void>;
|
|
20
16
|
getTable(id: string): Promise<TableRecord | undefined>;
|
|
21
17
|
getTableByName(name: string): Promise<TableRecord | undefined>;
|
|
22
18
|
listTables(): Promise<TableRecord[]>;
|
|
23
19
|
updateTable(id: string, expectedRevision: number, update: Parameters<BlockStore["updateTable"]>[2]): Promise<TableRecord>;
|
|
24
|
-
removeTable(id: string, expectedRevision: number): Promise<void>;
|
|
25
|
-
|
|
20
|
+
removeTable(id: string, expectedRevision: number, options?: Parameters<BlockStore["removeTable"]>[2]): Promise<void>;
|
|
21
|
+
dropTable(input: Parameters<BlockStore["dropTable"]>[0]): Promise<ManifestSummary>;
|
|
22
|
+
dropTableColumn(input: Parameters<BlockStore["dropTableColumn"]>[0]): Promise<ManifestSummary>;
|
|
26
23
|
getSegment(id: string): Promise<SegmentRecord | undefined>;
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
listSegmentPage(afterId: string | null, limit: number): Promise<StoragePage<SegmentRecord, string>>;
|
|
25
|
+
listTableSegmentPage(tableId: string, afterId: string | null, limit: number): Promise<StoragePage<SegmentRecord, string>>;
|
|
26
|
+
removeAbortedSegment(id: string, expectedTransactionId: string): Promise<boolean>;
|
|
27
|
+
adoptAbortedSegment(input: AdoptAbortedSegmentInput): Promise<TransactionRecord>;
|
|
29
28
|
reserveRowIds(tableId: string, count: number): Promise<RowIdRange>;
|
|
30
29
|
reserveAutoIncrement(tableId: string, columnId: string, count: number, atLeast?: bigint): Promise<RowIdRange>;
|
|
31
30
|
writeFtsBase(tableId: string, columnId: string, input: Parameters<BlockStore["writeFtsBase"]>[2]): Promise<void>;
|
|
31
|
+
beginFtsBaseBuild(input: Parameters<BlockStore["beginFtsBaseBuild"]>[0]): Promise<void>;
|
|
32
|
+
renewFtsBaseBuild(input: Parameters<BlockStore["renewFtsBaseBuild"]>[0]): Promise<void>;
|
|
33
|
+
writeFtsBaseBuildChunk(input: Parameters<BlockStore["writeFtsBaseBuildChunk"]>[0]): Promise<void>;
|
|
34
|
+
finishFtsBaseBuild(input: Parameters<BlockStore["finishFtsBaseBuild"]>[0]): Promise<void>;
|
|
35
|
+
abortFtsBaseBuild(input: Parameters<BlockStore["abortFtsBaseBuild"]>[0]): Promise<void>;
|
|
36
|
+
removeFtsColumn(tableId: string, columnId: string): Promise<void>;
|
|
32
37
|
readFtsCandidates(tableId: string, columnId: string, terms: Parameters<BlockStore["readFtsCandidates"]>[2], upToVersion: number): ReturnType<BlockStore["readFtsCandidates"]>;
|
|
38
|
+
readFtsPostings(tableId: string, columnId: string, upToVersion: number, maxRowIds?: number, maxRetainedBytes?: number): ReturnType<BlockStore["readFtsPostings"]>;
|
|
33
39
|
getExistingUniqueKeys(tableId: string, keyTokens: readonly string[]): Promise<string[]>;
|
|
40
|
+
beginUniqueKeyBuild(input: Parameters<BlockStore["beginUniqueKeyBuild"]>[0]): Promise<import("../storage/types.js").UniqueKeyBuildRecord>;
|
|
41
|
+
getUniqueKeyBuild(buildId: string): Promise<import("../storage/types.js").UniqueKeyBuildRecord | undefined>;
|
|
42
|
+
renewUniqueKeyBuild(input: Parameters<BlockStore["renewUniqueKeyBuild"]>[0]): Promise<import("../storage/types.js").UniqueKeyBuildRecord>;
|
|
43
|
+
appendUniqueKeyBuildChunk(input: Parameters<BlockStore["appendUniqueKeyBuildChunk"]>[0]): Promise<import("../storage/types.js").UniqueKeyBuildRecord>;
|
|
44
|
+
finishUniqueKeyBuild(input: Parameters<BlockStore["finishUniqueKeyBuild"]>[0]): Promise<TableRecord>;
|
|
45
|
+
abortUniqueKeyBuild(input: Parameters<BlockStore["abortUniqueKeyBuild"]>[0]): Promise<boolean>;
|
|
34
46
|
getCurrentManifestVersion(): Promise<number | null>;
|
|
35
47
|
getCurrentManifest(): Promise<Manifest | undefined>;
|
|
36
48
|
getManifest(version: number): Promise<Manifest | undefined>;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
listManifestBlockPage(input: Parameters<BlockStore["listManifestBlockPage"]>[0]): Promise<import("../storage/types.js").ManifestBlockPage>;
|
|
50
|
+
listRetiredManifestBlockPage(input: Parameters<BlockStore["listRetiredManifestBlockPage"]>[0]): Promise<import("../storage/types.js").ManifestBlockPage>;
|
|
51
|
+
listManifestPage(afterVersion: number | null, limit: number): Promise<StoragePage<ManifestSummary, number>>;
|
|
40
52
|
createTransaction(record: TransactionRecord): Promise<void>;
|
|
41
53
|
getTransaction(id: string): Promise<TransactionRecord | undefined>;
|
|
42
54
|
getTransactions(ids: readonly string[]): Promise<Array<TransactionRecord | undefined>>;
|
|
43
|
-
listTransactions(): Promise<TransactionRecord[]>;
|
|
44
55
|
listTransactionPage(afterId: string | null, limit: number): Promise<StoragePage<TransactionRecord, string>>;
|
|
45
56
|
updateTransaction(id: string, expectedRevision: number, update: TransactionRecordUpdate): Promise<TransactionRecord>;
|
|
57
|
+
renewTransaction(input: RenewTransactionInput): Promise<boolean>;
|
|
58
|
+
abortTransactionIfExpired(input: AbortTransactionIfExpiredInput): Promise<TransactionRecord | undefined>;
|
|
59
|
+
stageTransactionArtifacts(input: StageTransactionArtifactsInput): Promise<TransactionRecord>;
|
|
60
|
+
rollbackTransactionArtifacts(input: RollbackTransactionArtifactsInput): Promise<TransactionRecord>;
|
|
46
61
|
commitTransaction(input: CommitTransactionInput): Promise<ManifestSummary>;
|
|
47
62
|
createLease(record: LeaseRecord): Promise<void>;
|
|
48
63
|
getLease(id: string): Promise<LeaseRecord | undefined>;
|
|
49
64
|
listLeases(): Promise<LeaseRecord[]>;
|
|
50
|
-
|
|
65
|
+
listExpiredLeasePage(expiresAtCutoff: string, afterCursor: string | null, limit: number): Promise<StoragePage<LeaseRecord, string>>;
|
|
66
|
+
renewLease(input: Parameters<BlockStore["renewLease"]>[0]): Promise<LeaseRecord>;
|
|
51
67
|
removeLeaseIfExpired(id: string, expectedRevision: number, expiresAtCutoff: string): Promise<boolean>;
|
|
52
|
-
removeLease(
|
|
68
|
+
removeLease(input: Parameters<BlockStore["removeLease"]>[0]): Promise<boolean>;
|
|
53
69
|
createCompactionJob(record: CompactionJobRecord): Promise<void>;
|
|
54
70
|
getCompactionJob(id: string): Promise<CompactionJobRecord | undefined>;
|
|
55
71
|
listCompactionJobs(tableId?: string): Promise<CompactionJobRecord[]>;
|
|
56
72
|
listCompactionJobPage(afterId: string | null, limit: number): Promise<StoragePage<CompactionJobRecord, string>>;
|
|
57
73
|
updateCompactionJob(id: string, expectedRevision: number, update: CompactionJobRecordUpdate): Promise<CompactionJobRecord>;
|
|
58
74
|
cancelCompactionJob(id: string, expectedRevision: number, cancelledAt: string): Promise<CompactionJobRecord>;
|
|
59
|
-
removeCompactionJob(id: string): Promise<
|
|
75
|
+
removeCompactionJob(id: string): Promise<boolean>;
|
|
60
76
|
createGarbageCollectionJob(input: CreateGarbageCollectionJobInput): Promise<GarbageCollectionJobRecord>;
|
|
77
|
+
updateGarbageCollectionPlanning(input: Parameters<BlockStore["updateGarbageCollectionPlanning"]>[0]): Promise<GarbageCollectionJobRecord>;
|
|
61
78
|
getGarbageCollectionJob(id: string): Promise<GarbageCollectionJobRecord | undefined>;
|
|
62
79
|
listGarbageCollectionJobs(): Promise<GarbageCollectionJobRecord[]>;
|
|
80
|
+
listGarbageCollectionJobPage(afterId: string | null, limit: number): Promise<StoragePage<GarbageCollectionJobRecord, string>>;
|
|
63
81
|
runGarbageCollectionStep(input: RunGarbageCollectionStepInput): Promise<GarbageCollectionStepResult>;
|
|
64
|
-
removePrunedManifestRecords(): Promise<number>;
|
|
82
|
+
removePrunedManifestRecords(maxItems: number): Promise<number>;
|
|
65
83
|
removeGarbageCollectionJob(id: string): Promise<void>;
|
|
66
84
|
putTempRunPage(page: TempRunPage): Promise<void>;
|
|
67
85
|
getTempRunPage(ownerId: string, runId: string, pageIndex: number): Promise<Uint8Array | undefined>;
|
|
@@ -69,11 +87,13 @@ export declare class FaultInjectingBlockStore implements BlockStore {
|
|
|
69
87
|
removeTempOwner(ownerId: string): Promise<void>;
|
|
70
88
|
createTempOwner(record: TempOwnerRecord): Promise<void>;
|
|
71
89
|
getTempOwner(ownerId: string): Promise<TempOwnerRecord | undefined>;
|
|
72
|
-
renewTempOwner(
|
|
90
|
+
renewTempOwner(input: Parameters<BlockStore["renewTempOwner"]>[0]): Promise<TempOwnerRecord>;
|
|
73
91
|
removeTempOwnerIfExpired(ownerId: string, expiresAtCutoff: string): Promise<boolean>;
|
|
74
92
|
listTempOwnerIdsPage(afterOwnerId: string | null, limit: number): Promise<StoragePage<string, string>>;
|
|
93
|
+
listExpiredTempOwnerPage(expiresAtCutoff: string, afterCursor: string | null, limit: number): Promise<StoragePage<string, string>>;
|
|
75
94
|
close(): void;
|
|
76
95
|
}
|
|
77
96
|
export { blockStoreConformanceCases, runBlockStoreConformance, type BlockStoreConformanceCase, type BlockStoreConformanceTarget, } from "./block-store-conformance.js";
|
|
78
|
-
export { MemoryOpfs, type WriteFault } from "./opfs-shim.js";
|
|
79
|
-
|
|
97
|
+
export { MemoryOpfs, type TransferLimit, type WriteFault } from "./opfs-shim.js";
|
|
98
|
+
export { DeterministicScheduler, generateSimulationPlan, parseSimulationPlan, runSimulation, scheduledBlockStore, type CollectionPassSummary, type SimulationDelete, type SimulationMutation, type SimulationOptions, type SimulationPlan, type SimulationPut, type SimulationResult, type SimulationStep, type SimulationTraceEvent, } from "./simulator.js";
|
|
99
|
+
export { SqlLogicFailure, SqlLogicParseError, md5Hex, parseSqlLogicTest, parseSqlLogicTestLines, renderSqlLogicValue, runSqlLogicTest, type SqlLogicCondition, type SqlLogicDatabase, type SqlLogicExpectedHash, type SqlLogicExpectedValues, type SqlLogicHalt, type SqlLogicHashThreshold, type SqlLogicLocation, type SqlLogicQuery, type SqlLogicRecord, type SqlLogicRunStatistics, type SqlLogicRunOptions, type SqlLogicSortMode, type SqlLogicStatement, type SqlLogicType, } from "./sqllogictest.js";
|
package/dist/testing/index.js
CHANGED
|
@@ -3,39 +3,21 @@ export const faultPoints = [
|
|
|
3
3
|
"afterBlockWrite",
|
|
4
4
|
"beforeBlockRead",
|
|
5
5
|
"afterBlockRead",
|
|
6
|
-
"beforeManifestCommit",
|
|
7
|
-
"afterManifestCommit",
|
|
8
6
|
"beforeTransactionCommit",
|
|
9
7
|
"afterTransactionCommit",
|
|
10
8
|
];
|
|
11
9
|
export class FaultInjectingBlockStore {
|
|
12
10
|
inner;
|
|
13
11
|
inject;
|
|
14
|
-
/** Present only when the inner store implements it, so callers' fallbacks stay honest. */
|
|
15
|
-
getQueryCatalogState;
|
|
16
|
-
/** Present only when the inner store implements it, so callers' fallbacks stay honest. */
|
|
17
|
-
getCatalogProbe;
|
|
18
12
|
constructor(inner, inject) {
|
|
19
13
|
this.inner = inner;
|
|
20
14
|
this.inject = inject;
|
|
21
|
-
const innerCatalogState = inner.getQueryCatalogState?.bind(inner);
|
|
22
|
-
if (innerCatalogState !== undefined) {
|
|
23
|
-
this.getQueryCatalogState = (tableNames) => innerCatalogState(tableNames);
|
|
24
|
-
}
|
|
25
|
-
const innerCatalogProbe = inner.getCatalogProbe?.bind(inner);
|
|
26
|
-
if (innerCatalogProbe !== undefined) {
|
|
27
|
-
this.getCatalogProbe = () => innerCatalogProbe();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async addBlock(id, bytes) {
|
|
31
|
-
await this.inject("beforeBlockWrite");
|
|
32
|
-
await this.inner.addBlock(id, bytes);
|
|
33
|
-
await this.inject("afterBlockWrite");
|
|
34
15
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
16
|
+
getCatalogProbe() {
|
|
17
|
+
return this.inner.getCatalogProbe();
|
|
18
|
+
}
|
|
19
|
+
beginTransaction(input) {
|
|
20
|
+
return this.inner.beginTransaction(input);
|
|
39
21
|
}
|
|
40
22
|
async getBlock(id) {
|
|
41
23
|
await this.inject("beforeBlockRead");
|
|
@@ -49,14 +31,17 @@ export class FaultInjectingBlockStore {
|
|
|
49
31
|
await this.inject("afterBlockRead");
|
|
50
32
|
return blocks;
|
|
51
33
|
}
|
|
52
|
-
|
|
53
|
-
|
|
34
|
+
async readManifestBlock(version, id) {
|
|
35
|
+
await this.inject("beforeBlockRead");
|
|
36
|
+
const bytes = await this.inner.readManifestBlock(version, id);
|
|
37
|
+
await this.inject("afterBlockRead");
|
|
38
|
+
return bytes;
|
|
54
39
|
}
|
|
55
|
-
|
|
56
|
-
return this.inner.
|
|
40
|
+
hasManifestBlocks(version, ids) {
|
|
41
|
+
return this.inner.hasManifestBlocks(version, ids);
|
|
57
42
|
}
|
|
58
|
-
addTable(record) {
|
|
59
|
-
return this.inner.addTable(record);
|
|
43
|
+
addTable(record, options) {
|
|
44
|
+
return this.inner.addTable(record, options);
|
|
60
45
|
}
|
|
61
46
|
getTable(id) {
|
|
62
47
|
return this.inner.getTable(id);
|
|
@@ -70,20 +55,29 @@ export class FaultInjectingBlockStore {
|
|
|
70
55
|
updateTable(id, expectedRevision, update) {
|
|
71
56
|
return this.inner.updateTable(id, expectedRevision, update);
|
|
72
57
|
}
|
|
73
|
-
removeTable(id, expectedRevision) {
|
|
74
|
-
return this.inner.removeTable(id, expectedRevision);
|
|
58
|
+
removeTable(id, expectedRevision, options) {
|
|
59
|
+
return this.inner.removeTable(id, expectedRevision, options);
|
|
75
60
|
}
|
|
76
|
-
|
|
77
|
-
return this.inner.
|
|
61
|
+
dropTable(input) {
|
|
62
|
+
return this.inner.dropTable(input);
|
|
63
|
+
}
|
|
64
|
+
dropTableColumn(input) {
|
|
65
|
+
return this.inner.dropTableColumn(input);
|
|
78
66
|
}
|
|
79
67
|
getSegment(id) {
|
|
80
68
|
return this.inner.getSegment(id);
|
|
81
69
|
}
|
|
82
|
-
|
|
83
|
-
return this.inner.
|
|
70
|
+
listSegmentPage(afterId, limit) {
|
|
71
|
+
return this.inner.listSegmentPage(afterId, limit);
|
|
72
|
+
}
|
|
73
|
+
listTableSegmentPage(tableId, afterId, limit) {
|
|
74
|
+
return this.inner.listTableSegmentPage(tableId, afterId, limit);
|
|
84
75
|
}
|
|
85
|
-
|
|
86
|
-
return this.inner.
|
|
76
|
+
removeAbortedSegment(id, expectedTransactionId) {
|
|
77
|
+
return this.inner.removeAbortedSegment(id, expectedTransactionId);
|
|
78
|
+
}
|
|
79
|
+
adoptAbortedSegment(input) {
|
|
80
|
+
return this.inner.adoptAbortedSegment(input);
|
|
87
81
|
}
|
|
88
82
|
reserveRowIds(tableId, count) {
|
|
89
83
|
return this.inner.reserveRowIds(tableId, count);
|
|
@@ -94,12 +88,51 @@ export class FaultInjectingBlockStore {
|
|
|
94
88
|
writeFtsBase(tableId, columnId, input) {
|
|
95
89
|
return this.inner.writeFtsBase(tableId, columnId, input);
|
|
96
90
|
}
|
|
91
|
+
beginFtsBaseBuild(input) {
|
|
92
|
+
return this.inner.beginFtsBaseBuild(input);
|
|
93
|
+
}
|
|
94
|
+
renewFtsBaseBuild(input) {
|
|
95
|
+
return this.inner.renewFtsBaseBuild(input);
|
|
96
|
+
}
|
|
97
|
+
writeFtsBaseBuildChunk(input) {
|
|
98
|
+
return this.inner.writeFtsBaseBuildChunk(input);
|
|
99
|
+
}
|
|
100
|
+
finishFtsBaseBuild(input) {
|
|
101
|
+
return this.inner.finishFtsBaseBuild(input);
|
|
102
|
+
}
|
|
103
|
+
abortFtsBaseBuild(input) {
|
|
104
|
+
return this.inner.abortFtsBaseBuild(input);
|
|
105
|
+
}
|
|
106
|
+
removeFtsColumn(tableId, columnId) {
|
|
107
|
+
return this.inner.removeFtsColumn(tableId, columnId);
|
|
108
|
+
}
|
|
97
109
|
readFtsCandidates(tableId, columnId, terms, upToVersion) {
|
|
98
110
|
return this.inner.readFtsCandidates(tableId, columnId, terms, upToVersion);
|
|
99
111
|
}
|
|
112
|
+
readFtsPostings(tableId, columnId, upToVersion, maxRowIds, maxRetainedBytes) {
|
|
113
|
+
return this.inner.readFtsPostings(tableId, columnId, upToVersion, maxRowIds, maxRetainedBytes);
|
|
114
|
+
}
|
|
100
115
|
getExistingUniqueKeys(tableId, keyTokens) {
|
|
101
116
|
return this.inner.getExistingUniqueKeys(tableId, keyTokens);
|
|
102
117
|
}
|
|
118
|
+
beginUniqueKeyBuild(input) {
|
|
119
|
+
return this.inner.beginUniqueKeyBuild(input);
|
|
120
|
+
}
|
|
121
|
+
getUniqueKeyBuild(buildId) {
|
|
122
|
+
return this.inner.getUniqueKeyBuild(buildId);
|
|
123
|
+
}
|
|
124
|
+
renewUniqueKeyBuild(input) {
|
|
125
|
+
return this.inner.renewUniqueKeyBuild(input);
|
|
126
|
+
}
|
|
127
|
+
appendUniqueKeyBuildChunk(input) {
|
|
128
|
+
return this.inner.appendUniqueKeyBuildChunk(input);
|
|
129
|
+
}
|
|
130
|
+
finishUniqueKeyBuild(input) {
|
|
131
|
+
return this.inner.finishUniqueKeyBuild(input);
|
|
132
|
+
}
|
|
133
|
+
abortUniqueKeyBuild(input) {
|
|
134
|
+
return this.inner.abortUniqueKeyBuild(input);
|
|
135
|
+
}
|
|
103
136
|
getCurrentManifestVersion() {
|
|
104
137
|
return this.inner.getCurrentManifestVersion();
|
|
105
138
|
}
|
|
@@ -109,18 +142,15 @@ export class FaultInjectingBlockStore {
|
|
|
109
142
|
getManifest(version) {
|
|
110
143
|
return this.inner.getManifest(version);
|
|
111
144
|
}
|
|
112
|
-
|
|
113
|
-
return this.inner.
|
|
145
|
+
listManifestBlockPage(input) {
|
|
146
|
+
return this.inner.listManifestBlockPage(input);
|
|
147
|
+
}
|
|
148
|
+
listRetiredManifestBlockPage(input) {
|
|
149
|
+
return this.inner.listRetiredManifestBlockPage(input);
|
|
114
150
|
}
|
|
115
151
|
listManifestPage(afterVersion, limit) {
|
|
116
152
|
return this.inner.listManifestPage(afterVersion, limit);
|
|
117
153
|
}
|
|
118
|
-
async publishManifest(input) {
|
|
119
|
-
await this.inject("beforeManifestCommit");
|
|
120
|
-
const manifest = await this.inner.publishManifest(input);
|
|
121
|
-
await this.inject("afterManifestCommit");
|
|
122
|
-
return manifest;
|
|
123
|
-
}
|
|
124
154
|
createTransaction(record) {
|
|
125
155
|
return this.inner.createTransaction(record);
|
|
126
156
|
}
|
|
@@ -130,15 +160,27 @@ export class FaultInjectingBlockStore {
|
|
|
130
160
|
getTransactions(ids) {
|
|
131
161
|
return this.inner.getTransactions(ids);
|
|
132
162
|
}
|
|
133
|
-
listTransactions() {
|
|
134
|
-
return this.inner.listTransactions();
|
|
135
|
-
}
|
|
136
163
|
listTransactionPage(afterId, limit) {
|
|
137
164
|
return this.inner.listTransactionPage(afterId, limit);
|
|
138
165
|
}
|
|
139
166
|
updateTransaction(id, expectedRevision, update) {
|
|
140
167
|
return this.inner.updateTransaction(id, expectedRevision, update);
|
|
141
168
|
}
|
|
169
|
+
renewTransaction(input) {
|
|
170
|
+
return this.inner.renewTransaction(input);
|
|
171
|
+
}
|
|
172
|
+
abortTransactionIfExpired(input) {
|
|
173
|
+
return this.inner.abortTransactionIfExpired(input);
|
|
174
|
+
}
|
|
175
|
+
async stageTransactionArtifacts(input) {
|
|
176
|
+
await this.inject("beforeBlockWrite");
|
|
177
|
+
const transaction = await this.inner.stageTransactionArtifacts(input);
|
|
178
|
+
await this.inject("afterBlockWrite");
|
|
179
|
+
return transaction;
|
|
180
|
+
}
|
|
181
|
+
rollbackTransactionArtifacts(input) {
|
|
182
|
+
return this.inner.rollbackTransactionArtifacts(input);
|
|
183
|
+
}
|
|
142
184
|
async commitTransaction(input) {
|
|
143
185
|
await this.inject("beforeTransactionCommit");
|
|
144
186
|
const manifest = await this.inner.commitTransaction(input);
|
|
@@ -154,14 +196,17 @@ export class FaultInjectingBlockStore {
|
|
|
154
196
|
listLeases() {
|
|
155
197
|
return this.inner.listLeases();
|
|
156
198
|
}
|
|
157
|
-
|
|
158
|
-
return this.inner.
|
|
199
|
+
listExpiredLeasePage(expiresAtCutoff, afterCursor, limit) {
|
|
200
|
+
return this.inner.listExpiredLeasePage(expiresAtCutoff, afterCursor, limit);
|
|
201
|
+
}
|
|
202
|
+
renewLease(input) {
|
|
203
|
+
return this.inner.renewLease(input);
|
|
159
204
|
}
|
|
160
205
|
removeLeaseIfExpired(id, expectedRevision, expiresAtCutoff) {
|
|
161
206
|
return this.inner.removeLeaseIfExpired(id, expectedRevision, expiresAtCutoff);
|
|
162
207
|
}
|
|
163
|
-
removeLease(
|
|
164
|
-
return this.inner.removeLease(
|
|
208
|
+
removeLease(input) {
|
|
209
|
+
return this.inner.removeLease(input);
|
|
165
210
|
}
|
|
166
211
|
createCompactionJob(record) {
|
|
167
212
|
return this.inner.createCompactionJob(record);
|
|
@@ -187,17 +232,23 @@ export class FaultInjectingBlockStore {
|
|
|
187
232
|
createGarbageCollectionJob(input) {
|
|
188
233
|
return this.inner.createGarbageCollectionJob(input);
|
|
189
234
|
}
|
|
235
|
+
updateGarbageCollectionPlanning(input) {
|
|
236
|
+
return this.inner.updateGarbageCollectionPlanning(input);
|
|
237
|
+
}
|
|
190
238
|
getGarbageCollectionJob(id) {
|
|
191
239
|
return this.inner.getGarbageCollectionJob(id);
|
|
192
240
|
}
|
|
193
241
|
listGarbageCollectionJobs() {
|
|
194
242
|
return this.inner.listGarbageCollectionJobs();
|
|
195
243
|
}
|
|
244
|
+
listGarbageCollectionJobPage(afterId, limit) {
|
|
245
|
+
return this.inner.listGarbageCollectionJobPage(afterId, limit);
|
|
246
|
+
}
|
|
196
247
|
runGarbageCollectionStep(input) {
|
|
197
248
|
return this.inner.runGarbageCollectionStep(input);
|
|
198
249
|
}
|
|
199
|
-
removePrunedManifestRecords() {
|
|
200
|
-
return this.inner.removePrunedManifestRecords();
|
|
250
|
+
removePrunedManifestRecords(maxItems) {
|
|
251
|
+
return this.inner.removePrunedManifestRecords(maxItems);
|
|
201
252
|
}
|
|
202
253
|
removeGarbageCollectionJob(id) {
|
|
203
254
|
return this.inner.removeGarbageCollectionJob(id);
|
|
@@ -220,8 +271,8 @@ export class FaultInjectingBlockStore {
|
|
|
220
271
|
getTempOwner(ownerId) {
|
|
221
272
|
return this.inner.getTempOwner(ownerId);
|
|
222
273
|
}
|
|
223
|
-
renewTempOwner(
|
|
224
|
-
return this.inner.renewTempOwner(
|
|
274
|
+
renewTempOwner(input) {
|
|
275
|
+
return this.inner.renewTempOwner(input);
|
|
225
276
|
}
|
|
226
277
|
removeTempOwnerIfExpired(ownerId, expiresAtCutoff) {
|
|
227
278
|
return this.inner.removeTempOwnerIfExpired(ownerId, expiresAtCutoff);
|
|
@@ -229,10 +280,14 @@ export class FaultInjectingBlockStore {
|
|
|
229
280
|
listTempOwnerIdsPage(afterOwnerId, limit) {
|
|
230
281
|
return this.inner.listTempOwnerIdsPage(afterOwnerId, limit);
|
|
231
282
|
}
|
|
283
|
+
listExpiredTempOwnerPage(expiresAtCutoff, afterCursor, limit) {
|
|
284
|
+
return this.inner.listExpiredTempOwnerPage(expiresAtCutoff, afterCursor, limit);
|
|
285
|
+
}
|
|
232
286
|
close() {
|
|
233
287
|
this.inner.close();
|
|
234
288
|
}
|
|
235
289
|
}
|
|
236
290
|
export { blockStoreConformanceCases, runBlockStoreConformance, } from "./block-store-conformance.js";
|
|
237
291
|
export { MemoryOpfs } from "./opfs-shim.js";
|
|
238
|
-
|
|
292
|
+
export { DeterministicScheduler, generateSimulationPlan, parseSimulationPlan, runSimulation, scheduledBlockStore, } from "./simulator.js";
|
|
293
|
+
export { SqlLogicFailure, SqlLogicParseError, md5Hex, parseSqlLogicTest, parseSqlLogicTestLines, renderSqlLogicValue, runSqlLogicTest, } from "./sqllogictest.js";
|
|
@@ -12,24 +12,34 @@
|
|
|
12
12
|
* `InvalidModificationError`, `NoModificationAllowedError`, and injected
|
|
13
13
|
* `QuotaExceededError`s are actual `DOMException`s, since error identity is part of the
|
|
14
14
|
* storage contract.
|
|
15
|
-
* - **Injectable write faults.** `setWriteFault` throws from inside sync
|
|
16
|
-
*
|
|
15
|
+
* - **Injectable write faults and short transfers.** `setWriteFault` throws from inside sync
|
|
16
|
+
* writes, creates, or flushes; `setTransferLimit` makes reads or writes return any valid short
|
|
17
|
+
* byte count, including zero progress, at deterministic offsets.
|
|
17
18
|
*
|
|
18
19
|
* For applications, `MemoryBlockStore` remains the right store in Node tests. This shim is for
|
|
19
20
|
* adapter authors: it hosts `OpfsBlockStore` (pass `root`) or anything built on the storage
|
|
20
21
|
* toolkit's `SyncFileHandle` surface, in plain vitest, with crashes and quota failures on tap.
|
|
21
22
|
*/
|
|
22
23
|
export type WriteFault = (path: string, phase: "create" | "write" | "flush") => void;
|
|
24
|
+
export type DeleteFault = (path: string) => void;
|
|
25
|
+
export type TransferLimit = (path: string, operation: "read" | "write", requestedBytes: number, at: number) => number | undefined;
|
|
23
26
|
export declare class MemoryOpfs {
|
|
24
27
|
#private;
|
|
25
28
|
/** The tree's root, shaped like `navigator.storage.getDirectory()`'s result. */
|
|
26
29
|
get root(): FileSystemDirectoryHandle;
|
|
27
30
|
/** Installs (or clears, with `null`) a fault thrown from inside write paths. */
|
|
28
31
|
setWriteFault(fault: WriteFault | null): void;
|
|
32
|
+
/** Installs a fault at file/directory removal, for post-commit cleanup tests. */
|
|
33
|
+
setDeleteFault(fault: DeleteFault | null): void;
|
|
34
|
+
/** Limits individual sync-handle transfers so tests can deterministically exercise short I/O. */
|
|
35
|
+
setTransferLimit(limit: TransferLimit | null): void;
|
|
29
36
|
maybeFault(path: string, phase: "create" | "write" | "flush"): void;
|
|
37
|
+
maybeDeleteFault(path: string): void;
|
|
38
|
+
limitTransfer(path: string, operation: "read" | "write", requestedBytes: number, at: number): number;
|
|
30
39
|
/** Test-side peek: the file's current bytes, or undefined. Bypasses locks on purpose. */
|
|
31
40
|
readFileBytes(path: string): Uint8Array | undefined;
|
|
32
41
|
/** Test-side poke: writes bytes directly, creating parents. Bypasses locks on purpose. */
|
|
33
42
|
writeFileBytes(path: string, bytes: Uint8Array): void;
|
|
43
|
+
/** Test-side in-place corruption: existing sync handles observe the changed byte. */
|
|
44
|
+
corruptFileByte(path: string, offset: number): void;
|
|
34
45
|
}
|
|
35
|
-
//# sourceMappingURL=opfs-shim.d.ts.map
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
* `InvalidModificationError`, `NoModificationAllowedError`, and injected
|
|
13
13
|
* `QuotaExceededError`s are actual `DOMException`s, since error identity is part of the
|
|
14
14
|
* storage contract.
|
|
15
|
-
* - **Injectable write faults.** `setWriteFault` throws from inside sync
|
|
16
|
-
*
|
|
15
|
+
* - **Injectable write faults and short transfers.** `setWriteFault` throws from inside sync
|
|
16
|
+
* writes, creates, or flushes; `setTransferLimit` makes reads or writes return any valid short
|
|
17
|
+
* byte count, including zero progress, at deterministic offsets.
|
|
17
18
|
*
|
|
18
19
|
* For applications, `MemoryBlockStore` remains the right store in Node tests. This shim is for
|
|
19
20
|
* adapter authors: it hosts `OpfsBlockStore` (pass `root`) or anything built on the storage
|
|
@@ -22,6 +23,8 @@
|
|
|
22
23
|
export class MemoryOpfs {
|
|
23
24
|
#rootNode = { kind: "directory", name: "", children: new Map() };
|
|
24
25
|
#writeFault = null;
|
|
26
|
+
#deleteFault = null;
|
|
27
|
+
#transferLimit = null;
|
|
25
28
|
/** The tree's root, shaped like `navigator.storage.getDirectory()`'s result. */
|
|
26
29
|
get root() {
|
|
27
30
|
return new ShimDirectoryHandle(this, this.#rootNode, "");
|
|
@@ -30,9 +33,27 @@ export class MemoryOpfs {
|
|
|
30
33
|
setWriteFault(fault) {
|
|
31
34
|
this.#writeFault = fault;
|
|
32
35
|
}
|
|
36
|
+
/** Installs a fault at file/directory removal, for post-commit cleanup tests. */
|
|
37
|
+
setDeleteFault(fault) {
|
|
38
|
+
this.#deleteFault = fault;
|
|
39
|
+
}
|
|
40
|
+
/** Limits individual sync-handle transfers so tests can deterministically exercise short I/O. */
|
|
41
|
+
setTransferLimit(limit) {
|
|
42
|
+
this.#transferLimit = limit;
|
|
43
|
+
}
|
|
33
44
|
maybeFault(path, phase) {
|
|
34
45
|
this.#writeFault?.(path, phase);
|
|
35
46
|
}
|
|
47
|
+
maybeDeleteFault(path) {
|
|
48
|
+
this.#deleteFault?.(path);
|
|
49
|
+
}
|
|
50
|
+
limitTransfer(path, operation, requestedBytes, at) {
|
|
51
|
+
const limited = this.#transferLimit?.(path, operation, requestedBytes, at) ?? requestedBytes;
|
|
52
|
+
if (!Number.isSafeInteger(limited) || limited < 0 || limited > requestedBytes) {
|
|
53
|
+
throw new RangeError(`Invalid test transfer limit ${String(limited)} for ${String(requestedBytes)} requested bytes`);
|
|
54
|
+
}
|
|
55
|
+
return limited;
|
|
56
|
+
}
|
|
36
57
|
/** Test-side peek: the file's current bytes, or undefined. Bypasses locks on purpose. */
|
|
37
58
|
readFileBytes(path) {
|
|
38
59
|
const node = this.#find(path);
|
|
@@ -65,6 +86,16 @@ export class MemoryOpfs {
|
|
|
65
86
|
lockHolder: existing?.lockHolder ?? null,
|
|
66
87
|
});
|
|
67
88
|
}
|
|
89
|
+
/** Test-side in-place corruption: existing sync handles observe the changed byte. */
|
|
90
|
+
corruptFileByte(path, offset) {
|
|
91
|
+
const node = this.#find(path);
|
|
92
|
+
if (node?.kind !== "file")
|
|
93
|
+
throw new Error(`Not a file: ${path}`);
|
|
94
|
+
if (!Number.isSafeInteger(offset) || offset < 0 || offset >= node.bytes.byteLength) {
|
|
95
|
+
throw new RangeError(`Invalid corruption offset ${String(offset)} for ${path}`);
|
|
96
|
+
}
|
|
97
|
+
node.bytes[offset] = (node.bytes[offset] ?? 0) ^ 0xff;
|
|
98
|
+
}
|
|
68
99
|
#find(path) {
|
|
69
100
|
let node = this.#rootNode;
|
|
70
101
|
for (const segment of path.split("/").filter((segment) => segment.length > 0)) {
|
|
@@ -138,6 +169,7 @@ class ShimDirectoryHandle {
|
|
|
138
169
|
const existing = this.#node.children.get(name);
|
|
139
170
|
if (existing === undefined)
|
|
140
171
|
throw notFound(name);
|
|
172
|
+
this.#shim.maybeDeleteFault(this.#childPath(name));
|
|
141
173
|
if (existing.kind === "file") {
|
|
142
174
|
if (existing.lockHolder !== null)
|
|
143
175
|
throw locked(name);
|
|
@@ -251,7 +283,8 @@ class ShimSyncAccessHandle {
|
|
|
251
283
|
this.#assertOpen();
|
|
252
284
|
const at = options?.at ?? 0;
|
|
253
285
|
const target = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
254
|
-
const
|
|
286
|
+
const limit = this.#shim.limitTransfer(this.#path, "read", target.byteLength, at);
|
|
287
|
+
const source = this.#node.bytes.subarray(at, at + limit);
|
|
255
288
|
target.set(source);
|
|
256
289
|
return source.byteLength;
|
|
257
290
|
}
|
|
@@ -259,9 +292,11 @@ class ShimSyncAccessHandle {
|
|
|
259
292
|
this.#assertOpen();
|
|
260
293
|
this.#shim.maybeFault(this.#path, "write");
|
|
261
294
|
const at = options?.at ?? 0;
|
|
262
|
-
const
|
|
295
|
+
const requested = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
296
|
+
const limit = this.#shim.limitTransfer(this.#path, "write", requested.byteLength, at);
|
|
297
|
+
const source = requested.subarray(0, limit);
|
|
263
298
|
const end = at + source.byteLength;
|
|
264
|
-
if (end > this.#node.bytes.byteLength) {
|
|
299
|
+
if (source.byteLength > 0 && end > this.#node.bytes.byteLength) {
|
|
265
300
|
const grown = new Uint8Array(end);
|
|
266
301
|
grown.set(this.#node.bytes);
|
|
267
302
|
this.#node.bytes = grown;
|
|
@@ -292,4 +327,3 @@ class ShimSyncAccessHandle {
|
|
|
292
327
|
this.#node.lockHolder = null;
|
|
293
328
|
}
|
|
294
329
|
}
|
|
295
|
-
//# sourceMappingURL=opfs-shim.js.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type BlockStore } from "../storage/index.js";
|
|
2
|
+
import { type FaultPoint } from "./index.js";
|
|
3
|
+
export interface SimulationPut {
|
|
4
|
+
readonly kind: "put";
|
|
5
|
+
readonly client: number;
|
|
6
|
+
readonly key: number;
|
|
7
|
+
readonly amount: number;
|
|
8
|
+
}
|
|
9
|
+
export interface SimulationDelete {
|
|
10
|
+
readonly kind: "delete";
|
|
11
|
+
readonly client: number;
|
|
12
|
+
readonly key: number;
|
|
13
|
+
}
|
|
14
|
+
export type SimulationMutation = SimulationPut | SimulationDelete;
|
|
15
|
+
export type SimulationStep = {
|
|
16
|
+
readonly kind: "concurrent";
|
|
17
|
+
readonly operations: readonly SimulationMutation[];
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: "checkpoint";
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: "maintenance";
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "fault";
|
|
24
|
+
readonly point: FaultPoint;
|
|
25
|
+
readonly occurrence: number;
|
|
26
|
+
readonly operation: SimulationMutation;
|
|
27
|
+
};
|
|
28
|
+
export interface SimulationPlan {
|
|
29
|
+
readonly version: 1;
|
|
30
|
+
readonly seed: number;
|
|
31
|
+
readonly clients: number;
|
|
32
|
+
readonly keySpace: number;
|
|
33
|
+
readonly steps: readonly SimulationStep[];
|
|
34
|
+
}
|
|
35
|
+
export interface SimulationTraceEvent {
|
|
36
|
+
readonly sequence: number;
|
|
37
|
+
readonly operation: string;
|
|
38
|
+
readonly outcome: "resolved" | "rejected";
|
|
39
|
+
}
|
|
40
|
+
export interface SimulationResult {
|
|
41
|
+
readonly seed: number;
|
|
42
|
+
readonly acceptedMutations: number;
|
|
43
|
+
readonly rejectedConflicts: number;
|
|
44
|
+
readonly injectedFaults: number;
|
|
45
|
+
readonly checkpoints: number;
|
|
46
|
+
readonly maintenanceCompactions: number;
|
|
47
|
+
readonly compactionStop: string;
|
|
48
|
+
readonly collectionPasses: number;
|
|
49
|
+
readonly collectionTail: readonly CollectionPassSummary[];
|
|
50
|
+
readonly rows: ReadonlyArray<{
|
|
51
|
+
readonly id: number;
|
|
52
|
+
readonly client: number;
|
|
53
|
+
readonly amount: number;
|
|
54
|
+
}>;
|
|
55
|
+
readonly blockCount: number;
|
|
56
|
+
readonly segmentCount: number;
|
|
57
|
+
readonly transactionCount: number;
|
|
58
|
+
readonly manifestCount: number;
|
|
59
|
+
readonly leaseCount: number;
|
|
60
|
+
readonly storageBytes: number;
|
|
61
|
+
readonly schedulerHighWater: number;
|
|
62
|
+
readonly trace: readonly SimulationTraceEvent[];
|
|
63
|
+
readonly traceDigest: string;
|
|
64
|
+
}
|
|
65
|
+
export interface SimulationOptions {
|
|
66
|
+
/** Bounded diagnostic tail; old events are evicted as the simulator runs. */
|
|
67
|
+
readonly traceEvents?: number;
|
|
68
|
+
}
|
|
69
|
+
export interface CollectionPassSummary {
|
|
70
|
+
readonly prunedManifests: number;
|
|
71
|
+
readonly retainedManifests: number;
|
|
72
|
+
readonly reclaimedSegments: number;
|
|
73
|
+
readonly retainedSegments: number;
|
|
74
|
+
readonly reclaimedBlocks: number;
|
|
75
|
+
readonly retainedBlocks: number;
|
|
76
|
+
readonly reclaimedTransactions: number;
|
|
77
|
+
readonly retainedTransactions: number;
|
|
78
|
+
}
|
|
79
|
+
/** Chooses every storage completion from a seeded queue and keeps only a bounded trace tail. */
|
|
80
|
+
export declare class DeterministicScheduler {
|
|
81
|
+
#private;
|
|
82
|
+
constructor(seed: number, traceLimit?: number);
|
|
83
|
+
get highWater(): number;
|
|
84
|
+
get trace(): readonly SimulationTraceEvent[];
|
|
85
|
+
schedule<T>(label: string, run: () => Promise<T>): Promise<T>;
|
|
86
|
+
settle<T>(promises: ReadonlyArray<Promise<T>>): Promise<Array<PromiseSettledResult<T>>>;
|
|
87
|
+
}
|
|
88
|
+
/** Wraps every asynchronous BlockStore entry point in the deterministic completion scheduler. */
|
|
89
|
+
export declare function scheduledBlockStore(store: BlockStore, scheduler: DeterministicScheduler): BlockStore;
|
|
90
|
+
export declare function generateSimulationPlan(seed: number, options?: {
|
|
91
|
+
readonly rounds?: number;
|
|
92
|
+
readonly clients?: number;
|
|
93
|
+
readonly keySpace?: number;
|
|
94
|
+
}): SimulationPlan;
|
|
95
|
+
export declare function parseSimulationPlan(source: string): SimulationPlan;
|
|
96
|
+
/** Runs a replayable state-machine plan through production SQL, transactions, and block storage. */
|
|
97
|
+
export declare function runSimulation(plan: SimulationPlan, options?: SimulationOptions): Promise<SimulationResult>;
|