@quereus/plugin-leveldb 3.3.0 → 4.1.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 +197 -166
- package/dist/src/plugin.d.ts +10 -3
- package/dist/src/plugin.d.ts.map +1 -1
- package/dist/src/plugin.js +2 -0
- package/dist/src/plugin.js.map +1 -1
- package/dist/src/provider.d.ts +77 -21
- package/dist/src/provider.d.ts.map +1 -1
- package/dist/src/provider.js +297 -147
- package/dist/src/provider.js.map +1 -1
- package/dist/src/store.d.ts +47 -7
- package/dist/src/store.d.ts.map +1 -1
- package/dist/src/store.js +70 -25
- package/dist/src/store.js.map +1 -1
- package/package.json +19 -11
package/dist/src/provider.js
CHANGED
|
@@ -1,213 +1,363 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* LevelDB
|
|
2
|
+
* LevelDB KVStoreProvider — shared-root layout.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* All of a database's stores live inside ONE physical LevelDB at `basePath`, each
|
|
5
|
+
* as a sublevel keyed by its store name:
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
* {
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* {schema}.{table} - table data (buildDataStoreName)
|
|
8
|
+
* {schema}.{table}_idx_{name} - secondary index (buildIndexStoreName)
|
|
9
|
+
* __stats__ - unified stats (STATS_STORE_NAME)
|
|
10
|
+
* __catalog__ - catalog / DDL (CATALOG_STORE_NAME)
|
|
11
|
+
*
|
|
12
|
+
* Because every sublevel shares one physical store, a single chained batch
|
|
13
|
+
* (`root.batch()…write()`) commits across sublevels atomically and durably — see
|
|
14
|
+
* {@link LevelDBProvider.beginAtomicBatch}. This is the crash-safe single commit
|
|
15
|
+
* that the prior per-directory layout (a separate ClassicLevel per table) could
|
|
16
|
+
* not provide: separate physical databases cannot share a write batch.
|
|
17
|
+
*
|
|
18
|
+
* HARD CUTOVER: this is the only LevelDB layout. Databases written by the prior
|
|
19
|
+
* per-directory layout (`{basePath}/{schema}/{table}`) are NOT read here and must
|
|
20
|
+
* be re-created (pre-1.0 dev data). There is no on-disk migration. See README.
|
|
11
21
|
*/
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
22
|
+
import { ClassicLevel } from 'classic-level';
|
|
23
|
+
import { buildDataStoreName, buildIndexStoreName, CATALOG_STORE_NAME, STATS_STORE_NAME } from '@quereus/store';
|
|
24
|
+
import { QuereusError, StatusCode } from '@quereus/quereus';
|
|
15
25
|
import { LevelDBStore } from './store.js';
|
|
26
|
+
const textEncoder = new TextEncoder();
|
|
16
27
|
/**
|
|
17
|
-
*
|
|
28
|
+
* Encode a logical store name into a sublevel-safe name.
|
|
18
29
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
30
|
+
* abstract-level requires every byte of a sublevel name to be in `(separator, 127)`
|
|
31
|
+
* — with the default `!` separator that is 35..126. Logical store names are
|
|
32
|
+
* `{schema}.{table}` identifiers that may contain spaces, punctuation, or non-ASCII
|
|
33
|
+
* (e.g. a quoted table name `"Table With Spaces"`), so any byte outside the safe set
|
|
34
|
+
* is percent-encoded. The mapping is deterministic and injective (distinct logical
|
|
35
|
+
* names → distinct sublevel names), which is all the provider's name-keyed caching
|
|
36
|
+
* and the StoreModule's collision checks require; the sublevel name is never decoded
|
|
37
|
+
* back. Common names (lowercase identifiers, `.`, `_`) pass through unchanged.
|
|
38
|
+
*/
|
|
39
|
+
function encodeSublevelName(name) {
|
|
40
|
+
let out = '';
|
|
41
|
+
for (const b of textEncoder.encode(name)) {
|
|
42
|
+
// Safe: printable ASCII in (34, 127) except '%' (0x25), which is reserved as
|
|
43
|
+
// the escape introducer so the encoding stays injective.
|
|
44
|
+
if (b > 34 && b < 127 && b !== 0x25) {
|
|
45
|
+
out += String.fromCharCode(b);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
out += '%' + b.toString(16).toUpperCase().padStart(2, '0');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* LevelDB implementation of KVStoreProvider over a single shared root with one
|
|
55
|
+
* sublevel per logical store.
|
|
21
56
|
*/
|
|
22
57
|
export class LevelDBProvider {
|
|
23
58
|
basePath;
|
|
24
59
|
createIfMissing;
|
|
60
|
+
syncCommits;
|
|
61
|
+
/** The shared physical root, once opened. */
|
|
62
|
+
root = null;
|
|
63
|
+
/** Memoized in-flight root open so concurrent first-opens share one handle. */
|
|
64
|
+
rootOpening = null;
|
|
65
|
+
/** Cached store handles, keyed by store (sublevel) name. */
|
|
25
66
|
stores = new Map();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
67
|
+
/** In-flight sublevel opens, keyed by store name, so concurrent callers dedupe. */
|
|
68
|
+
storeOpening = new Map();
|
|
69
|
+
/**
|
|
70
|
+
* Sublevel + ownership proof for every store this provider produced. Used by the
|
|
71
|
+
* atomic batch to map a {@link KVStore} handle back to its sublevel and to reject
|
|
72
|
+
* a foreign handle (a non-LevelDB store, or one from another provider, is absent).
|
|
73
|
+
*/
|
|
74
|
+
sublevelByStore = new WeakMap();
|
|
29
75
|
constructor(options) {
|
|
30
76
|
this.basePath = options.basePath;
|
|
31
77
|
this.createIfMissing = options.createIfMissing ?? true;
|
|
78
|
+
this.syncCommits = options.syncCommits ?? true;
|
|
32
79
|
}
|
|
33
|
-
async getStore(schemaName, tableName,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
80
|
+
async getStore(schemaName, tableName, _options) {
|
|
81
|
+
// NOTE: the prior per-directory layout honored an `options.path` override to
|
|
82
|
+
// place a table's database elsewhere. With one shared root there is no
|
|
83
|
+
// per-table path, so the override is gone (the engine never passed it).
|
|
84
|
+
return this.getOrCreateStore(buildDataStoreName(schemaName, tableName));
|
|
37
85
|
}
|
|
38
86
|
async getIndexStore(schemaName, tableName, indexName) {
|
|
39
|
-
|
|
40
|
-
const storePath = path.join(this.basePath, schemaName, `${tableName}${STORE_SUFFIX.INDEX}${indexName}`);
|
|
41
|
-
return this.getOrCreateStore(storeName, storePath);
|
|
87
|
+
return this.getOrCreateStore(buildIndexStoreName(schemaName, tableName, indexName));
|
|
42
88
|
}
|
|
43
89
|
async getStatsStore(_schemaName, _tableName) {
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
const statsPath = path.join(this.basePath, STATS_STORE_NAME);
|
|
47
|
-
this.statsStore = await LevelDBStore.open({
|
|
48
|
-
path: statsPath,
|
|
49
|
-
createIfMissing: this.createIfMissing,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
return this.statsStore;
|
|
90
|
+
// Unified __stats__ store for all tables.
|
|
91
|
+
return this.getOrCreateStore(STATS_STORE_NAME);
|
|
53
92
|
}
|
|
54
93
|
async getCatalogStore() {
|
|
55
|
-
|
|
56
|
-
const catalogPath = path.join(this.basePath, CATALOG_STORE_NAME);
|
|
57
|
-
this.catalogStore = await LevelDBStore.open({
|
|
58
|
-
path: catalogPath,
|
|
59
|
-
createIfMissing: this.createIfMissing,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
return this.catalogStore;
|
|
94
|
+
return this.getOrCreateStore(CATALOG_STORE_NAME);
|
|
63
95
|
}
|
|
64
96
|
async closeStore(schemaName, tableName) {
|
|
65
|
-
|
|
66
|
-
await this.closeStoreByName(storeName);
|
|
97
|
+
await this.closeStoreByName(buildDataStoreName(schemaName, tableName));
|
|
67
98
|
}
|
|
68
99
|
async closeIndexStore(schemaName, tableName, indexName) {
|
|
69
|
-
|
|
70
|
-
await this.closeStoreByName(storeName);
|
|
100
|
+
await this.closeStoreByName(buildIndexStoreName(schemaName, tableName, indexName));
|
|
71
101
|
}
|
|
72
102
|
async closeAll() {
|
|
103
|
+
// Await any in-flight opens (stores + root) first so we don't strand a
|
|
104
|
+
// freshly-opened sublevel/root after clearing the caches and closing the root.
|
|
105
|
+
await Promise.allSettled([
|
|
106
|
+
...this.storeOpening.values(),
|
|
107
|
+
this.rootOpening,
|
|
108
|
+
].filter(Boolean));
|
|
109
|
+
// Close each cached sublevel handle, then close the root. Closing the root
|
|
110
|
+
// would itself cascade to attached sublevels, but closing handles first
|
|
111
|
+
// marks our store wrappers closed and keeps the close ordering explicit.
|
|
73
112
|
for (const store of this.stores.values()) {
|
|
74
113
|
await store.close();
|
|
75
114
|
}
|
|
76
115
|
this.stores.clear();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this.
|
|
80
|
-
|
|
81
|
-
if (this.statsStore) {
|
|
82
|
-
await this.statsStore.close();
|
|
83
|
-
this.statsStore = null;
|
|
116
|
+
this.storeOpening.clear();
|
|
117
|
+
if (this.root) {
|
|
118
|
+
await this.root.close();
|
|
119
|
+
this.root = null;
|
|
84
120
|
}
|
|
121
|
+
this.rootOpening = null;
|
|
85
122
|
}
|
|
86
123
|
async deleteIndexStore(schemaName, tableName, indexName) {
|
|
87
|
-
|
|
88
|
-
const storePath = this.storePaths.get(storeName)
|
|
89
|
-
?? path.join(this.basePath, schemaName, `${tableName}${STORE_SUFFIX.INDEX}${indexName}`);
|
|
90
|
-
await this.closeStoreByName(storeName);
|
|
91
|
-
await removeDir(storePath);
|
|
124
|
+
await this.clearAndDropStore(buildIndexStoreName(schemaName, tableName, indexName));
|
|
92
125
|
}
|
|
93
|
-
async renameTableStores(schemaName, oldName, newName) {
|
|
94
|
-
const
|
|
95
|
-
const
|
|
126
|
+
async renameTableStores(schemaName, oldName, newName, indexNames) {
|
|
127
|
+
const root = await this.getRoot();
|
|
128
|
+
const oldDataStoreName = buildDataStoreName(schemaName, oldName);
|
|
129
|
+
const newDataStoreName = buildDataStoreName(schemaName, newName);
|
|
96
130
|
if (this.stores.has(newDataStoreName)) {
|
|
97
131
|
throw new Error(`Cannot rename '${oldName}' to '${newName}': store already open under the new name`);
|
|
98
132
|
}
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// Move data directory, if present.
|
|
112
|
-
const schemaDir = path.join(this.basePath, schemaName);
|
|
113
|
-
const oldDataPath = path.join(schemaDir, oldName);
|
|
114
|
-
const newDataPath = path.join(schemaDir, newName);
|
|
115
|
-
if (await pathExists(oldDataPath)) {
|
|
116
|
-
if (await pathExists(newDataPath)) {
|
|
117
|
-
throw new Error(`Cannot rename '${oldName}' to '${newName}': destination path '${newDataPath}' already exists`);
|
|
118
|
-
}
|
|
119
|
-
await fs.promises.rename(oldDataPath, newDataPath);
|
|
133
|
+
// (old → new) store-name pairs: data store + each schema index, built
|
|
134
|
+
// exact-by-name via buildIndexStoreName — never a `${oldName}_idx_` prefix
|
|
135
|
+
// scan, which would also match a sibling table literally named
|
|
136
|
+
// `${oldName}_idx_<x>` (its data store) and relocate its keys.
|
|
137
|
+
const pairs = [
|
|
138
|
+
{ old: oldDataStoreName, new: newDataStoreName },
|
|
139
|
+
];
|
|
140
|
+
for (const indexName of indexNames) {
|
|
141
|
+
pairs.push({
|
|
142
|
+
old: buildIndexStoreName(schemaName, oldName, indexName),
|
|
143
|
+
new: buildIndexStoreName(schemaName, newName, indexName),
|
|
144
|
+
});
|
|
120
145
|
}
|
|
121
|
-
//
|
|
122
|
-
|
|
146
|
+
// Open destination sublevels and assert each is empty BEFORE moving anything.
|
|
147
|
+
// A non-empty (or already-open) destination is a silent clobber/merge — this
|
|
148
|
+
// is the backstop equivalent of the prior fs "destination already exists"
|
|
149
|
+
// guard (e.g. an index relocating onto a sibling table's data store).
|
|
150
|
+
const destSublevels = new Map();
|
|
123
151
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
152
|
+
for (const pair of pairs) {
|
|
153
|
+
if (this.stores.has(pair.new)) {
|
|
154
|
+
throw new Error(`Cannot rename '${oldName}' to '${newName}': destination store '${pair.new}' already open`);
|
|
155
|
+
}
|
|
156
|
+
const dest = this.openSublevel(root, pair.new);
|
|
157
|
+
await dest.open();
|
|
158
|
+
if (await sublevelHasAnyKey(dest)) {
|
|
159
|
+
throw new Error(`Cannot rename '${oldName}' to '${newName}': destination store '${pair.new}' already exists`);
|
|
160
|
+
}
|
|
161
|
+
destSublevels.set(pair.new, dest);
|
|
162
|
+
}
|
|
163
|
+
// Relocate every pair's keys in ONE chained batch over the shared root:
|
|
164
|
+
// put → new sublevel, del → old sublevel. A single write() is atomic and
|
|
165
|
+
// durable, so the rename is all-or-nothing across data + every index.
|
|
166
|
+
const batch = root.batch();
|
|
167
|
+
for (const pair of pairs) {
|
|
168
|
+
const oldStore = await this.getOrCreateStore(pair.old);
|
|
169
|
+
const oldSublevel = this.sublevelByStore.get(oldStore);
|
|
170
|
+
const dest = destSublevels.get(pair.new);
|
|
171
|
+
for await (const { key, value } of oldStore.iterate()) {
|
|
172
|
+
batch.put(key, value, { sublevel: dest });
|
|
173
|
+
batch.del(key, { sublevel: oldSublevel });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (batch.length > 0) {
|
|
177
|
+
await batch.write({ sync: this.syncCommits });
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
await batch.close();
|
|
181
|
+
}
|
|
182
|
+
// Drop old handles so subsequent getStore/getIndexStore open fresh
|
|
183
|
+
// sublevels under the new name (the old keyspaces are now empty).
|
|
184
|
+
for (const pair of pairs) {
|
|
185
|
+
await this.closeStoreByName(pair.old);
|
|
131
186
|
}
|
|
132
187
|
}
|
|
133
|
-
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
|
|
188
|
+
finally {
|
|
189
|
+
// Close the temporary destination handles; the next getStore(newName)
|
|
190
|
+
// opens and caches a fresh sublevel over the now-populated keyspace.
|
|
191
|
+
for (const dest of destSublevels.values()) {
|
|
192
|
+
await dest.close().catch(() => { });
|
|
193
|
+
}
|
|
138
194
|
}
|
|
139
195
|
}
|
|
140
|
-
async deleteTableStores(schemaName, tableName) {
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const indexStoreNames = [];
|
|
152
|
-
for (const name of this.stores.keys()) {
|
|
153
|
-
if (name.startsWith(indexPrefix))
|
|
154
|
-
indexStoreNames.push(name);
|
|
155
|
-
}
|
|
156
|
-
for (const name of indexStoreNames) {
|
|
157
|
-
const indexPath = this.storePaths.get(name);
|
|
158
|
-
await this.closeStoreByName(name);
|
|
159
|
-
if (indexPath)
|
|
160
|
-
await removeDir(indexPath);
|
|
161
|
-
}
|
|
162
|
-
// Also sweep any on-disk index directories for this table that were never opened
|
|
163
|
-
// in this session (e.g. after a process restart followed by a DROP).
|
|
164
|
-
const schemaDir = path.join(this.basePath, schemaName);
|
|
165
|
-
const indexDirPrefix = `${tableName}${STORE_SUFFIX.INDEX}`;
|
|
166
|
-
try {
|
|
167
|
-
const entries = await fs.promises.readdir(schemaDir);
|
|
168
|
-
for (const entry of entries) {
|
|
169
|
-
if (entry.startsWith(indexDirPrefix)) {
|
|
170
|
-
await removeDir(path.join(schemaDir, entry));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
196
|
+
async deleteTableStores(schemaName, tableName, indexNames) {
|
|
197
|
+
// Clear and drop the data store's keyspace.
|
|
198
|
+
await this.clearAndDropStore(buildDataStoreName(schemaName, tableName));
|
|
199
|
+
// Stats live in the unified __stats__ store; the individual stats entry is
|
|
200
|
+
// removed by the calling code (StoreModule), not by clearing a store.
|
|
201
|
+
// Clear exactly the table's index stores (by name). Built via
|
|
202
|
+
// buildIndexStoreName from the authoritative schema index list — never a
|
|
203
|
+
// `${tableName}_idx_` prefix scan, which would also match a sibling table
|
|
204
|
+
// literally named `${tableName}_idx_<x>` and destroy its data.
|
|
205
|
+
for (const indexName of indexNames) {
|
|
206
|
+
await this.clearAndDropStore(buildIndexStoreName(schemaName, tableName, indexName));
|
|
173
207
|
}
|
|
174
|
-
|
|
175
|
-
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Open an atomic batch across this provider's sublevels, or undefined when the
|
|
211
|
+
* shared root has not been opened yet (no stores exist → nothing to commit).
|
|
212
|
+
*
|
|
213
|
+
* All sublevels share one physical LevelDB, so a single chained batch
|
|
214
|
+
* (`root.batch()…write()`) with each op targeting its sublevel commits them
|
|
215
|
+
* atomically and durably. The transaction coordinator uses this to commit a
|
|
216
|
+
* table's data + secondary-index stores in one physical batch, closing the
|
|
217
|
+
* crash window where a per-store loop could leave them divergent.
|
|
218
|
+
*
|
|
219
|
+
* In practice the coordinator only calls this once it has pending ops — which
|
|
220
|
+
* means stores (hence the root) were already opened — so the undefined branch
|
|
221
|
+
* is defensive (the coordinator falls back to per-store `batch()`).
|
|
222
|
+
*/
|
|
223
|
+
beginAtomicBatch() {
|
|
224
|
+
const root = this.root;
|
|
225
|
+
if (!root)
|
|
226
|
+
return undefined;
|
|
227
|
+
return new LevelDBAtomicBatch(root, (store) => this.resolveSublevel(store), this.syncCommits);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Map a {@link KVStore} handle this provider handed out back to its sublevel.
|
|
231
|
+
* A handle not produced by this provider (wrong type, or from another provider)
|
|
232
|
+
* is absent from the ownership map — a programming error.
|
|
233
|
+
*/
|
|
234
|
+
resolveSublevel(store) {
|
|
235
|
+
const sublevel = this.sublevelByStore.get(store);
|
|
236
|
+
if (!sublevel) {
|
|
237
|
+
throw new QuereusError('AtomicBatch received a KVStore handle not produced by this provider', StatusCode.MISUSE);
|
|
176
238
|
}
|
|
239
|
+
return sublevel;
|
|
177
240
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
|
|
241
|
+
/** Open (memoized) the shared physical root database. */
|
|
242
|
+
async getRoot() {
|
|
243
|
+
if (this.root)
|
|
244
|
+
return this.root;
|
|
245
|
+
if (!this.rootOpening) {
|
|
246
|
+
const db = new ClassicLevel(this.basePath, {
|
|
247
|
+
keyEncoding: 'view',
|
|
248
|
+
valueEncoding: 'view',
|
|
183
249
|
createIfMissing: this.createIfMissing,
|
|
184
250
|
});
|
|
185
|
-
this.
|
|
186
|
-
|
|
251
|
+
this.rootOpening = db.open().then(() => {
|
|
252
|
+
this.root = db;
|
|
253
|
+
this.rootOpening = null;
|
|
254
|
+
return db;
|
|
255
|
+
}).catch(err => {
|
|
256
|
+
this.rootOpening = null;
|
|
257
|
+
throw err;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return this.rootOpening;
|
|
261
|
+
}
|
|
262
|
+
/** Create a sublevel handle over the shared root, with the store's byte encodings. */
|
|
263
|
+
openSublevel(root, storeName) {
|
|
264
|
+
return root.sublevel(encodeSublevelName(storeName), {
|
|
265
|
+
keyEncoding: 'view',
|
|
266
|
+
valueEncoding: 'view',
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
async getOrCreateStore(storeName) {
|
|
270
|
+
const existing = this.stores.get(storeName);
|
|
271
|
+
if (existing && !existing.isClosed())
|
|
272
|
+
return existing;
|
|
273
|
+
if (existing) {
|
|
274
|
+
// A handle handed out earlier was closed out-of-band (e.g. the StoreTable's
|
|
275
|
+
// releaseIndexStore closes the index handle before dropIndex calls
|
|
276
|
+
// deleteIndexStore). Evict the stale entry and reopen a fresh sublevel.
|
|
277
|
+
this.stores.delete(storeName);
|
|
278
|
+
}
|
|
279
|
+
// Share a single in-flight open across concurrent callers for the same store
|
|
280
|
+
// name so we cache exactly one handle (and one sublevel) per name.
|
|
281
|
+
let opening = this.storeOpening.get(storeName);
|
|
282
|
+
if (!opening) {
|
|
283
|
+
opening = this.openSublevelStore(storeName).then(store => {
|
|
284
|
+
this.stores.set(storeName, store);
|
|
285
|
+
this.storeOpening.delete(storeName);
|
|
286
|
+
return store;
|
|
287
|
+
}).catch(err => {
|
|
288
|
+
this.storeOpening.delete(storeName);
|
|
289
|
+
throw err;
|
|
290
|
+
});
|
|
291
|
+
this.storeOpening.set(storeName, opening);
|
|
187
292
|
}
|
|
293
|
+
return opening;
|
|
294
|
+
}
|
|
295
|
+
async openSublevelStore(storeName) {
|
|
296
|
+
const root = await this.getRoot();
|
|
297
|
+
const sublevel = this.openSublevel(root, storeName);
|
|
298
|
+
await sublevel.open();
|
|
299
|
+
const store = LevelDBStore.overSublevel(sublevel);
|
|
300
|
+
this.sublevelByStore.set(store, sublevel);
|
|
188
301
|
return store;
|
|
189
302
|
}
|
|
190
303
|
async closeStoreByName(storeName) {
|
|
191
304
|
const store = this.stores.get(storeName);
|
|
192
305
|
if (store) {
|
|
193
|
-
// Remove from
|
|
306
|
+
// Remove from the map before awaiting close, so a concurrent
|
|
194
307
|
// getOrCreateStore cannot observe a store that is about to be closed.
|
|
195
308
|
this.stores.delete(storeName);
|
|
196
|
-
|
|
197
|
-
await store.close();
|
|
309
|
+
await store.close(); // drops the sublevel handle; the shared root stays open
|
|
198
310
|
}
|
|
199
311
|
}
|
|
312
|
+
/** Clear a store's keyspace (sublevel.clear) and drop its cached handle. */
|
|
313
|
+
async clearAndDropStore(storeName) {
|
|
314
|
+
const store = await this.getOrCreateStore(storeName);
|
|
315
|
+
await store.clear();
|
|
316
|
+
await this.closeStoreByName(storeName);
|
|
317
|
+
}
|
|
200
318
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
async function pathExists(p) {
|
|
205
|
-
try {
|
|
206
|
-
await fs.promises.access(p);
|
|
319
|
+
/** True if the sublevel has at least one key. */
|
|
320
|
+
async function sublevelHasAnyKey(sublevel) {
|
|
321
|
+
for await (const _key of sublevel.keys({ limit: 1 })) {
|
|
207
322
|
return true;
|
|
208
323
|
}
|
|
209
|
-
|
|
210
|
-
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* {@link AtomicBatch} over the shared root's chained batch.
|
|
328
|
+
*
|
|
329
|
+
* Every op targets its store's sublevel via the chained-batch `{ sublevel }`
|
|
330
|
+
* option, so a single `write()` commits across all referenced sublevels in one
|
|
331
|
+
* atomic, durable physical commit. Handles are mapped to sublevels by the
|
|
332
|
+
* provider's `resolveSublevel`.
|
|
333
|
+
*/
|
|
334
|
+
class LevelDBAtomicBatch {
|
|
335
|
+
resolveSublevel;
|
|
336
|
+
sync;
|
|
337
|
+
batch;
|
|
338
|
+
constructor(root, resolveSublevel, sync) {
|
|
339
|
+
this.resolveSublevel = resolveSublevel;
|
|
340
|
+
this.sync = sync;
|
|
341
|
+
this.batch = root.batch();
|
|
342
|
+
}
|
|
343
|
+
put(store, key, value) {
|
|
344
|
+
this.batch.put(key, value, { sublevel: this.resolveSublevel(store) });
|
|
345
|
+
}
|
|
346
|
+
delete(store, key) {
|
|
347
|
+
this.batch.del(key, { sublevel: this.resolveSublevel(store) });
|
|
348
|
+
}
|
|
349
|
+
async write() {
|
|
350
|
+
if (this.batch.length === 0) {
|
|
351
|
+
// Free the chained batch's resources without a no-op commit.
|
|
352
|
+
await this.batch.close();
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
// sync=true → fsync the commit so a committed transaction survives power loss
|
|
356
|
+
// (the crash-safe commit this layout exists to provide). One fsync per commit.
|
|
357
|
+
await this.batch.write({ sync: this.sync });
|
|
358
|
+
}
|
|
359
|
+
clear() {
|
|
360
|
+
this.batch.clear();
|
|
211
361
|
}
|
|
212
362
|
}
|
|
213
363
|
/**
|
package/dist/src/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"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"}
|