@minnowdb/core 0.3.0 → 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 +4 -2
- 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 +0 -1
- package/dist/engine/artifact-cache.js +0 -1
- package/dist/engine/batch.d.ts +5 -2
- package/dist/engine/batch.js +0 -1
- 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 +5 -6
- package/dist/engine/catalog.js +5 -5
- package/dist/engine/client.d.ts +27 -7
- package/dist/engine/client.js +197 -31
- package/dist/engine/database.d.ts +161 -38
- package/dist/engine/database.js +4320 -1523
- package/dist/engine/defaults.d.ts +0 -1
- package/dist/engine/defaults.js +2 -4
- 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 +39 -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 -11
- package/dist/engine/index.js +12 -10
- 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 +499 -129
- 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 +4 -4
- package/dist/engine/query-api.d.ts +3 -0
- package/dist/engine/query-api.js +3 -0
- package/dist/engine/query-cache.d.ts +0 -1
- package/dist/engine/query-cache.js +4 -4
- package/dist/engine/query.d.ts +4 -7
- package/dist/engine/query.js +348 -155
- package/dist/engine/result-wire.d.ts +0 -1
- package/dist/engine/result-wire.js +2 -2
- package/dist/engine/schema-wire.d.ts +1 -2
- package/dist/engine/schema-wire.js +0 -1
- package/dist/engine/schema.d.ts +3 -8
- package/dist/engine/schema.js +41 -24
- package/dist/engine/sort-keys.d.ts +0 -1
- package/dist/engine/sort-keys.js +2 -2
- package/dist/engine/sql-domains.d.ts +6 -1
- package/dist/engine/sql-domains.js +209 -45
- package/dist/engine/sql-driver.d.ts +2 -2
- package/dist/engine/sql-driver.js +0 -1
- package/dist/engine/sql-json.d.ts +0 -1
- package/dist/engine/sql-json.js +53 -7
- package/dist/engine/sql-semantics.d.ts +8 -5
- package/dist/engine/sql-semantics.js +427 -65
- package/dist/engine/typed-live.d.ts +67 -0
- package/dist/engine/typed-live.js +349 -0
- package/dist/engine/vector.d.ts +7 -1
- package/dist/engine/vector.js +202 -58
- package/dist/engine/worker-host.d.ts +8 -2
- package/dist/engine/worker-host.js +616 -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 +0 -1
- package/dist/plan/index.js +0 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/storage/indexeddb.d.ts +74 -65
- package/dist/storage/indexeddb.js +12301 -2076
- package/dist/storage/memory.d.ts +56 -66
- package/dist/storage/memory.js +1004 -139
- 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 +403 -91
- package/dist/storage/opfs/leader.js +4306 -602
- package/dist/storage/opfs/rpc.d.ts +15 -3
- package/dist/storage/opfs/rpc.js +223 -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 +26 -121
- package/dist/storage/opfs/store.js +436 -388
- 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 -99
- package/dist/storage/snapshot.js +33 -309
- package/dist/storage/toolkit/extents.d.ts +41 -7
- package/dist/storage/toolkit/extents.js +402 -39
- package/dist/storage/toolkit/index.d.ts +3 -4
- package/dist/storage/toolkit/index.js +27 -3
- package/dist/storage/toolkit/record-core.d.ts +174 -61
- package/dist/storage/toolkit/record-core.js +5401 -849
- 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 +4 -6
- package/dist/storage/toolkit/wire.js +80 -25
- package/dist/storage/types.d.ts +1271 -218
- package/dist/storage/types.js +1471 -138
- package/dist/testing/block-store-conformance.d.ts +0 -1
- package/dist/testing/block-store-conformance.js +877 -138
- package/dist/testing/index.d.ts +42 -31
- package/dist/testing/index.js +100 -68
- package/dist/testing/opfs-shim.d.ts +13 -3
- package/dist/testing/opfs-shim.js +40 -6
- package/dist/testing/simulator.d.ts +0 -1
- package/dist/testing/simulator.js +43 -12
- package/dist/testing/sqllogictest.d.ts +0 -1
- package/dist/testing/sqllogictest.js +0 -1
- package/dist/transactions/index.d.ts +81 -20
- package/dist/transactions/index.js +1050 -268
- package/dist/worker-protocol/index.d.ts +3 -2
- package/dist/worker-protocol/index.js +2 -5
- package/package.json +49 -1
- 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-domains.d.ts.map +0 -1
- package/dist/engine/sql-domains.js.map +0 -1
- package/dist/engine/sql-driver.d.ts.map +0 -1
- package/dist/engine/sql-driver.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/testing/simulator.d.ts.map +0 -1
- package/dist/testing/simulator.js.map +0 -1
- package/dist/testing/sqllogictest.d.ts.map +0 -1
- package/dist/testing/sqllogictest.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
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { dateMilliseconds } from "../date-value.js";
|
|
2
|
+
function sameLiveValue(left, right) {
|
|
3
|
+
if (Object.is(left, right))
|
|
4
|
+
return true;
|
|
5
|
+
if (left instanceof Date || right instanceof Date) {
|
|
6
|
+
return (left instanceof Date &&
|
|
7
|
+
right instanceof Date &&
|
|
8
|
+
Object.is(dateMilliseconds(left), dateMilliseconds(right)));
|
|
9
|
+
}
|
|
10
|
+
if (Array.isArray(left) || Array.isArray(right)) {
|
|
11
|
+
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length)
|
|
12
|
+
return false;
|
|
13
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
14
|
+
if (!sameLiveValue(left[index], right[index]))
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const leftRecord = left;
|
|
23
|
+
const rightRecord = right;
|
|
24
|
+
const leftKeys = Object.keys(leftRecord);
|
|
25
|
+
const rightKeys = Object.keys(rightRecord);
|
|
26
|
+
if (leftKeys.length !== rightKeys.length)
|
|
27
|
+
return false;
|
|
28
|
+
for (let index = 0; index < leftKeys.length; index += 1) {
|
|
29
|
+
const key = leftKeys[index];
|
|
30
|
+
if (key === undefined || key !== rightKeys[index])
|
|
31
|
+
return false;
|
|
32
|
+
if (!sameLiveValue(leftRecord[key], rightRecord[key]))
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
function sameRows(left, right) {
|
|
38
|
+
return sameLiveValue(left, right);
|
|
39
|
+
}
|
|
40
|
+
function immutableRows(rows) {
|
|
41
|
+
// Adapters own their values. Copy the array so mutating the returned builder result cannot
|
|
42
|
+
// change the snapshot identity retained for exact suppression.
|
|
43
|
+
return Object.freeze([...rows]);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* One typed live SELECT. It is also a framework-neutral external store: getSnapshot is stable
|
|
47
|
+
* until state changes and subscribe returns synchronous cleanup. Slow consumers coalesce to the
|
|
48
|
+
* newest invalidation; errors retain the last good rows.
|
|
49
|
+
*/
|
|
50
|
+
export class LiveQuery {
|
|
51
|
+
#listeners = new Set();
|
|
52
|
+
#source;
|
|
53
|
+
#backend;
|
|
54
|
+
#onClose;
|
|
55
|
+
#snapshot = { status: "loading", rows: [] };
|
|
56
|
+
#subscription;
|
|
57
|
+
#observationGeneration = 0;
|
|
58
|
+
#queued;
|
|
59
|
+
#execution;
|
|
60
|
+
#executionAbort;
|
|
61
|
+
#invalidationSequence = 0;
|
|
62
|
+
#closed = false;
|
|
63
|
+
constructor(backend, source, onClose) {
|
|
64
|
+
this.#backend = backend;
|
|
65
|
+
this.#source = source;
|
|
66
|
+
this.#onClose = onClose;
|
|
67
|
+
}
|
|
68
|
+
getSnapshot = () => this.#snapshot;
|
|
69
|
+
subscribe = (listener) => {
|
|
70
|
+
if (this.#closed)
|
|
71
|
+
throw new Error("Live query is closed");
|
|
72
|
+
// A subscription is a lease, even when a framework reuses the same callback function.
|
|
73
|
+
const registered = () => listener();
|
|
74
|
+
this.#listeners.add(registered);
|
|
75
|
+
if (this.#listeners.size === 1)
|
|
76
|
+
this.#startObservation();
|
|
77
|
+
let subscribed = true;
|
|
78
|
+
return () => {
|
|
79
|
+
if (!subscribed)
|
|
80
|
+
return;
|
|
81
|
+
subscribed = false;
|
|
82
|
+
this.#listeners.delete(registered);
|
|
83
|
+
if (this.#listeners.size === 0)
|
|
84
|
+
this.#stopObservation();
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
async refresh() {
|
|
88
|
+
if (this.#closed)
|
|
89
|
+
throw new Error("Live query is closed");
|
|
90
|
+
const sequence = this.#invalidationSequence;
|
|
91
|
+
if (this.#listeners.size > 0) {
|
|
92
|
+
// A transient dependency/observer setup failure must not strand existing subscribers.
|
|
93
|
+
// Re-open first so this refresh and future commits reach the query again.
|
|
94
|
+
if (this.#subscription === undefined)
|
|
95
|
+
this.#startObservation();
|
|
96
|
+
const opening = this.#subscription;
|
|
97
|
+
if (opening !== undefined)
|
|
98
|
+
await opening.catch(() => undefined);
|
|
99
|
+
await this.#backend.refresh();
|
|
100
|
+
}
|
|
101
|
+
// A backend refresh normally invalidates observers itself. Only synthesize an execution
|
|
102
|
+
// when it did not, which preserves manual retry without running every refreshed query twice.
|
|
103
|
+
if (this.#invalidationSequence === sequence) {
|
|
104
|
+
const version = this.#snapshot.status === "loading" ? null : this.#snapshot.version;
|
|
105
|
+
this.#schedule({ manifestVersion: version, catalogEpoch: 0, initial: false });
|
|
106
|
+
}
|
|
107
|
+
await this.#waitForIdle();
|
|
108
|
+
}
|
|
109
|
+
close() {
|
|
110
|
+
if (this.#closed)
|
|
111
|
+
return;
|
|
112
|
+
this.#closed = true;
|
|
113
|
+
this.#observationGeneration += 1;
|
|
114
|
+
this.#executionAbort?.abort(new Error("Live query is closed"));
|
|
115
|
+
const subscription = this.#subscription;
|
|
116
|
+
this.#subscription = undefined;
|
|
117
|
+
if (subscription !== undefined) {
|
|
118
|
+
void subscription.then((handle) => handle.close()).catch(() => undefined);
|
|
119
|
+
}
|
|
120
|
+
// Wake iterators before removing their listeners so a parked next() terminates.
|
|
121
|
+
this.#emit();
|
|
122
|
+
this.#listeners.clear();
|
|
123
|
+
this.#onClose?.();
|
|
124
|
+
}
|
|
125
|
+
#startObservation() {
|
|
126
|
+
if (this.#subscription !== undefined || this.#closed)
|
|
127
|
+
return;
|
|
128
|
+
const generation = (this.#observationGeneration += 1);
|
|
129
|
+
const subscription = this.#backend.observe(this.#source.query, {
|
|
130
|
+
onInvalidate: (invalidation) => {
|
|
131
|
+
if (generation !== this.#observationGeneration || this.#closed)
|
|
132
|
+
return;
|
|
133
|
+
this.#schedule(invalidation);
|
|
134
|
+
},
|
|
135
|
+
onError: (error) => {
|
|
136
|
+
if (generation !== this.#observationGeneration || this.#closed)
|
|
137
|
+
return;
|
|
138
|
+
this.#setError(error, this.#currentVersion());
|
|
139
|
+
},
|
|
140
|
+
onComplete: () => {
|
|
141
|
+
if (generation !== this.#observationGeneration)
|
|
142
|
+
return;
|
|
143
|
+
this.#subscription = undefined;
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
this.#subscription = subscription;
|
|
147
|
+
subscription.catch((error) => {
|
|
148
|
+
if (generation !== this.#observationGeneration || this.#closed)
|
|
149
|
+
return;
|
|
150
|
+
this.#subscription = undefined;
|
|
151
|
+
this.#setError(error, this.#currentVersion());
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
#stopObservation() {
|
|
155
|
+
this.#observationGeneration += 1;
|
|
156
|
+
this.#executionAbort?.abort(new Error("Live query has no subscribers"));
|
|
157
|
+
const subscription = this.#subscription;
|
|
158
|
+
this.#subscription = undefined;
|
|
159
|
+
if (subscription !== undefined) {
|
|
160
|
+
void subscription.then((handle) => handle.close()).catch(() => undefined);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
#schedule(invalidation) {
|
|
164
|
+
this.#invalidationSequence += 1;
|
|
165
|
+
this.#queued = invalidation;
|
|
166
|
+
if (this.#execution !== undefined)
|
|
167
|
+
return;
|
|
168
|
+
const execution = this.#drain();
|
|
169
|
+
this.#execution = execution;
|
|
170
|
+
void execution.finally(() => {
|
|
171
|
+
if (this.#execution === execution)
|
|
172
|
+
this.#execution = undefined;
|
|
173
|
+
if (this.#queued !== undefined && !this.#closed)
|
|
174
|
+
this.#schedule(this.#queued);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
async #drain() {
|
|
178
|
+
while (this.#queued !== undefined && !this.#closed) {
|
|
179
|
+
const invalidation = this.#queued;
|
|
180
|
+
this.#queued = undefined;
|
|
181
|
+
const abort = new AbortController();
|
|
182
|
+
this.#executionAbort = abort;
|
|
183
|
+
try {
|
|
184
|
+
const rows = immutableRows(await this.#source.execute(abort.signal));
|
|
185
|
+
if (this.#executionWasCancelled(abort))
|
|
186
|
+
continue;
|
|
187
|
+
// A newer invalidation arrived while this ran. Skip the intermediate snapshot and let
|
|
188
|
+
// the loop execute once more against the newest durable state.
|
|
189
|
+
if (this.#hasQueuedInvalidation())
|
|
190
|
+
continue;
|
|
191
|
+
const previous = this.#snapshot.rows;
|
|
192
|
+
if (this.#snapshot.status === "ready" &&
|
|
193
|
+
this.#snapshot.version === invalidation.manifestVersion &&
|
|
194
|
+
sameRows(previous, rows)) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (sameRows(previous, rows) && this.#snapshot.status !== "loading") {
|
|
198
|
+
// Advance the version without replacing the immutable row array.
|
|
199
|
+
this.#snapshot = {
|
|
200
|
+
status: "ready",
|
|
201
|
+
rows: previous,
|
|
202
|
+
version: invalidation.manifestVersion,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
this.#snapshot = {
|
|
207
|
+
status: "ready",
|
|
208
|
+
rows,
|
|
209
|
+
version: invalidation.manifestVersion,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
this.#emit();
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (this.#executionWasCancelled(abort) || this.#hasQueuedInvalidation())
|
|
216
|
+
continue;
|
|
217
|
+
this.#setError(error, invalidation.manifestVersion);
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
if (this.#executionAbort === abort)
|
|
221
|
+
this.#executionAbort = undefined;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
#executionWasCancelled(abort) {
|
|
226
|
+
return abort.signal.aborted || this.#closed;
|
|
227
|
+
}
|
|
228
|
+
#hasQueuedInvalidation() {
|
|
229
|
+
return this.#queued !== undefined;
|
|
230
|
+
}
|
|
231
|
+
async #waitForIdle() {
|
|
232
|
+
for (;;) {
|
|
233
|
+
const execution = this.#execution;
|
|
234
|
+
if (execution === undefined)
|
|
235
|
+
return;
|
|
236
|
+
await execution;
|
|
237
|
+
if (this.#execution === undefined && this.#queued === undefined)
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
#currentVersion() {
|
|
242
|
+
return this.#snapshot.status === "loading" ? null : this.#snapshot.version;
|
|
243
|
+
}
|
|
244
|
+
#setError(error, version) {
|
|
245
|
+
this.#snapshot = { status: "error", rows: this.#snapshot.rows, error, version };
|
|
246
|
+
this.#emit();
|
|
247
|
+
}
|
|
248
|
+
#emit() {
|
|
249
|
+
for (const listener of [...this.#listeners]) {
|
|
250
|
+
try {
|
|
251
|
+
listener();
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// One framework listener must not prevent the others from observing the same snapshot.
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
[Symbol.asyncIterator]() {
|
|
259
|
+
const inbox = {
|
|
260
|
+
latest: this.#snapshot,
|
|
261
|
+
hasLatest: true,
|
|
262
|
+
stopped: false,
|
|
263
|
+
notify: undefined,
|
|
264
|
+
};
|
|
265
|
+
const wake = () => {
|
|
266
|
+
const notify = inbox.notify;
|
|
267
|
+
inbox.notify = undefined;
|
|
268
|
+
notify?.();
|
|
269
|
+
};
|
|
270
|
+
const unsubscribe = this.subscribe(() => {
|
|
271
|
+
inbox.latest = this.#snapshot;
|
|
272
|
+
inbox.hasLatest = true;
|
|
273
|
+
wake();
|
|
274
|
+
});
|
|
275
|
+
const done = { done: true, value: undefined };
|
|
276
|
+
const read = async () => {
|
|
277
|
+
for (;;) {
|
|
278
|
+
if (inbox.stopped || this.#closed)
|
|
279
|
+
return done;
|
|
280
|
+
if (inbox.hasLatest) {
|
|
281
|
+
inbox.hasLatest = false;
|
|
282
|
+
return { done: false, value: inbox.latest };
|
|
283
|
+
}
|
|
284
|
+
await new Promise((resolve) => {
|
|
285
|
+
inbox.notify = resolve;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
let queue = Promise.resolve();
|
|
290
|
+
return {
|
|
291
|
+
next: () => {
|
|
292
|
+
const result = queue.then(read, read);
|
|
293
|
+
queue = result.then(() => undefined, () => undefined);
|
|
294
|
+
return result;
|
|
295
|
+
},
|
|
296
|
+
return: async () => {
|
|
297
|
+
inbox.stopped = true;
|
|
298
|
+
wake();
|
|
299
|
+
unsubscribe();
|
|
300
|
+
return done;
|
|
301
|
+
},
|
|
302
|
+
throw: async (error) => {
|
|
303
|
+
inbox.stopped = true;
|
|
304
|
+
wake();
|
|
305
|
+
unsubscribe();
|
|
306
|
+
throw error;
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/** Owns one shared low-level set and every typed query created from it. */
|
|
312
|
+
export class LiveQueryManager {
|
|
313
|
+
#backend;
|
|
314
|
+
#queries = new Set();
|
|
315
|
+
#closed = false;
|
|
316
|
+
constructor(driver, options = {}) {
|
|
317
|
+
this.#backend = driver.liveQueries(options);
|
|
318
|
+
}
|
|
319
|
+
watch(source) {
|
|
320
|
+
if (this.#closed)
|
|
321
|
+
throw new Error("Live query manager is closed");
|
|
322
|
+
const query = new LiveQuery(this.#backend, source, () => {
|
|
323
|
+
this.#queries.delete(query);
|
|
324
|
+
});
|
|
325
|
+
this.#queries.add(query);
|
|
326
|
+
return query;
|
|
327
|
+
}
|
|
328
|
+
async refresh() {
|
|
329
|
+
if (this.#closed)
|
|
330
|
+
throw new Error("Live query manager is closed");
|
|
331
|
+
// The shared backend sweep remains selective. Queries that were already in an adapter-level
|
|
332
|
+
// error also run their local retry path; concurrent backend refresh calls collapse into the
|
|
333
|
+
// same low-level sweep, so this does not multiply durable probes.
|
|
334
|
+
const failed = [...this.#queries].filter((query) => query.getSnapshot().status === "error");
|
|
335
|
+
await Promise.all([this.#backend.refresh(), ...failed.map((query) => query.refresh())]);
|
|
336
|
+
}
|
|
337
|
+
async close() {
|
|
338
|
+
if (this.#closed)
|
|
339
|
+
return;
|
|
340
|
+
this.#closed = true;
|
|
341
|
+
for (const query of [...this.#queries])
|
|
342
|
+
query.close();
|
|
343
|
+
this.#queries.clear();
|
|
344
|
+
await this.#backend.close();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
export function createLiveQueryManager(driver, options = {}) {
|
|
348
|
+
return new LiveQueryManager(driver, options);
|
|
349
|
+
}
|
package/dist/engine/vector.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export interface PreparedVectorQuery {
|
|
|
52
52
|
readonly memoryUsage: QueryMemoryUsage;
|
|
53
53
|
execute(): QueryResult;
|
|
54
54
|
executeAsync(options?: AsyncQueryExecutionOptions): Promise<QueryResult>;
|
|
55
|
+
executeBatches(options: QueryBatchExecutionOptions, consume: (batch: QueryResult) => void | Promise<void>): Promise<readonly string[]>;
|
|
55
56
|
close(): void;
|
|
56
57
|
}
|
|
57
58
|
export interface QuerySpillStore {
|
|
@@ -84,6 +85,12 @@ export interface AsyncQueryExecutionOptions {
|
|
|
84
85
|
*/
|
|
85
86
|
readonly loadScanWindow?: (start: number, length: number) => number | Promise<number>;
|
|
86
87
|
}
|
|
88
|
+
export interface QueryBatchExecutionOptions extends AsyncQueryExecutionOptions {
|
|
89
|
+
/** Maximum result rows handed to the consumer at once. */
|
|
90
|
+
readonly batchRows: number;
|
|
91
|
+
/** Stops before the next scan batch and is checked after every awaited storage read. */
|
|
92
|
+
readonly signal?: AbortSignal;
|
|
93
|
+
}
|
|
87
94
|
export interface PrepareVectorQueryOptions {
|
|
88
95
|
readonly memoryContext?: QueryMemoryContext;
|
|
89
96
|
/**
|
|
@@ -99,4 +106,3 @@ export declare function columnarTableFromRows(name: string, rows: readonly Datab
|
|
|
99
106
|
export declare function prepareVectorQuery(plan: CompiledQuery, inputTables: ReadonlyMap<string, ColumnarTable>, options?: PrepareVectorQueryOptions): PreparedVectorQuery;
|
|
100
107
|
export declare function vectorValue(vector: ColumnVector, rowIndex: number): QueryValue;
|
|
101
108
|
export {};
|
|
102
|
-
//# sourceMappingURL=vector.d.ts.map
|