@quereus/store 4.14.0 → 4.16.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 +761 -702
- package/dist/src/common/cost-profile.d.ts +32 -0
- package/dist/src/common/cost-profile.d.ts.map +1 -1
- package/dist/src/common/cost-profile.js +30 -0
- package/dist/src/common/cost-profile.js.map +1 -1
- package/dist/src/common/events.d.ts +18 -28
- package/dist/src/common/events.d.ts.map +1 -1
- package/dist/src/common/events.js.map +1 -1
- package/dist/src/common/index.d.ts +1 -0
- package/dist/src/common/index.d.ts.map +1 -1
- package/dist/src/common/index.js +5 -0
- package/dist/src/common/index.js.map +1 -1
- package/dist/src/common/memory-store.d.ts +9 -0
- package/dist/src/common/memory-store.d.ts.map +1 -1
- package/dist/src/common/memory-store.js +11 -0
- package/dist/src/common/memory-store.js.map +1 -1
- package/dist/src/common/pk-key-resolution.d.ts +34 -0
- package/dist/src/common/pk-key-resolution.d.ts.map +1 -1
- package/dist/src/common/pk-key-resolution.js +47 -0
- package/dist/src/common/pk-key-resolution.js.map +1 -1
- package/dist/src/common/store-module-access-plan.d.ts +8 -0
- package/dist/src/common/store-module-access-plan.d.ts.map +1 -1
- package/dist/src/common/store-module-access-plan.js +362 -19
- package/dist/src/common/store-module-access-plan.js.map +1 -1
- package/dist/src/common/store-module-alter.d.ts.map +1 -1
- package/dist/src/common/store-module-alter.js +2 -3
- package/dist/src/common/store-module-alter.js.map +1 -1
- package/dist/src/common/store-module-schema-sync.d.ts.map +1 -1
- package/dist/src/common/store-module-schema-sync.js +6 -0
- package/dist/src/common/store-module-schema-sync.js.map +1 -1
- package/dist/src/common/store-table-scan.d.ts.map +1 -1
- package/dist/src/common/store-table-scan.js +19 -1
- package/dist/src/common/store-table-scan.js.map +1 -1
- package/dist/src/testing/index.d.ts +12 -0
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/index.js +12 -0
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/testing/kv-counting-store.d.ts +96 -0
- package/dist/src/testing/kv-counting-store.d.ts.map +1 -0
- package/dist/src/testing/kv-counting-store.js +226 -0
- package/dist/src/testing/kv-counting-store.js.map +1 -0
- package/dist/src/testing/kv-delegating-store.d.ts +28 -0
- package/dist/src/testing/kv-delegating-store.d.ts.map +1 -0
- package/dist/src/testing/kv-delegating-store.js +47 -0
- package/dist/src/testing/kv-delegating-store.js.map +1 -0
- package/dist/src/testing/memory-provider.d.ts +51 -0
- package/dist/src/testing/memory-provider.d.ts.map +1 -0
- package/dist/src/testing/memory-provider.js +124 -0
- package/dist/src/testing/memory-provider.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared counting test doubles for KVStore-backed specs — test-support, ships in
|
|
3
|
+
* `@quereus/store/testing`.
|
|
4
|
+
*
|
|
5
|
+
* Several specs in this package (and this package's benchmark suite) each need a `KVStore`
|
|
6
|
+
* that counts what passes through it: on the read side entries pulled from `iterate()`,
|
|
7
|
+
* `get()` calls, `getMany()` round trips and the keys they carried; on the write side
|
|
8
|
+
* point writes, `write()` round trips and the operations those carried. This file is the
|
|
9
|
+
* one shared implementation — see {@link CountingKVStore}'s doc comment for the two
|
|
10
|
+
* subtleties in how it has to be built.
|
|
11
|
+
*/
|
|
12
|
+
import { defaultGetMany } from '../common/kv-store.js';
|
|
13
|
+
import { buildDataStoreName, buildIndexStoreName, CATALOG_STORE_NAME, STATS_STORE_NAME } from '../common/key-builder.js';
|
|
14
|
+
import { InMemoryKVStore } from '../common/memory-store.js';
|
|
15
|
+
import { DelegatingKVStore } from './kv-delegating-store.js';
|
|
16
|
+
/**
|
|
17
|
+
* A {@link WriteBatch} that counts what its owning {@link CountingKVStore} commits.
|
|
18
|
+
*
|
|
19
|
+
* Exists because {@link DelegatingKVStore.batch} hands back the INNER store's batch, whose
|
|
20
|
+
* `put`/`delete`/`write` never pass back through the wrapper — so counting the commit path
|
|
21
|
+
* takes a wrapper here, not merely new fields on the store.
|
|
22
|
+
*
|
|
23
|
+
* Operations are attributed to the `write()` that carried them, not to the moment they were
|
|
24
|
+
* queued: `pending` accumulates and is handed to the owner when `write()` fires, so a batch
|
|
25
|
+
* that is queued and then `clear()`ed (or abandoned without writing) contributes nothing.
|
|
26
|
+
* The hand-off happens BEFORE awaiting the inner write, so a commit that fails still counts
|
|
27
|
+
* as a round trip issued — which is what a caller measuring storage traffic is asking about.
|
|
28
|
+
*/
|
|
29
|
+
class CountingWriteBatch {
|
|
30
|
+
inner;
|
|
31
|
+
onWrite;
|
|
32
|
+
/** Operations queued since construction or since the last `write()` / `clear()`. */
|
|
33
|
+
pending = 0;
|
|
34
|
+
constructor(inner, onWrite) {
|
|
35
|
+
this.inner = inner;
|
|
36
|
+
this.onWrite = onWrite;
|
|
37
|
+
}
|
|
38
|
+
put(key, value) {
|
|
39
|
+
this.pending++;
|
|
40
|
+
this.inner.put(key, value);
|
|
41
|
+
}
|
|
42
|
+
delete(key) {
|
|
43
|
+
this.pending++;
|
|
44
|
+
this.inner.delete(key);
|
|
45
|
+
}
|
|
46
|
+
write() {
|
|
47
|
+
const carried = this.pending;
|
|
48
|
+
this.pending = 0;
|
|
49
|
+
this.onWrite(carried);
|
|
50
|
+
return this.inner.write();
|
|
51
|
+
}
|
|
52
|
+
clear() {
|
|
53
|
+
this.pending = 0;
|
|
54
|
+
this.inner.clear();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Counts what passes through a wrapped {@link KVStore}. On the read side: entries pulled
|
|
59
|
+
* from `iterate()`, `get()` calls, `getMany()` round trips, and the keys those round trips
|
|
60
|
+
* carried. On the write side: point writes issued outside any batch, `write()` round trips,
|
|
61
|
+
* and the operations those carried.
|
|
62
|
+
*
|
|
63
|
+
* `getMany` routes through `defaultGetMany(this, keys)` rather than forwarding straight to
|
|
64
|
+
* `this.inner.getMany(keys)`. That is deliberate, not an oversight. `defaultGetMany` issues
|
|
65
|
+
* one `get(key)` per key against whatever object it is handed; passing `this` (the wrapper)
|
|
66
|
+
* means each of those `get` calls lands on THIS class's own overridden, counted `get()`
|
|
67
|
+
* (which in turn calls `this.inner.get`) — so a single `getMany` of N keys also advances
|
|
68
|
+
* `getCount` by N, matching how the specs built against this class assert. Forwarding to
|
|
69
|
+
* `this.inner.getMany(keys)` would run `defaultGetMany` with `this = inner`, bypassing the
|
|
70
|
+
* wrapper's `get()` entirely and leaving `getCount` unchanged after a batched read — a subtle
|
|
71
|
+
* break because most of the affected assertions are upper bounds (`.at.most(...)`), not exact
|
|
72
|
+
* equalities, so the bug would pass silently in most specs and only fail the one exact-equal
|
|
73
|
+
* assertion that happens to pin it.
|
|
74
|
+
*
|
|
75
|
+
* The trade-off this creates: `getManyCalls` / `getManyKeyCount` measure batching AT THE CALL
|
|
76
|
+
* BOUNDARY into this wrapper (did the caller invoke `getMany` once with N keys, vs. N calls to
|
|
77
|
+
* `get`) — not the wrapped backend's own internal round-trip count. That is the right thing to
|
|
78
|
+
* measure for the specs this class serves today, which are proving the ENGINE batches its
|
|
79
|
+
* reads, not that the wrapped backend has a native multi-get. A future benchmark reaching for
|
|
80
|
+
* this class to measure a REAL backend's own native batching needs to know that distinction.
|
|
81
|
+
*
|
|
82
|
+
* The write side has the SAME call-boundary caveat, and one structural requirement:
|
|
83
|
+
* `batch()` is overridden to return a {@link CountingWriteBatch}, because the base class's
|
|
84
|
+
* `batch()` hands out the inner store's batch directly and nothing queued on it would ever
|
|
85
|
+
* reach this wrapper. The write counters are deliberately split direct-vs-batched — a commit
|
|
86
|
+
* path that queues N operations and issues ONE `write()` is a different physical cost from
|
|
87
|
+
* one that issues N point writes, and a single combined "writes" number could not tell them
|
|
88
|
+
* apart. The four read counters and the four write counters are independent; a workload
|
|
89
|
+
* touches both.
|
|
90
|
+
*/
|
|
91
|
+
export class CountingKVStore extends DelegatingKVStore {
|
|
92
|
+
/** Entries pulled from the inner store's `iterate()`. */
|
|
93
|
+
iterateEntryCount = 0;
|
|
94
|
+
/** `get()` calls. */
|
|
95
|
+
getCount = 0;
|
|
96
|
+
/** `getMany()` calls — round trips, as observed at this counting boundary. */
|
|
97
|
+
getManyCalls = 0;
|
|
98
|
+
/** Keys carried by those `getMany()` calls. */
|
|
99
|
+
getManyKeyCount = 0;
|
|
100
|
+
/** Puts issued one at a time, outside any batch. */
|
|
101
|
+
directPutCount = 0;
|
|
102
|
+
/** Deletes issued one at a time, outside any batch. */
|
|
103
|
+
directDeleteCount = 0;
|
|
104
|
+
/** `WriteBatch.write()` calls — the write-side round-trip count. */
|
|
105
|
+
batchWriteCalls = 0;
|
|
106
|
+
/** Put/delete operations those `write()` calls carried. */
|
|
107
|
+
batchOpCount = 0;
|
|
108
|
+
/** Zero every counter, read and write. */
|
|
109
|
+
reset() {
|
|
110
|
+
this.iterateEntryCount = 0;
|
|
111
|
+
this.getCount = 0;
|
|
112
|
+
this.getManyCalls = 0;
|
|
113
|
+
this.getManyKeyCount = 0;
|
|
114
|
+
this.directPutCount = 0;
|
|
115
|
+
this.directDeleteCount = 0;
|
|
116
|
+
this.batchWriteCalls = 0;
|
|
117
|
+
this.batchOpCount = 0;
|
|
118
|
+
}
|
|
119
|
+
async get(key) {
|
|
120
|
+
this.getCount++;
|
|
121
|
+
return this.inner.get(key);
|
|
122
|
+
}
|
|
123
|
+
async getMany(keys) {
|
|
124
|
+
this.getManyCalls++;
|
|
125
|
+
this.getManyKeyCount += keys.length;
|
|
126
|
+
// Must route through the wrapper's own `get` — see the class doc comment above.
|
|
127
|
+
return defaultGetMany(this, keys);
|
|
128
|
+
}
|
|
129
|
+
async *iterate(options) {
|
|
130
|
+
for await (const entry of this.inner.iterate(options)) {
|
|
131
|
+
this.iterateEntryCount++;
|
|
132
|
+
yield entry;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
put(key, value, options) {
|
|
136
|
+
this.directPutCount++;
|
|
137
|
+
return this.inner.put(key, value, options);
|
|
138
|
+
}
|
|
139
|
+
delete(key, options) {
|
|
140
|
+
this.directDeleteCount++;
|
|
141
|
+
return this.inner.delete(key, options);
|
|
142
|
+
}
|
|
143
|
+
// NOTE: only the per-store `WriteBatch` path is counted, never `AtomicBatch`. Nothing
|
|
144
|
+
// counted reaches the atomic path today — `createCountingProvider` exposes no
|
|
145
|
+
// `beginAtomicBatch`, so the transaction coordinator always takes its per-store
|
|
146
|
+
// fallback — and an `AtomicBatch` wrapper nothing exercises is dead weight. If the
|
|
147
|
+
// counting provider ever gains a shared commit domain, wrap `AtomicBatch` at the same
|
|
148
|
+
// time: until then such a commit would report zero writes rather than fail loudly.
|
|
149
|
+
batch() {
|
|
150
|
+
return new CountingWriteBatch(this.inner.batch(), (opsCarried) => {
|
|
151
|
+
this.batchWriteCalls++;
|
|
152
|
+
this.batchOpCount += opsCarried;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A {@link KVStoreProvider} whose stores are {@link CountingKVStore}s, so a spec can assert
|
|
158
|
+
* on the read traffic (`iterate`/`get`/`getMany`) and the write traffic (point writes and
|
|
159
|
+
* batch commits) StoreModule generates, without reaching into a real backend.
|
|
160
|
+
*
|
|
161
|
+
* Store names come from the shared builders (`buildDataStoreName` / `buildIndexStoreName`,
|
|
162
|
+
* the reserved `__stats__` / `__catalog__` constants) — the same rule every real provider
|
|
163
|
+
* is held to by `runStoreNameDistinctness`. Hand-composing them here would lose the
|
|
164
|
+
* builders' lowercasing, so a mixed-case table name would land on a store no real backend
|
|
165
|
+
* would have used.
|
|
166
|
+
*
|
|
167
|
+
* @param countedStores - Map the counted stores are recorded into, keyed by BUILT store
|
|
168
|
+
* name: `schema.table` (every table's data store) and, when `scope` is `'all'`, also
|
|
169
|
+
* `schema.table_idx_index` (secondary indexes), `__stats__`, and `__catalog__`. The caller
|
|
170
|
+
* reads counters back out of this map after driving a query.
|
|
171
|
+
* @param scope - `'data'` (default): only each table's data store is counted; index,
|
|
172
|
+
* stats, and catalog stores stay plain, uncounted `InMemoryKVStore`s the caller never
|
|
173
|
+
* sees. `'all'`: every store the provider hands out is counted into `countedStores`.
|
|
174
|
+
*/
|
|
175
|
+
// NOTE: implements no `deleteIndexStore` / `deleteTableStores` (both optional on the
|
|
176
|
+
// interface), so a spec that drops a table or index and recreates it under the same name
|
|
177
|
+
// reads the dropped store's entries back. Every spec using this provider today creates its
|
|
178
|
+
// tables once; if one starts exercising drop-then-recreate, implement them (erase, don't
|
|
179
|
+
// just drop the handle) rather than working around it in the spec.
|
|
180
|
+
export function createCountingProvider(countedStores, scope = 'data') {
|
|
181
|
+
const auxStores = new Map();
|
|
182
|
+
const aux = (key) => {
|
|
183
|
+
let s = auxStores.get(key);
|
|
184
|
+
if (!s) {
|
|
185
|
+
s = new InMemoryKVStore();
|
|
186
|
+
auxStores.set(key, s);
|
|
187
|
+
}
|
|
188
|
+
return s;
|
|
189
|
+
};
|
|
190
|
+
const counted = (key) => {
|
|
191
|
+
let s = countedStores.get(key);
|
|
192
|
+
if (!s) {
|
|
193
|
+
s = new CountingKVStore(new InMemoryKVStore());
|
|
194
|
+
countedStores.set(key, s);
|
|
195
|
+
}
|
|
196
|
+
return s;
|
|
197
|
+
};
|
|
198
|
+
const maybeCounted = (key) => (scope === 'all' ? counted(key) : aux(key));
|
|
199
|
+
return {
|
|
200
|
+
async getStore(schemaName, tableName) {
|
|
201
|
+
return counted(buildDataStoreName(schemaName, tableName));
|
|
202
|
+
},
|
|
203
|
+
async getIndexStore(schemaName, tableName, indexName) {
|
|
204
|
+
return maybeCounted(buildIndexStoreName(schemaName, tableName, indexName));
|
|
205
|
+
},
|
|
206
|
+
// One unified stats store for every table, as the interface specifies — the
|
|
207
|
+
// schema/table arguments are ignored.
|
|
208
|
+
async getStatsStore() {
|
|
209
|
+
return maybeCounted(STATS_STORE_NAME);
|
|
210
|
+
},
|
|
211
|
+
async getCatalogStore() {
|
|
212
|
+
return maybeCounted(CATALOG_STORE_NAME);
|
|
213
|
+
},
|
|
214
|
+
async closeStore() { },
|
|
215
|
+
async closeIndexStore() { },
|
|
216
|
+
async closeAll() {
|
|
217
|
+
for (const s of countedStores.values())
|
|
218
|
+
await s.close();
|
|
219
|
+
for (const s of auxStores.values())
|
|
220
|
+
await s.close();
|
|
221
|
+
countedStores.clear();
|
|
222
|
+
auxStores.clear();
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=kv-counting-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv-counting-store.js","sourceRoot":"","sources":["../../../src/testing/kv-counting-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pass-through {@link KVStore} base every test double in this package extends —
|
|
3
|
+
* test-support, ships in `@quereus/store/testing`.
|
|
4
|
+
*
|
|
5
|
+
* Lives on its own rather than beside any one double because it is not specific to what
|
|
6
|
+
* any of them model: the counting store here, and the buffering / rescanning / getMany-
|
|
7
|
+
* misbehaving doubles in `test/kv-store-doubles.ts`, all subclass it and override exactly
|
|
8
|
+
* the one method whose behavior they are demonstrating.
|
|
9
|
+
*/
|
|
10
|
+
import type { IterateOptions, KVEntry, KVStore, WriteBatch, WriteOptions } from '../common/kv-store.js';
|
|
11
|
+
/**
|
|
12
|
+
* Forwards every {@link KVStore} method to an inner store. Subclasses override only
|
|
13
|
+
* the one method whose behavior they are modeling.
|
|
14
|
+
*/
|
|
15
|
+
export declare class DelegatingKVStore implements KVStore {
|
|
16
|
+
protected readonly inner: KVStore;
|
|
17
|
+
constructor(inner: KVStore);
|
|
18
|
+
get(key: Uint8Array): Promise<Uint8Array | undefined>;
|
|
19
|
+
getMany(keys: readonly Uint8Array[]): Promise<(Uint8Array | undefined)[]>;
|
|
20
|
+
put(key: Uint8Array, value: Uint8Array, options?: WriteOptions): Promise<void>;
|
|
21
|
+
delete(key: Uint8Array, options?: WriteOptions): Promise<void>;
|
|
22
|
+
has(key: Uint8Array): Promise<boolean>;
|
|
23
|
+
iterate(options?: IterateOptions): AsyncIterable<KVEntry>;
|
|
24
|
+
batch(): WriteBatch;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
approximateCount(options?: IterateOptions): Promise<number>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=kv-delegating-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv-delegating-store.d.ts","sourceRoot":"","sources":["../../../src/testing/kv-delegating-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAExG;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IACpC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO;gBAAd,KAAK,EAAE,OAAO;IAE7C,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIrD,OAAO,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,CAAC;IAIzE,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAItC,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,aAAa,CAAC,OAAO,CAAC;IAIzD,KAAK,IAAI,UAAU;IAInB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,gBAAgB,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;CAG3D"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pass-through {@link KVStore} base every test double in this package extends —
|
|
3
|
+
* test-support, ships in `@quereus/store/testing`.
|
|
4
|
+
*
|
|
5
|
+
* Lives on its own rather than beside any one double because it is not specific to what
|
|
6
|
+
* any of them model: the counting store here, and the buffering / rescanning / getMany-
|
|
7
|
+
* misbehaving doubles in `test/kv-store-doubles.ts`, all subclass it and override exactly
|
|
8
|
+
* the one method whose behavior they are demonstrating.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Forwards every {@link KVStore} method to an inner store. Subclasses override only
|
|
12
|
+
* the one method whose behavior they are modeling.
|
|
13
|
+
*/
|
|
14
|
+
export class DelegatingKVStore {
|
|
15
|
+
inner;
|
|
16
|
+
constructor(inner) {
|
|
17
|
+
this.inner = inner;
|
|
18
|
+
}
|
|
19
|
+
get(key) {
|
|
20
|
+
return this.inner.get(key);
|
|
21
|
+
}
|
|
22
|
+
getMany(keys) {
|
|
23
|
+
return this.inner.getMany(keys);
|
|
24
|
+
}
|
|
25
|
+
put(key, value, options) {
|
|
26
|
+
return this.inner.put(key, value, options);
|
|
27
|
+
}
|
|
28
|
+
delete(key, options) {
|
|
29
|
+
return this.inner.delete(key, options);
|
|
30
|
+
}
|
|
31
|
+
has(key) {
|
|
32
|
+
return this.inner.has(key);
|
|
33
|
+
}
|
|
34
|
+
iterate(options) {
|
|
35
|
+
return this.inner.iterate(options);
|
|
36
|
+
}
|
|
37
|
+
batch() {
|
|
38
|
+
return this.inner.batch();
|
|
39
|
+
}
|
|
40
|
+
close() {
|
|
41
|
+
return this.inner.close();
|
|
42
|
+
}
|
|
43
|
+
approximateCount(options) {
|
|
44
|
+
return this.inner.approximateCount(options);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=kv-delegating-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv-delegating-store.js","sourceRoot":"","sources":["../../../src/testing/kv-delegating-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACE;IAA/B,YAA+B,KAAc;QAAd,UAAK,GAAL,KAAK,CAAS;IAAG,CAAC;IAEjD,GAAG,CAAC,GAAe;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,IAA2B;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,GAAe,EAAE,KAAiB,EAAE,OAAsB;QAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,GAAe,EAAE,OAAsB;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,GAAG,CAAC,GAAe;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,OAAwB;QAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,KAAK;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,gBAAgB,CAAC,OAAwB;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;CACD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared in-memory {@link KVStoreProvider} test double — test-support, ships in
|
|
3
|
+
* `@quereus/store/testing`.
|
|
4
|
+
*
|
|
5
|
+
* Nearly every spec in this package's `test/` directory (and this package's benchmark
|
|
6
|
+
* suite) opens with its own private copy of an all-`InMemoryKVStore` provider. This is the
|
|
7
|
+
* one shared implementation, built to the same conventions as its sibling
|
|
8
|
+
* {@link createCountingProvider}:
|
|
9
|
+
*
|
|
10
|
+
* - Store names come from {@link buildDataStoreName} / {@link buildIndexStoreName} and the
|
|
11
|
+
* reserved {@link CATALOG_STORE_NAME} / {@link STATS_STORE_NAME} constants — never
|
|
12
|
+
* hand-composed template strings, which drop the builders' lowercasing.
|
|
13
|
+
* - {@link KVStoreProvider.getStatsStore} returns ONE unified `__stats__` store for every
|
|
14
|
+
* table, as the interface specifies (its schema/table arguments are documented as
|
|
15
|
+
* ignored) — not the per-table `schema.table.__stats__` spelling most local copies use.
|
|
16
|
+
* - `options.costProfile` is spread in only when present, so a provider built with no
|
|
17
|
+
* options (or `{}`) has no `costProfile` property at all, matching what a genuine
|
|
18
|
+
* pre-profile third-party provider looks like.
|
|
19
|
+
*
|
|
20
|
+
* Unlike {@link createCountingProvider} — which deliberately omits `deleteIndexStore` /
|
|
21
|
+
* `deleteTableStores` — this provider implements both, and they ERASE rather than merely
|
|
22
|
+
* drop the map entry: see {@link erase} for why a live handle still needs its bytes cleared.
|
|
23
|
+
* `renameTableStores` is deliberately NOT implemented; `StoreModule` falls back to a generic
|
|
24
|
+
* copy for a provider without it (`test/rename-store-copy-fallback.spec.ts`), and nothing
|
|
25
|
+
* that needs this provider today renames.
|
|
26
|
+
*
|
|
27
|
+
* Neither is `beginAtomicBatch`, and that one is not a gap to fill later: separate
|
|
28
|
+
* `InMemoryKVStore`s share no commit domain, so there is nothing for a cross-store batch to
|
|
29
|
+
* make atomic. The consequence is worth knowing before reading numbers off this provider —
|
|
30
|
+
* `StoreModuleBase` sets `atomicProvider` from that method's presence and commits per store
|
|
31
|
+
* here, where a LevelDB-family provider commits in one physical write. A benchmark putting
|
|
32
|
+
* this provider next to LevelDB is comparing two commit PATHS, not one path over two
|
|
33
|
+
* backends.
|
|
34
|
+
*/
|
|
35
|
+
import type { KVStoreProvider } from '../common/kv-store.js';
|
|
36
|
+
import type { KVCostProfile } from '../common/cost-profile.js';
|
|
37
|
+
/** Options accepted by {@link createInMemoryProvider}. */
|
|
38
|
+
export interface InMemoryProviderOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Forwarded verbatim as the provider's declared `costProfile`. Omitted (the default)
|
|
41
|
+
* means the returned provider has no `costProfile` property at all — see the class doc
|
|
42
|
+
* comment above for why that shape matters to `resolveCostProfile`'s parity path.
|
|
43
|
+
*/
|
|
44
|
+
readonly costProfile?: KVCostProfile;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build an all-`InMemoryKVStore` {@link KVStoreProvider}. Every distinct built store name
|
|
48
|
+
* gets its own `InMemoryKVStore`, created lazily on first access.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createInMemoryProvider(options?: InMemoryProviderOptions): KVStoreProvider;
|
|
51
|
+
//# sourceMappingURL=memory-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-provider.d.ts","sourceRoot":"","sources":["../../../src/testing/memory-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI/D,0DAA0D;AAC1D,MAAM,WAAW,uBAAuB;IACvC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,eAAe,CAqFzF"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared in-memory {@link KVStoreProvider} test double — test-support, ships in
|
|
3
|
+
* `@quereus/store/testing`.
|
|
4
|
+
*
|
|
5
|
+
* Nearly every spec in this package's `test/` directory (and this package's benchmark
|
|
6
|
+
* suite) opens with its own private copy of an all-`InMemoryKVStore` provider. This is the
|
|
7
|
+
* one shared implementation, built to the same conventions as its sibling
|
|
8
|
+
* {@link createCountingProvider}:
|
|
9
|
+
*
|
|
10
|
+
* - Store names come from {@link buildDataStoreName} / {@link buildIndexStoreName} and the
|
|
11
|
+
* reserved {@link CATALOG_STORE_NAME} / {@link STATS_STORE_NAME} constants — never
|
|
12
|
+
* hand-composed template strings, which drop the builders' lowercasing.
|
|
13
|
+
* - {@link KVStoreProvider.getStatsStore} returns ONE unified `__stats__` store for every
|
|
14
|
+
* table, as the interface specifies (its schema/table arguments are documented as
|
|
15
|
+
* ignored) — not the per-table `schema.table.__stats__` spelling most local copies use.
|
|
16
|
+
* - `options.costProfile` is spread in only when present, so a provider built with no
|
|
17
|
+
* options (or `{}`) has no `costProfile` property at all, matching what a genuine
|
|
18
|
+
* pre-profile third-party provider looks like.
|
|
19
|
+
*
|
|
20
|
+
* Unlike {@link createCountingProvider} — which deliberately omits `deleteIndexStore` /
|
|
21
|
+
* `deleteTableStores` — this provider implements both, and they ERASE rather than merely
|
|
22
|
+
* drop the map entry: see {@link erase} for why a live handle still needs its bytes cleared.
|
|
23
|
+
* `renameTableStores` is deliberately NOT implemented; `StoreModule` falls back to a generic
|
|
24
|
+
* copy for a provider without it (`test/rename-store-copy-fallback.spec.ts`), and nothing
|
|
25
|
+
* that needs this provider today renames.
|
|
26
|
+
*
|
|
27
|
+
* Neither is `beginAtomicBatch`, and that one is not a gap to fill later: separate
|
|
28
|
+
* `InMemoryKVStore`s share no commit domain, so there is nothing for a cross-store batch to
|
|
29
|
+
* make atomic. The consequence is worth knowing before reading numbers off this provider —
|
|
30
|
+
* `StoreModuleBase` sets `atomicProvider` from that method's presence and commits per store
|
|
31
|
+
* here, where a LevelDB-family provider commits in one physical write. A benchmark putting
|
|
32
|
+
* this provider next to LevelDB is comparing two commit PATHS, not one path over two
|
|
33
|
+
* backends.
|
|
34
|
+
*/
|
|
35
|
+
import { buildDataStoreName, buildIndexStoreName, CATALOG_STORE_NAME, STATS_STORE_NAME } from '../common/key-builder.js';
|
|
36
|
+
import { InMemoryKVStore } from '../common/memory-store.js';
|
|
37
|
+
/**
|
|
38
|
+
* Build an all-`InMemoryKVStore` {@link KVStoreProvider}. Every distinct built store name
|
|
39
|
+
* gets its own `InMemoryKVStore`, created lazily on first access.
|
|
40
|
+
*/
|
|
41
|
+
export function createInMemoryProvider(options) {
|
|
42
|
+
const stores = new Map();
|
|
43
|
+
// NOTE: a cached store the CALLER closed directly is handed back closed, so the next op
|
|
44
|
+
// on it throws `InMemoryKVStore is closed` rather than re-opening — unlike a real backend,
|
|
45
|
+
// which re-opens the name with its bytes intact. No StoreModule path does that today
|
|
46
|
+
// (`StoreTableBase.releaseIndexStore` is the only close, and its caller always deletes the
|
|
47
|
+
// store right after, which drops the entry). If a spec or benchmark ever closes a handle
|
|
48
|
+
// and keeps using the name, treat a closed cached store as absent here.
|
|
49
|
+
const getOrCreate = (key) => {
|
|
50
|
+
let store = stores.get(key);
|
|
51
|
+
if (!store) {
|
|
52
|
+
store = new InMemoryKVStore();
|
|
53
|
+
stores.set(key, store);
|
|
54
|
+
}
|
|
55
|
+
return store;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Erase the store named `key`: a caller re-opening this name afterwards must find it
|
|
59
|
+
* empty, and a caller still holding a LIVE handle to it must see the erase too (the
|
|
60
|
+
* reclaim battery's "handle the caller already closed" case is the other order — see
|
|
61
|
+
* below). Two cases, both ending in the map entry being dropped so the name re-opens
|
|
62
|
+
* fresh:
|
|
63
|
+
*
|
|
64
|
+
* - Live store: `clear()` it first, so an existing handle observes the erase, THEN
|
|
65
|
+
* drop the map entry.
|
|
66
|
+
* - Already-closed store (the caller closed its handle before asking for the delete —
|
|
67
|
+
* exactly what `StoreModuleIndex.tearDownIndexStore` does): `close()` already
|
|
68
|
+
* cleared its entries and marked it closed, so `clear()` would just throw
|
|
69
|
+
* (`checkOpen()`) for no benefit. Skip straight to dropping the map entry.
|
|
70
|
+
*
|
|
71
|
+
* A store that was never created (key absent from the map) is a no-op, matching the
|
|
72
|
+
* interface's speculative-delete contract.
|
|
73
|
+
*
|
|
74
|
+
* NOTE: the live handle is cleared, not closed, so a caller still holding it can go on
|
|
75
|
+
* PUTting into a store the provider has forgotten — those writes land nowhere anyone can
|
|
76
|
+
* read, silently. A real backend's handle is dead after its store is dropped. Closing here
|
|
77
|
+
* instead would trade the silence for a throw, but would also break the contract line
|
|
78
|
+
* above (a live handle must read back EMPTY, not throw); revisit if a spec is ever found
|
|
79
|
+
* writing through a post-delete handle.
|
|
80
|
+
*/
|
|
81
|
+
const erase = async (key) => {
|
|
82
|
+
const store = stores.get(key);
|
|
83
|
+
if (!store)
|
|
84
|
+
return;
|
|
85
|
+
if (!store.isClosed) {
|
|
86
|
+
store.clear();
|
|
87
|
+
}
|
|
88
|
+
stores.delete(key);
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
...(options?.costProfile ? { costProfile: options.costProfile } : {}),
|
|
92
|
+
async getStore(schemaName, tableName) {
|
|
93
|
+
return getOrCreate(buildDataStoreName(schemaName, tableName));
|
|
94
|
+
},
|
|
95
|
+
async getIndexStore(schemaName, tableName, indexName) {
|
|
96
|
+
return getOrCreate(buildIndexStoreName(schemaName, tableName, indexName));
|
|
97
|
+
},
|
|
98
|
+
async getStatsStore() {
|
|
99
|
+
return getOrCreate(STATS_STORE_NAME);
|
|
100
|
+
},
|
|
101
|
+
async getCatalogStore() {
|
|
102
|
+
return getOrCreate(CATALOG_STORE_NAME);
|
|
103
|
+
},
|
|
104
|
+
async closeStore() { },
|
|
105
|
+
async closeIndexStore() { },
|
|
106
|
+
async closeAll() {
|
|
107
|
+
for (const store of stores.values())
|
|
108
|
+
await store.close();
|
|
109
|
+
stores.clear();
|
|
110
|
+
},
|
|
111
|
+
async deleteIndexStore(schemaName, tableName, indexName) {
|
|
112
|
+
await erase(buildIndexStoreName(schemaName, tableName, indexName));
|
|
113
|
+
},
|
|
114
|
+
async deleteTableStores(schemaName, tableName, indexNames) {
|
|
115
|
+
await erase(buildDataStoreName(schemaName, tableName));
|
|
116
|
+
for (const indexName of indexNames) {
|
|
117
|
+
await erase(buildIndexStoreName(schemaName, tableName, indexName));
|
|
118
|
+
}
|
|
119
|
+
// The unified __stats__ store is deliberately untouched — a table's row count is
|
|
120
|
+
// one ENTRY there, and removing it is the caller's business, not a store deletion.
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=memory-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-provider.js","sourceRoot":"","sources":["../../../src/testing/memory-provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quereus/store",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.16.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Abstract key-value storage module for Quereus",
|
|
6
6
|
"keywords": [
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"test:single": "cd ../.. && node --import ./packages/quereus-store/register.mjs node_modules/mocha/bin/mocha.js --bail"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@quereus/isolation": "^4.
|
|
56
|
-
"@quereus/quereus": "^4.
|
|
55
|
+
"@quereus/isolation": "^4.16.0",
|
|
56
|
+
"@quereus/quereus": "^4.16.0"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@quereus/isolation": "^4.
|
|
60
|
-
"@quereus/quereus": "^4.
|
|
59
|
+
"@quereus/isolation": "^4.16.0",
|
|
60
|
+
"@quereus/quereus": "^4.16.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/mocha": "^10.0.10",
|