@optimystic/db-p2p-storage-ns 1.14.0 → 1.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.
@@ -1,153 +1,146 @@
1
- import { KvRawStorage, identityForHandle } from '@optimystic/db-p2p';
1
+ import { KvRawStorage, StoreFailedError, SyncDeadlines, WriteGroupDriver, identityForHandle, } from '@optimystic/db-p2p';
2
2
  import { createLogger } from './logger.js';
3
+ import { bumpDurabilityMark } from './sqlite-sync.js';
3
4
  const log = createLogger('storage:sqlite');
5
+ const LAYOUTS = {
6
+ metadata: { keyColumns: ['block_id'], valueColumn: 'value' },
7
+ revisions: { keyColumns: ['block_id', 'rev'], valueColumn: 'action_id' },
8
+ proofs: { keyColumns: ['block_id', 'rev'], valueColumn: 'value' },
9
+ pending: { keyColumns: ['block_id', 'action_id'], valueColumn: 'value' },
10
+ transactions: { keyColumns: ['block_id', 'action_id'], valueColumn: 'value' },
11
+ materialized: { keyColumns: ['block_id', 'action_id'], valueColumn: 'value' },
12
+ };
13
+ const STORES = Object.keys(LAYOUTS);
14
+ const whereKey = (store) => LAYOUTS[store].keyColumns.map(column => `${column} = ?`).join(' AND ');
15
+ const sqlByStore = (build) => Object.fromEntries(STORES.map(store => [store, build(store)]));
16
+ const GET_SQL = sqlByStore(store => `SELECT ${LAYOUTS[store].valueColumn} FROM ${store} WHERE ${whereKey(store)}`);
17
+ const PUT_SQL = sqlByStore(store => {
18
+ const columns = [...LAYOUTS[store].keyColumns, LAYOUTS[store].valueColumn];
19
+ return `INSERT OR REPLACE INTO ${store} (${columns.join(', ')}) VALUES (${columns.map(() => '?').join(', ')})`;
20
+ });
21
+ const DELETE_SQL = sqlByStore(store => `DELETE FROM ${store} WHERE ${whereKey(store)}`);
22
+ /** The key's bind parameters, in the order of its store's key columns. */
23
+ function keyParams(key) {
24
+ switch (key.store) {
25
+ case 'metadata':
26
+ return [key.blockId];
27
+ case 'revisions':
28
+ case 'proofs':
29
+ return [key.blockId, key.rev];
30
+ case 'pending':
31
+ case 'transactions':
32
+ case 'materialized':
33
+ return [key.blockId, key.actionId];
34
+ }
35
+ }
4
36
  /**
5
- * SQLite {@link RawStoreDriver}: the six logical block-storage stores mapped to
6
- * the six relational tables (`metadata`, `revisions`, `pending`, `transactions`,
7
- * `proofs`, `materialized`) with their original columns and keys.
37
+ * SQLite {@link BatchBackend}: the six logical block-storage stores mapped to the six relational
38
+ * tables (`metadata`, `revisions`, `pending`, `transactions`, `proofs`, `materialized`) with their
39
+ * original columns and keys, every batch applied as ONE SQLite transaction. The reads are the
40
+ * former per-write driver's statements unchanged, so the on-disk format did not change with the
41
+ * move to batches.
42
+ *
43
+ * `KvRawStorage` owns all JSON serialization, so this backend only ever reads/writes `Uint8Array`
44
+ * values: the value columns are BLOB and SQLite binds a `Uint8Array` as a BLOB and returns it as a
45
+ * `Uint8Array`, so no codec lives here (a TEXT column would risk UTF-8 coercion corrupting non-ASCII
46
+ * JSON bytes).
47
+ *
48
+ * ### Why a committed batch survives a power cut, and in order
49
+ *
50
+ * `applySchema` (`db.ts`) opens every database in write-ahead-log (WAL) mode under
51
+ * `synchronous = NORMAL`. A commit appends the batch's frames to the one WAL file, each frame
52
+ * checksummed over the frames before it, and recovery stops at the first bad frame; before every
53
+ * checkpoint SQLite syncs the WAL, so the database file never holds later content ahead of earlier
54
+ * content. What a power cut leaves is therefore a prefix of the committed transactions, in commit
55
+ * order — rule 3 of the flush contract on `RawStoreDriver.flush` — and a batch is one transaction,
56
+ * so it survives whole or not at all. A commit under `synchronous = FULL`
57
+ * (`SqliteTransactionOptions.synced`) syncs the WAL at that commit, and the WAL being one
58
+ * append-only file, that sync covers every earlier commit on the database, the key-value store's
59
+ * and the identity helper's included, since all three share one connection. So the sync of a batch
60
+ * is one `FULL` commit — this batch's own when it must be synced at once, a later batch's, or the
61
+ * `durability_mark` bump the deadline timer commits — which is what `durability: 'power-loss'`
62
+ * states.
63
+ *
64
+ * ### How a commit decides
8
65
  *
9
- * `KvRawStorage` now owns all JSON serialization, so this driver only ever
10
- * reads/writes `Uint8Array` values: the value columns are BLOB and SQLite binds
11
- * a `Uint8Array` as a BLOB and returns it as a `Uint8Array`, so no codec lives
12
- * here (a TEXT column would risk UTF-8 coercion corrupting non-ASCII JSON bytes).
13
- * Everything SQLite-specific stays: each CRUD op goes through a prepared
14
- * statement bound once in the constructor; range/list queries drain their rows
15
- * (`.all(...)`) before yielding so no cursor straddles a consumer's `await`; and
16
- * `promote` runs as a single `db.transaction(fn)` — `BEGIN IMMEDIATE; INSERT…;
17
- * DELETE…; COMMIT;` — whose three statements are re-prepared against the OPEN
18
- * transaction so they run on the held mutex slot without re-locking (which would
19
- * deadlock — see `st-nativescript-sqlite-transaction-mutex`).
66
+ * The deadlines, the timer and the backpressure test are the rules of `SyncDeadlines` from
67
+ * `@optimystic/db-p2p`, shared with the file backend. `commit` takes the batch's deadline as it is
68
+ * called and decides whether the transaction is synced BEFORE taking the connection mutex, since
69
+ * the pragma is set as the transaction starts; the bookkeeping — `defer` of a deferred batch,
70
+ * `take` of the cover a synced one settles — runs INSIDE the transaction body, under the mutex, so
71
+ * it is ordered against every other commit and sync: a cover taken there is exactly the batches
72
+ * whose transactions committed earlier, every one of which this `FULL` commit syncs. A deadline
73
+ * that passes between the decision and the mutex only delays that commit's backpressure to the
74
+ * timer, which is due anyway.
75
+ *
76
+ * A read sees a batch as soon as its transaction commits, before it is synced, which `BatchBackend`
77
+ * allows; the overlay above serves the batch until it is durable. The handle is shared with
78
+ * `SqliteKVStore` and `loadOrCreateNSPeerKey`, so `close()` never closes it. Every write of a batch
79
+ * goes through `tx.prepare`, never a class-level statement, which would re-take the mutex the
80
+ * transaction holds and deadlock (see `SqliteDb.transaction`).
20
81
  */
21
- export class SqliteStoreDriver {
82
+ export class SqliteBatchBackend {
22
83
  db;
23
- stmts;
84
+ durability = 'power-loss';
24
85
  // NOTE: identity is the HANDLE object, so two handles opened over the same SQLite FILE read
25
86
  // as two identities. Resolving that would mean naming the underlying database file, which
26
87
  // `SqliteDb` does not expose. The package opener (`ns-opener.ts`) hands out one handle per
27
88
  // file in practice, so this is the reachable case, not the complete one.
28
89
  identity;
29
- constructor(db) {
90
+ /** One point read per store. Reads run off the mutex, so a class-level statement is right here. */
91
+ reads;
92
+ stmts;
93
+ /**
94
+ * Batches committed and not yet synced, in order, each with the `durable` the next sync settles;
95
+ * the earliest deadline among them, with a timer armed for it; and the `window-overrun` episode.
96
+ * A batch's payload is nothing: its transaction has already applied it.
97
+ */
98
+ deadlines;
99
+ fault;
100
+ constructor(db, options = {}) {
30
101
  this.db = db;
31
102
  this.identity = identityForHandle('sqlite-handle', db);
103
+ this.reads = Object.fromEntries(STORES.map(store => [store, db.prepare(GET_SQL[store])]));
32
104
  this.stmts = {
33
- getMetadata: db.prepare('SELECT value FROM metadata WHERE block_id = ?'),
34
- saveMetadata: db.prepare('INSERT OR REPLACE INTO metadata (block_id, value) VALUES (?, ?)'),
35
- getRevision: db.prepare('SELECT action_id FROM revisions WHERE block_id = ? AND rev = ?'),
36
- saveRevision: db.prepare('INSERT OR REPLACE INTO revisions (block_id, rev, action_id) VALUES (?, ?, ?)'),
37
- listRevisionsAsc: db.prepare('SELECT rev, action_id FROM revisions WHERE block_id = ? AND rev BETWEEN ? AND ? ORDER BY rev ASC'),
38
- listRevisionsDesc: db.prepare('SELECT rev, action_id FROM revisions WHERE block_id = ? AND rev BETWEEN ? AND ? ORDER BY rev DESC'),
39
- getPending: db.prepare('SELECT value FROM pending WHERE block_id = ? AND action_id = ?'),
40
- savePending: db.prepare('INSERT OR REPLACE INTO pending (block_id, action_id, value) VALUES (?, ?, ?)'),
41
- deletePending: db.prepare('DELETE FROM pending WHERE block_id = ? AND action_id = ?'),
105
+ listRevisions: db.prepare('SELECT rev, action_id FROM revisions WHERE block_id = ? AND rev BETWEEN ? AND ? ORDER BY rev ASC'),
42
106
  listPending: db.prepare('SELECT action_id FROM pending WHERE block_id = ? ORDER BY action_id ASC'),
43
107
  // metadata.block_id is the PRIMARY KEY, so each row is a distinct block id —
44
108
  // no dedup needed. NOTE: drains the whole metadata table up front; if a peer
45
109
  // ever holds millions of blocks and this SELECT becomes a startup-latency
46
110
  // problem, page it (LIMIT/OFFSET or keyset) — fine at current scale.
47
111
  listBlockIds: db.prepare('SELECT block_id FROM metadata'),
48
- getTransaction: db.prepare('SELECT value FROM transactions WHERE block_id = ? AND action_id = ?'),
49
- saveTransaction: db.prepare('INSERT OR REPLACE INTO transactions (block_id, action_id, value) VALUES (?, ?, ?)'),
50
- getProof: db.prepare('SELECT value FROM proofs WHERE block_id = ? AND rev = ?'),
51
- saveProof: db.prepare('INSERT OR REPLACE INTO proofs (block_id, rev, value) VALUES (?, ?, ?)'),
52
- getMaterialized: db.prepare('SELECT value FROM materialized WHERE block_id = ? AND action_id = ?'),
53
- saveMaterialized: db.prepare('INSERT OR REPLACE INTO materialized (block_id, action_id, value) VALUES (?, ?, ?)'),
54
- deleteMaterialized: db.prepare('DELETE FROM materialized WHERE block_id = ? AND action_id = ?'),
55
112
  pageCount: db.prepare('PRAGMA page_count'),
56
113
  pageSize: db.prepare('PRAGMA page_size'),
57
114
  };
115
+ this.deadlines = new SyncDeadlines({
116
+ onDue: firedAt => this.syncInBackground(firedAt),
117
+ setTimer: options.setTimer,
118
+ log,
119
+ subject: this.identity,
120
+ });
121
+ }
122
+ /** True once a transaction or a sync failed; every later `commit` and `sync` then throws {@link StoreFailedError}. */
123
+ get failed() {
124
+ return this.fault !== undefined;
58
125
  }
59
126
  storeIdentity() {
60
127
  return this.identity;
61
128
  }
62
- // --- metadata ---
63
- async getMetadata(blockId) {
64
- const row = await this.stmts.getMetadata.get(blockId);
65
- return row ? row.value : undefined;
66
- }
67
- async putMetadata(blockId, value) {
68
- await this.stmts.saveMetadata.run(blockId, value);
129
+ // --- reads ---
130
+ async get(key) {
131
+ const row = await this.reads[key.store].get(...keyParams(key));
132
+ return row ? row[LAYOUTS[key.store].valueColumn] : undefined;
69
133
  }
70
- // --- revisions ---
71
- async getRevision(blockId, rev) {
72
- const row = await this.stmts.getRevision.get(blockId, rev);
73
- return row ? row.action_id : undefined;
134
+ async rangeRevisions(blockId, lo, hi) {
135
+ const rows = await this.stmts.listRevisions.all(blockId, lo, hi);
136
+ return rows.map(row => [row.rev, row.action_id]);
74
137
  }
75
- async putRevision(blockId, rev, value) {
76
- await this.stmts.saveRevision.run(blockId, rev, value);
77
- }
78
- async *rangeRevisions(blockId, lo, hi, reverse) {
79
- // `.all(...)` materializes every row before we yield, so no SQLite cursor
80
- // straddles the consumer's awaits (the kernel's drain-before-yield contract).
81
- const stmt = reverse ? this.stmts.listRevisionsDesc : this.stmts.listRevisionsAsc;
82
- const rows = await stmt.all(blockId, lo, hi);
83
- for (const row of rows) {
84
- yield [row.rev, row.action_id];
85
- }
86
- }
87
- // --- pending ---
88
- async getPending(blockId, actionId) {
89
- const row = await this.stmts.getPending.get(blockId, actionId);
90
- return row ? row.value : undefined;
91
- }
92
- async putPending(blockId, actionId, value) {
93
- await this.stmts.savePending.run(blockId, actionId, value);
94
- }
95
- async deletePending(blockId, actionId) {
96
- await this.stmts.deletePending.run(blockId, actionId);
97
- }
98
- async *listPendingActionIds(blockId) {
99
- // Drained by `.all(...)` before yielding — same rationale as rangeRevisions.
138
+ async listPendingActionIds(blockId) {
100
139
  const rows = await this.stmts.listPending.all(blockId);
101
- for (const row of rows) {
102
- yield row.action_id;
103
- }
104
- }
105
- // --- transactions ---
106
- async getTransaction(blockId, actionId) {
107
- const row = await this.stmts.getTransaction.get(blockId, actionId);
108
- return row ? row.value : undefined;
109
- }
110
- async putTransaction(blockId, actionId, value) {
111
- await this.stmts.saveTransaction.run(blockId, actionId, value);
112
- }
113
- // --- proofs (keyed (block_id, rev) like revisions; no delete — see RawStoreDriver.getProof) ---
114
- async getProof(blockId, rev) {
115
- const row = await this.stmts.getProof.get(blockId, rev);
116
- return row ? row.value : undefined;
117
- }
118
- async putProof(blockId, rev, value) {
119
- await this.stmts.saveProof.run(blockId, rev, value);
120
- }
121
- // --- materialized ---
122
- async getMaterialized(blockId, actionId) {
123
- const row = await this.stmts.getMaterialized.get(blockId, actionId);
124
- return row ? row.value : undefined;
125
- }
126
- async putMaterialized(blockId, actionId, value) {
127
- await this.stmts.saveMaterialized.run(blockId, actionId, value);
128
- }
129
- async deleteMaterialized(blockId, actionId) {
130
- await this.stmts.deleteMaterialized.run(blockId, actionId);
131
- }
132
- // --- promote (the only cross-key atomic op) ---
133
- async promote(blockId, actionId) {
134
- await this.db.transaction(async (tx) => {
135
- // Prepare against the open transaction so these three statements run on
136
- // the held mutex slot without re-locking the connection (which would
137
- // deadlock). Re-preparing is cheap — the driver caches by SQL text.
138
- const getPending = tx.prepare('SELECT value FROM pending WHERE block_id = ? AND action_id = ?');
139
- const saveTransaction = tx.prepare('INSERT OR REPLACE INTO transactions (block_id, action_id, value) VALUES (?, ?, ?)');
140
- const deletePending = tx.prepare('DELETE FROM pending WHERE block_id = ? AND action_id = ?');
141
- const row = await getPending.get(blockId, actionId);
142
- if (!row) {
143
- throw new Error(`Pending action ${actionId} not found for block ${blockId}`);
144
- }
145
- await saveTransaction.run(blockId, actionId, row.value);
146
- await deletePending.run(blockId, actionId);
147
- });
140
+ return rows.map(row => row.action_id);
148
141
  }
149
- // --- optional passthroughs ---
150
142
  async *listBlockIds() {
143
+ // Drained by `.all(...)` before yielding, so no cursor straddles the consumer's awaits.
151
144
  const rows = await this.stmts.listBlockIds.all();
152
145
  for (const row of rows) {
153
146
  yield row.block_id;
@@ -166,22 +159,146 @@ export class SqliteStoreDriver {
166
159
  return 0;
167
160
  }
168
161
  }
162
+ // --- the write group's sink ---
163
+ /**
164
+ * Apply the batch as one transaction and resolve with its `durable`. `WriteGroupSink.commit`'s
165
+ * contract: with `syncWithinMs` 0, or a deadline already passed (`SyncDeadlines.mustSyncNow`),
166
+ * the transaction commits under `synchronous = FULL`, which syncs this batch and every one held,
167
+ * and `durable` is already settled; otherwise it commits under `NORMAL` and `durable` settles at
168
+ * the next sync, which the timer makes by the earliest deadline held. A rejection has latched the
169
+ * backend.
170
+ */
171
+ commit(entries, { syncWithinMs }) {
172
+ if (!(syncWithinMs >= 0) || !Number.isFinite(syncWithinMs)) {
173
+ return Promise.reject(new RangeError(`syncWithinMs must be a finite number of milliseconds at or above 0, got ${syncWithinMs}`));
174
+ }
175
+ if (this.fault)
176
+ return Promise.reject(new StoreFailedError(this.fault.cause));
177
+ const deadline = this.deadlines.deadlineFor(syncWithinMs);
178
+ return this.deadlines.mustSyncNow(deadline) ? this.commitSynced(entries) : this.commitDeferred(entries, deadline);
179
+ }
180
+ /** Hasten: one synced commit covering every batch held when it runs; with nothing held, nothing is synced. `WriteGroupSink.sync`'s contract. */
181
+ sync() {
182
+ return this.syncHeld();
183
+ }
184
+ /**
185
+ * The handle is shared, so it is not closed here: only the deadline timer must not outlive the
186
+ * backend. `WriteGroupDriver.close` flushes strictly first, which took and settled everything
187
+ * held and so disarmed the timer; a caller that did not flush gets the same here. After a latch
188
+ * nothing is held, since the latch took and rejected it.
189
+ */
190
+ async close() {
191
+ if (this.fault)
192
+ return;
193
+ await this.syncHeld();
194
+ }
195
+ async commitDeferred(entries, deadline) {
196
+ try {
197
+ return await this.db.transaction(async (tx) => {
198
+ this.throwIfFailed();
199
+ await this.applyEntries(tx, entries);
200
+ // Deferred under the mutex, so the next sync's cover, also taken under it, includes this
201
+ // batch only once its transaction has committed.
202
+ return { durable: this.deadlines.defer(undefined, deadline) };
203
+ });
204
+ }
205
+ catch (err) {
206
+ throw this.latch(err);
207
+ }
208
+ }
209
+ async commitSynced(entries) {
210
+ await this.syncHeld(undefined, tx => this.applyEntries(tx, entries));
211
+ return { durable: Promise.resolve() };
212
+ }
213
+ /**
214
+ * The sync step: one synced transaction whose body runs `write`, if given, then takes the cover
215
+ * of every batch held — under the mutex, so the cover is exactly the batches whose transactions
216
+ * committed before this one — and, when there is a cover to settle and nothing of its own was
217
+ * written, bumps `durability_mark` so the commit has a frame to sync. The cover settles once the
218
+ * commit has resolved. A failure anywhere latches the backend and rejects every covered
219
+ * `durable`, so no flush waits for a sync the store will not make.
220
+ *
221
+ * `owedSince` is the moment the timer fired, when the timer's task runs this: `SyncDeadlines.take`
222
+ * counts the sync's lateness from it rather than from a deadline the timer's own slop missed.
223
+ */
224
+ async syncHeld(owedSince, write) {
225
+ // Assigned inside the body, so a failure after the take still reaches the cover it took.
226
+ let cover;
227
+ try {
228
+ await this.db.transaction(async (tx) => {
229
+ this.throwIfFailed();
230
+ const written = write ? await write(tx) : 0;
231
+ cover = this.deadlines.take(owedSince);
232
+ if (written === 0 && cover.items.length > 0)
233
+ await bumpDurabilityMark(tx);
234
+ }, { synced: true });
235
+ }
236
+ catch (err) {
237
+ const failure = this.latch(err);
238
+ cover?.fail(failure.cause);
239
+ throw failure;
240
+ }
241
+ cover?.settle();
242
+ }
243
+ /** The timer fired: run the sync step. Its failure has latched the backend, so it is only logged here. */
244
+ syncInBackground(firedAt) {
245
+ this.syncHeld(firedAt).catch((err) => {
246
+ log('deferred sync of %s failed; the store refuses every later write: %o', this.identity, err);
247
+ });
248
+ }
249
+ /**
250
+ * Every entry in order — a put as `INSERT OR REPLACE`, a delete as `DELETE` — each statement
251
+ * prepared once per batch against the open transaction. Returns how many were applied.
252
+ */
253
+ async applyEntries(tx, entries) {
254
+ const prepared = new Map();
255
+ const statement = (sql) => {
256
+ let stmt = prepared.get(sql);
257
+ if (!stmt) {
258
+ stmt = tx.prepare(sql);
259
+ prepared.set(sql, stmt);
260
+ }
261
+ return stmt;
262
+ };
263
+ for (const { key, value } of entries) {
264
+ if (value === undefined)
265
+ await statement(DELETE_SQL[key.store]).run(...keyParams(key));
266
+ else
267
+ await statement(PUT_SQL[key.store]).run(...keyParams(key), value);
268
+ }
269
+ return entries.length;
270
+ }
271
+ throwIfFailed() {
272
+ if (this.fault)
273
+ throw new StoreFailedError(this.fault.cause);
274
+ }
275
+ /**
276
+ * Latch the backend failed on its first fault and reject every batch waiting for a sync that will
277
+ * now never be made, so no caller waits on a `durable` for ever. Returns the error to throw.
278
+ */
279
+ latch(err) {
280
+ this.fault ??= { cause: err };
281
+ this.deadlines.failAll(err);
282
+ return new StoreFailedError(this.fault.cause);
283
+ }
169
284
  }
170
285
  /**
171
- * SQLite-backed {@link IRawStorage} for NativeScript peers, now a thin shell over
172
- * the shared {@link KvRawStorage} kernel driven by a {@link SqliteStoreDriver}.
173
- * The public name/constructor (`new SqliteRawStorage(db)`) is unchanged so
174
- * existing imports keep resolving; the kernel supplies the `IRawStorage` surface
175
- * and the driver supplies SQLite behavior.
286
+ * SQLite-backed {@link IRawStorage} for NativeScript peers: the shared {@link KvRawStorage} kernel
287
+ * over a {@link WriteGroupDriver} over a {@link SqliteBatchBackend}. Every write resolves into the
288
+ * driver's in-memory overlay; `flush()` hands the group to the backend as one batch, which applies
289
+ * it as one SQLite transaction, synced before the flush resolves or within the window the flush
290
+ * allows. The public name/constructor (`new SqliteRawStorage(db)`) is unchanged so existing imports
291
+ * keep resolving.
176
292
  *
177
- * `listBlockIds`/`getApproximateBytesUsed` are re-declared here as always-present
178
- * (the SQLite driver always implements them, so the kernel constructor always
179
- * wires them) — the base declares them optional, but every NS consumer relies on
180
- * them.
293
+ * `listBlockIds`/`getApproximateBytesUsed`/`getStoreIdentity`/`close` are re-declared here as
294
+ * always-present (the backend always implements the first three, so the driver and kernel always
295
+ * wire them, and the driver always has a `close`) — the base declares them optional, but every NS
296
+ * consumer relies on them. `close()` flushes what is still held, syncs it, and disarms the timers;
297
+ * it does not close the shared handle, which the host closes afterwards.
181
298
  */
182
299
  export class SqliteRawStorage extends KvRawStorage {
183
- constructor(db) {
184
- super(new SqliteStoreDriver(db));
300
+ constructor(db, options = {}) {
301
+ super(new WriteGroupDriver(new SqliteBatchBackend(db, options), options));
185
302
  }
186
303
  }
187
304
  //# sourceMappingURL=sqlite-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-storage.js","sourceRoot":"","sources":["../../src/sqlite-storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite-storage.js","sourceRoot":"","sources":["../../src/sqlite-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { SqliteDb, SqliteTransaction } from './db.js';
2
+ /**
3
+ * Bump the one `durability_mark` row inside an open transaction, so that the transaction has a
4
+ * frame to commit whatever else it wrote. The row's count means nothing; a sync needs a change to
5
+ * commit, because a transaction that changed nothing writes no frame and syncs nothing.
6
+ */
7
+ export declare function bumpDurabilityMark(tx: SqliteTransaction): Promise<void>;
8
+ /**
9
+ * Sync the database: one synced transaction (`SqliteTransactionOptions.synced`) that bumps the
10
+ * `durability_mark` row. Its commit syncs the write-ahead log, which is one append-only file, so
11
+ * every earlier commit on this database — the block store's, the key-value store's and the identity
12
+ * helper's, all on one connection — survives a power cut once this resolves. Every sync in the
13
+ * package goes through this helper or through a synced transaction that writes rows of its own
14
+ * (`SqliteBatchBackend`).
15
+ */
16
+ export declare function syncSqliteDb(db: SqliteDb): Promise<void>;
17
+ //# sourceMappingURL=sqlite-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-sync.d.ts","sourceRoot":"","sources":["../../src/sqlite-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAI3D;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D"}
@@ -0,0 +1,21 @@
1
+ const BUMP_MARK_SQL = 'INSERT INTO durability_mark (id, n) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET n = n + 1';
2
+ /**
3
+ * Bump the one `durability_mark` row inside an open transaction, so that the transaction has a
4
+ * frame to commit whatever else it wrote. The row's count means nothing; a sync needs a change to
5
+ * commit, because a transaction that changed nothing writes no frame and syncs nothing.
6
+ */
7
+ export async function bumpDurabilityMark(tx) {
8
+ await tx.prepare(BUMP_MARK_SQL).run();
9
+ }
10
+ /**
11
+ * Sync the database: one synced transaction (`SqliteTransactionOptions.synced`) that bumps the
12
+ * `durability_mark` row. Its commit syncs the write-ahead log, which is one append-only file, so
13
+ * every earlier commit on this database — the block store's, the key-value store's and the identity
14
+ * helper's, all on one connection — survives a power cut once this resolves. Every sync in the
15
+ * package goes through this helper or through a synced transaction that writes rows of its own
16
+ * (`SqliteBatchBackend`).
17
+ */
18
+ export async function syncSqliteDb(db) {
19
+ await db.transaction(bumpDurabilityMark, { synced: true });
20
+ }
21
+ //# sourceMappingURL=sqlite-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-sync.js","sourceRoot":"","sources":["../../src/sqlite-sync.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG,2FAA2F,CAAC;AAElH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAqB;IAC7D,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,EAAE,CAAC;AACvC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAY;IAC9C,MAAM,EAAE,CAAC,WAAW,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optimystic/db-p2p-storage-ns",
3
- "version": "1.14.0",
3
+ "version": "1.16.0",
4
4
  "type": "module",
5
5
  "description": "NativeScript SQLite storage backend for @optimystic/db-p2p",
6
6
  "main": "dist/src/index.js",
@@ -53,8 +53,8 @@
53
53
  "typescript": "^5.9.3"
54
54
  },
55
55
  "dependencies": {
56
- "@optimystic/db-core": "^1.14.0",
57
- "@optimystic/db-p2p": "^1.14.0",
56
+ "@optimystic/db-core": "^1.16.0",
57
+ "@optimystic/db-p2p": "^1.16.0",
58
58
  "debug": "^4.4.3"
59
59
  },
60
60
  "peerDependencies": {