@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 CHANGED
@@ -1,166 +1,197 @@
1
- # @quereus/plugin-leveldb
2
-
3
- LevelDB storage plugin for Quereus. Provides persistent storage for Node.js environments using the [`@quereus/store`](../quereus-store/) module.
4
-
5
- ## Features
6
-
7
- - **Fast**: LevelDB offers excellent read/write performance for key-value workloads
8
- - **Transaction isolation**: Read-your-own-writes and snapshot isolation by default
9
- - **Sorted keys**: Efficient range queries with ordered iteration
10
- - **ACID batches**: Atomic writes across multiple keys
11
- - **Compression**: Built-in Snappy compression for reduced disk usage
12
-
13
- ## Installation
14
-
15
- ```bash
16
- npm install @quereus/plugin-leveldb @quereus/store @quereus/isolation
17
- ```
18
-
19
- ## Quick Start
20
-
21
- ### With registerPlugin (Recommended)
22
-
23
- ```typescript
24
- import { Database, registerPlugin } from '@quereus/quereus';
25
- import leveldbPlugin from '@quereus/plugin-leveldb/plugin';
26
-
27
- const db = new Database();
28
- await registerPlugin(db, leveldbPlugin, { basePath: './data' });
29
-
30
- await db.exec(`
31
- create table users (id integer primary key, name text)
32
- using store
33
- `);
34
-
35
- // Full transaction isolation enabled by default
36
- await db.exec('BEGIN');
37
- await db.exec(`INSERT INTO users VALUES (1, 'Alice')`);
38
- const user = await db.get('SELECT * FROM users WHERE id = 1'); // Sees uncommitted insert
39
- await db.exec('COMMIT');
40
- ```
41
-
42
- ### Disabling Isolation
43
-
44
- If you need maximum performance and don't require read-your-own-writes within transactions:
45
-
46
- ```typescript
47
- await registerPlugin(db, leveldbPlugin, {
48
- basePath: './data',
49
- isolation: false // Disable isolation layer
50
- });
51
- ```
52
-
53
- ### Direct Usage with Provider
54
-
55
- ```typescript
56
- import { Database } from '@quereus/quereus';
57
- import { createLevelDBProvider } from '@quereus/plugin-leveldb';
58
- import { createIsolatedStoreModule } from '@quereus/store';
59
-
60
- const db = new Database();
61
- const provider = createLevelDBProvider({ basePath: './data' });
62
-
63
- // With isolation (recommended)
64
- const storeModule = createIsolatedStoreModule({ provider });
65
- db.registerModule('store', storeModule);
66
-
67
- await db.exec(`
68
- create table users (id integer primary key, name text)
69
- using store
70
- `);
71
- ```
72
-
73
- ## API
74
-
75
- ### LevelDBStore
76
-
77
- Low-level KVStore implementation:
78
-
79
- ```typescript
80
- import { LevelDBStore } from '@quereus/plugin-leveldb';
81
-
82
- const store = await LevelDBStore.open({ path: './data/mystore' });
83
-
84
- await store.put(key, value);
85
- const data = await store.get(key);
86
- await store.delete(key);
87
-
88
- // Range iteration
89
- for await (const { key, value } of store.iterate({ gte: startKey, lt: endKey })) {
90
- console.log(key, value);
91
- }
92
-
93
- // Batch writes
94
- const batch = store.batch();
95
- batch.put(key1, value1);
96
- batch.put(key2, value2);
97
- batch.delete(key3);
98
- await batch.write();
99
-
100
- await store.close();
101
- ```
102
-
103
- ### LevelDBProvider
104
-
105
- Factory for managing multiple stores:
106
-
107
- ```typescript
108
- import { createLevelDBProvider } from '@quereus/plugin-leveldb';
109
-
110
- const provider = createLevelDBProvider({ basePath: './data' });
111
-
112
- const userStore = await provider.getStore('main', 'users'); // ./data/main/users
113
- const catalogStore = await provider.getCatalogStore(); // ./data/__catalog__
114
-
115
- await provider.closeStore('main', 'users');
116
- await provider.closeAll();
117
- ```
118
-
119
- ## Configuration
120
-
121
- ### Plugin Settings
122
-
123
- | Setting | Type | Default | Description |
124
- |---------|------|---------|-------------|
125
- | `basePath` | string | `'./data'` | Base directory for all stores |
126
- | `createIfMissing` | boolean | `true` | Create directories if they don't exist |
127
- | `moduleName` | string | `'store'` | Name to register the virtual table module under |
128
-
129
- ### LevelDBStore Options
130
-
131
- | Option | Type | Default | Description |
132
- |--------|------|---------|-------------|
133
- | `path` | string | required | Directory path for the database |
134
- | `createIfMissing` | boolean | `true` | Create database if it doesn't exist |
135
-
136
- ## Example with Transactions
137
-
138
- ```typescript
139
- import { Database, registerPlugin } from '@quereus/quereus';
140
- import leveldbPlugin from '@quereus/plugin-leveldb/plugin';
141
-
142
- const db = new Database();
143
- await registerPlugin(db, leveldbPlugin, { basePath: './data' });
144
-
145
- await db.exec(`create table accounts (id integer primary key, balance real) using store`);
146
-
147
- await db.exec('begin');
148
- try {
149
- await db.exec(`update accounts set balance = balance - 100 where id = 1`);
150
- await db.exec(`update accounts set balance = balance + 100 where id = 2`);
151
- await db.exec('commit');
152
- } catch (e) {
153
- await db.exec('rollback');
154
- throw e;
155
- }
156
- ```
157
-
158
- ## Related Packages
159
-
160
- - [`@quereus/store`](../quereus-store/) - Core storage module (StoreModule, StoreTable)
161
- - [`@quereus/plugin-indexeddb`](../quereus-plugin-indexeddb/) - IndexedDB plugin for browsers
162
-
163
- ## License
164
-
165
- MIT
166
-
1
+ # @quereus/plugin-leveldb
2
+
3
+ LevelDB storage plugin for Quereus. Provides persistent storage for Node.js environments using the [`@quereus/store`](../quereus-store/) module.
4
+
5
+ ## Features
6
+
7
+ - **Fast**: LevelDB offers excellent read/write performance for key-value workloads
8
+ - **Transaction isolation**: Read-your-own-writes and snapshot isolation by default
9
+ - **Sorted keys**: Efficient range queries with ordered iteration
10
+ - **Crash-safe commits**: A whole transaction's data + secondary-index writes commit in one atomic, durable LevelDB batch (see [Storage layout](#storage-layout))
11
+ - **Compression**: Built-in Snappy compression for reduced disk usage
12
+
13
+ ## Storage layout
14
+
15
+ All of a database's stores live inside **one physical LevelDB** at `basePath`,
16
+ each as a [sublevel](https://github.com/Level/abstract-level#sublevel) keyed by
17
+ its store name:
18
+
19
+ | Logical store | Sublevel name |
20
+ |---|---|
21
+ | Table data | `{schema}.{table}` |
22
+ | Secondary index | `{schema}.{table}_idx_{name}` |
23
+ | Unified stats | `__stats__` |
24
+ | Catalog (DDL) | `__catalog__` |
25
+
26
+ Because every sublevel shares one physical store, a single chained batch commits
27
+ across all of a table's sublevels (data + every secondary index) **atomically and
28
+ durably** — closing the crash window where a per-store commit loop could leave a
29
+ table's rows and its indexes divergent on disk. By default each commit is
30
+ `fsync`'d so it survives power loss; see [`syncCommits`](#plugin-settings).
31
+
32
+ > **Hard cutover (no on-disk migration).** This shared-root layout is the only
33
+ > LevelDB layout. Databases written by the older per-directory layout
34
+ > (`{basePath}/{schema}/{table}`, a separate LevelDB per table) are **not** read
35
+ > by this version and must be re-created. Pre-1.0 dev data is expected to be
36
+ > thrown away; there is no migration importer.
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ npm install @quereus/plugin-leveldb @quereus/store @quereus/isolation
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ### With registerPlugin (Recommended)
47
+
48
+ ```typescript
49
+ import { Database, registerPlugin } from '@quereus/quereus';
50
+ import leveldbPlugin from '@quereus/plugin-leveldb/plugin';
51
+
52
+ const db = new Database();
53
+ await registerPlugin(db, leveldbPlugin, { basePath: './data' });
54
+
55
+ await db.exec(`
56
+ create table users (id integer primary key, name text)
57
+ using store
58
+ `);
59
+
60
+ // Full transaction isolation enabled by default
61
+ await db.exec('BEGIN');
62
+ await db.exec(`INSERT INTO users VALUES (1, 'Alice')`);
63
+ const user = await db.get('SELECT * FROM users WHERE id = 1'); // Sees uncommitted insert
64
+ await db.exec('COMMIT');
65
+ ```
66
+
67
+ ### Disabling Isolation
68
+
69
+ If you need maximum performance and don't require read-your-own-writes within transactions:
70
+
71
+ ```typescript
72
+ await registerPlugin(db, leveldbPlugin, {
73
+ basePath: './data',
74
+ isolation: false // Disable isolation layer
75
+ });
76
+ ```
77
+
78
+ ### Direct Usage with Provider
79
+
80
+ ```typescript
81
+ import { Database } from '@quereus/quereus';
82
+ import { createLevelDBProvider } from '@quereus/plugin-leveldb';
83
+ import { createIsolatedStoreModule } from '@quereus/store';
84
+
85
+ const db = new Database();
86
+ const provider = createLevelDBProvider({ basePath: './data' });
87
+
88
+ // With isolation (recommended)
89
+ const storeModule = createIsolatedStoreModule({ provider });
90
+ db.registerModule('store', storeModule);
91
+
92
+ await db.exec(`
93
+ create table users (id integer primary key, name text)
94
+ using store
95
+ `);
96
+ ```
97
+
98
+ ## API
99
+
100
+ ### LevelDBStore
101
+
102
+ Low-level KVStore implementation. `LevelDBStore.open()` opens a **standalone**
103
+ single physical LevelDB database — useful for one-off key-value stores (e.g. sync
104
+ metadata). The multi-table StoreModule backend does not use this directly; it
105
+ opens one shared root and hands out sublevel-backed stores via `LevelDBProvider`.
106
+
107
+ ```typescript
108
+ import { LevelDBStore } from '@quereus/plugin-leveldb';
109
+
110
+ const store = await LevelDBStore.open({ path: './data/mystore' });
111
+
112
+ await store.put(key, value);
113
+ const data = await store.get(key);
114
+ await store.delete(key);
115
+
116
+ // Range iteration
117
+ for await (const { key, value } of store.iterate({ gte: startKey, lt: endKey })) {
118
+ console.log(key, value);
119
+ }
120
+
121
+ // Batch writes
122
+ const batch = store.batch();
123
+ batch.put(key1, value1);
124
+ batch.put(key2, value2);
125
+ batch.delete(key3);
126
+ await batch.write();
127
+
128
+ await store.close();
129
+ ```
130
+
131
+ ### LevelDBProvider
132
+
133
+ Factory for managing multiple stores:
134
+
135
+ ```typescript
136
+ import { createLevelDBProvider } from '@quereus/plugin-leveldb';
137
+
138
+ const provider = createLevelDBProvider({ basePath: './data' });
139
+
140
+ // All stores are sublevels of the single LevelDB at ./data
141
+ const userStore = await provider.getStore('main', 'users'); // sublevel main.users
142
+ const catalogStore = await provider.getCatalogStore(); // sublevel __catalog__
143
+
144
+ await provider.closeStore('main', 'users'); // drops the sublevel handle
145
+ await provider.closeAll(); // closes the shared root
146
+ ```
147
+
148
+ ## Configuration
149
+
150
+ ### Plugin Settings
151
+
152
+ | Setting | Type | Default | Description |
153
+ |---------|------|---------|-------------|
154
+ | `basePath` | string | `'./data'` | Directory of the single shared LevelDB database |
155
+ | `createIfMissing` | boolean | `true` | Create the database if it doesn't exist |
156
+ | `syncCommits` | boolean | `true` | `fsync` each transaction commit so it survives power loss (slower commits when on) |
157
+ | `moduleName` | string | `'store'` | Name to register the virtual table module under |
158
+ | `isolation` | boolean | `true` | Wrap with the isolation layer (read-your-own-writes, snapshot isolation) |
159
+
160
+ ### LevelDBStore Options (standalone `open`)
161
+
162
+ | Option | Type | Default | Description |
163
+ |--------|------|---------|-------------|
164
+ | `path` | string | required | Directory path for the database |
165
+ | `createIfMissing` | boolean | `true` | Create database if it doesn't exist |
166
+
167
+ ## Example with Transactions
168
+
169
+ ```typescript
170
+ import { Database, registerPlugin } from '@quereus/quereus';
171
+ import leveldbPlugin from '@quereus/plugin-leveldb/plugin';
172
+
173
+ const db = new Database();
174
+ await registerPlugin(db, leveldbPlugin, { basePath: './data' });
175
+
176
+ await db.exec(`create table accounts (id integer primary key, balance real) using store`);
177
+
178
+ await db.exec('begin');
179
+ try {
180
+ await db.exec(`update accounts set balance = balance - 100 where id = 1`);
181
+ await db.exec(`update accounts set balance = balance + 100 where id = 2`);
182
+ await db.exec('commit');
183
+ } catch (e) {
184
+ await db.exec('rollback');
185
+ throw e;
186
+ }
187
+ ```
188
+
189
+ ## Related Packages
190
+
191
+ - [`@quereus/store`](../quereus-store/) - Core storage module (StoreModule, StoreTable)
192
+ - [`@quereus/plugin-indexeddb`](../quereus-plugin-indexeddb/) - IndexedDB plugin for browsers
193
+
194
+ ## License
195
+
196
+ MIT
197
+
@@ -10,16 +10,23 @@ import { StoreModule } from '@quereus/store';
10
10
  */
11
11
  export interface LevelDBPluginConfig {
12
12
  /**
13
- * Base path for all LevelDB stores.
14
- * Each table gets a subdirectory under this path.
13
+ * Base path for the single shared LevelDB database. Every table, index, the
14
+ * catalog, and stats live as sublevels inside this one physical store.
15
15
  * @default './data'
16
16
  */
17
17
  basePath?: string;
18
18
  /**
19
- * Create directories if they don't exist.
19
+ * Create the database if it doesn't exist.
20
20
  * @default true
21
21
  */
22
22
  createIfMissing?: boolean;
23
+ /**
24
+ * fsync each transaction commit before resolving, so a committed transaction
25
+ * survives power loss. The cost is one fsync per commit; set false to trade
26
+ * durability for lower commit latency.
27
+ * @default true
28
+ */
29
+ syncCommits?: boolean;
23
30
  /**
24
31
  * Module name to register. Tables are created with `USING <moduleName>`.
25
32
  * @default 'store'
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAA6B,MAAM,gBAAgB,CAAC;AAGxE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC/B,GAAG,EAAE,QAAQ,EACb,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAM;;;;;EAwBrC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAA6B,MAAM,gBAAgB,CAAC;AAGxE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC/B,GAAG,EAAE,QAAQ,EACb,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAM;;;;;EA0BrC"}
@@ -13,9 +13,11 @@ export default function register(_db, config = {}) {
13
13
  const createIfMissing = config.createIfMissing !== false;
14
14
  const moduleName = config.moduleName ?? 'store';
15
15
  const isolation = config.isolation ?? true;
16
+ const syncCommits = config.syncCommits !== false;
16
17
  const provider = new LevelDBProvider({
17
18
  basePath,
18
19
  createIfMissing,
20
+ syncCommits,
19
21
  });
20
22
  const storeModule = isolation
21
23
  ? createIsolatedStoreModule({ provider })
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAiChD;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC/B,GAAa,EACb,SAAmC,EAAE;IAErC,MAAM,QAAQ,GAAI,MAAM,CAAC,QAAmB,IAAI,QAAQ,CAAC;IACzD,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,KAAK,KAAK,CAAC;IACzD,MAAM,UAAU,GAAI,MAAM,CAAC,UAAqB,IAAI,OAAO,CAAC;IAC5D,MAAM,SAAS,GAAI,MAAM,CAAC,SAAqB,IAAI,IAAI,CAAC;IAExD,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC;QACpC,QAAQ;QACR,eAAe;KACf,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,SAAS;QAC5B,CAAC,CAAC,yBAAyB,CAAC,EAAE,QAAQ,EAAE,CAAC;QACzC,CAAC,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;IAE7B,OAAO;QACN,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,WAAW;aACnB;SACD;KACD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAyChD;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC/B,GAAa,EACb,SAAmC,EAAE;IAErC,MAAM,QAAQ,GAAI,MAAM,CAAC,QAAmB,IAAI,QAAQ,CAAC;IACzD,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,KAAK,KAAK,CAAC;IACzD,MAAM,UAAU,GAAI,MAAM,CAAC,UAAqB,IAAI,OAAO,CAAC;IAC5D,MAAM,SAAS,GAAI,MAAM,CAAC,SAAqB,IAAI,IAAI,CAAC;IACxD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC;IAEjD,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC;QACpC,QAAQ;QACR,eAAe;QACf,WAAW;KACX,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,SAAS;QAC5B,CAAC,CAAC,yBAAyB,CAAC,EAAE,QAAQ,EAAE,CAAC;QACzC,CAAC,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;IAE7B,OAAO;QACN,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,WAAW;aACnB;SACD;KACD,CAAC;AACH,CAAC"}
@@ -1,45 +1,73 @@
1
1
  /**
2
- * LevelDB KVStore provider implementation.
2
+ * LevelDB KVStoreProvider — shared-root layout.
3
3
  *
4
- * Manages LevelDB stores for the StoreModule.
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
- * Storage naming convention:
7
- * {basePath}/{schema}/{table} - Data store (row data)
8
- * {basePath}/{schema}/{table}_idx_{name} - Index store (secondary indexes)
9
- * {basePath}/__stats__ - Unified stats store (row counts for all tables)
10
- * {basePath}/__catalog__ - Catalog store (DDL metadata)
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 type { KVStore, KVStoreProvider } from '@quereus/store';
22
+ import type { AtomicBatch, KVStore, KVStoreProvider } from '@quereus/store';
13
23
  /**
14
24
  * Options for creating a LevelDB provider.
15
25
  */
16
26
  export interface LevelDBProviderOptions {
17
27
  /**
18
- * Base path for all LevelDB stores.
19
- * Each table gets a subdirectory under this path.
28
+ * Base path for the single shared LevelDB database. Every table, index, the
29
+ * catalog, and stats live as sublevels inside this one physical store.
20
30
  */
21
31
  basePath: string;
22
32
  /**
23
- * Create directories if they don't exist.
33
+ * Create the database if it doesn't exist.
24
34
  * @default true
25
35
  */
26
36
  createIfMissing?: boolean;
37
+ /**
38
+ * fsync each atomic transaction commit (the chained batch issued by
39
+ * {@link LevelDBProvider.beginAtomicBatch}) before resolving. Default true —
40
+ * a committed transaction then survives power loss, which is the crash-safe
41
+ * guarantee this layout exists to provide. The cost is one fsync per commit;
42
+ * set false to trade durability for lower commit latency.
43
+ * @default true
44
+ */
45
+ syncCommits?: boolean;
27
46
  }
28
47
  /**
29
- * LevelDB implementation of KVStoreProvider.
30
- *
31
- * Creates separate LevelDB databases for each table, stored
32
- * in subdirectories under the configured base path.
48
+ * LevelDB implementation of KVStoreProvider over a single shared root with one
49
+ * sublevel per logical store.
33
50
  */
34
51
  export declare class LevelDBProvider implements KVStoreProvider {
35
52
  private basePath;
36
53
  private createIfMissing;
54
+ private syncCommits;
55
+ /** The shared physical root, once opened. */
56
+ private root;
57
+ /** Memoized in-flight root open so concurrent first-opens share one handle. */
58
+ private rootOpening;
59
+ /** Cached store handles, keyed by store (sublevel) name. */
37
60
  private stores;
38
- private storePaths;
39
- private catalogStore;
40
- private statsStore;
61
+ /** In-flight sublevel opens, keyed by store name, so concurrent callers dedupe. */
62
+ private storeOpening;
63
+ /**
64
+ * Sublevel + ownership proof for every store this provider produced. Used by the
65
+ * atomic batch to map a {@link KVStore} handle back to its sublevel and to reject
66
+ * a foreign handle (a non-LevelDB store, or one from another provider, is absent).
67
+ */
68
+ private sublevelByStore;
41
69
  constructor(options: LevelDBProviderOptions);
42
- getStore(schemaName: string, tableName: string, options?: Record<string, unknown>): Promise<KVStore>;
70
+ getStore(schemaName: string, tableName: string, _options?: Record<string, unknown>): Promise<KVStore>;
43
71
  getIndexStore(schemaName: string, tableName: string, indexName: string): Promise<KVStore>;
44
72
  getStatsStore(_schemaName: string, _tableName: string): Promise<KVStore>;
45
73
  getCatalogStore(): Promise<KVStore>;
@@ -47,10 +75,38 @@ export declare class LevelDBProvider implements KVStoreProvider {
47
75
  closeIndexStore(schemaName: string, tableName: string, indexName: string): Promise<void>;
48
76
  closeAll(): Promise<void>;
49
77
  deleteIndexStore(schemaName: string, tableName: string, indexName: string): Promise<void>;
50
- renameTableStores(schemaName: string, oldName: string, newName: string): Promise<void>;
51
- deleteTableStores(schemaName: string, tableName: string): Promise<void>;
78
+ renameTableStores(schemaName: string, oldName: string, newName: string, indexNames: readonly string[]): Promise<void>;
79
+ deleteTableStores(schemaName: string, tableName: string, indexNames: readonly string[]): Promise<void>;
80
+ /**
81
+ * Open an atomic batch across this provider's sublevels, or undefined when the
82
+ * shared root has not been opened yet (no stores exist → nothing to commit).
83
+ *
84
+ * All sublevels share one physical LevelDB, so a single chained batch
85
+ * (`root.batch()…write()`) with each op targeting its sublevel commits them
86
+ * atomically and durably. The transaction coordinator uses this to commit a
87
+ * table's data + secondary-index stores in one physical batch, closing the
88
+ * crash window where a per-store loop could leave them divergent.
89
+ *
90
+ * In practice the coordinator only calls this once it has pending ops — which
91
+ * means stores (hence the root) were already opened — so the undefined branch
92
+ * is defensive (the coordinator falls back to per-store `batch()`).
93
+ */
94
+ beginAtomicBatch(): AtomicBatch | undefined;
95
+ /**
96
+ * Map a {@link KVStore} handle this provider handed out back to its sublevel.
97
+ * A handle not produced by this provider (wrong type, or from another provider)
98
+ * is absent from the ownership map — a programming error.
99
+ */
100
+ private resolveSublevel;
101
+ /** Open (memoized) the shared physical root database. */
102
+ private getRoot;
103
+ /** Create a sublevel handle over the shared root, with the store's byte encodings. */
104
+ private openSublevel;
52
105
  private getOrCreateStore;
106
+ private openSublevelStore;
53
107
  private closeStoreByName;
108
+ /** Clear a store's keyspace (sublevel.clear) and drop its cached handle. */
109
+ private clearAndDropStore;
54
110
  }
55
111
  /**
56
112
  * Create a LevelDB provider with the given options.
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAI/D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,eAAe;IACtD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,UAAU,CAA6B;gBAEnC,OAAO,EAAE,sBAAsB;IAKrC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAMpG,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMzF,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYxE,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAWnC,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhE,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBzB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzF,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDtF,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAuC/D,gBAAgB;YAehB,gBAAgB;CAU9B;AAeD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAEtF"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAuC5E;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,eAAe;IACtD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,WAAW,CAAU;IAE7B,6CAA6C;IAC7C,OAAO,CAAC,IAAI,CAA0B;IACtC,+EAA+E;IAC/E,OAAO,CAAC,WAAW,CAAmC;IAEtD,4DAA4D;IAC5D,OAAO,CAAC,MAAM,CAAmC;IACjD,mFAAmF;IACnF,OAAO,CAAC,YAAY,CAA4C;IAChE;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAoC;gBAE/C,OAAO,EAAE,sBAAsB;IAMrC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrG,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIzF,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxE,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBzB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzF,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA0ErH,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB5G;;;;;;;;;;;;;OAaG;IACH,gBAAgB,IAAI,WAAW,GAAG,SAAS;IAM3C;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAWvB,yDAAyD;YAC3C,OAAO;IAoBrB,sFAAsF;IACtF,OAAO,CAAC,YAAY;YAON,gBAAgB;YA2BhB,iBAAiB;YASjB,gBAAgB;IAU9B,4EAA4E;YAC9D,iBAAiB;CAK/B;AAqDD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAEtF"}