@bastani/atomic 0.9.62-alpha.1 → 0.9.63-alpha.1

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/package.json +1 -1
  5. package/dist/builtin/web-access/package.json +1 -1
  6. package/dist/builtin/workflows/builtin/{chunk-vzbec50q.js → chunk-95r61ve5.js} +1 -1
  7. package/dist/builtin/workflows/builtin/{chunk-a2j0x1a6.js → chunk-qbthhjjk.js} +1 -1
  8. package/dist/builtin/workflows/builtin/{chunk-zhyqnf5g.js → chunk-rv4xxwd6.js} +69 -26
  9. package/dist/builtin/workflows/builtin/goal.js +2 -2
  10. package/dist/builtin/workflows/builtin/index.js +3 -3
  11. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  12. package/dist/builtin/workflows/package.json +1 -1
  13. package/dist/builtin/workflows/src/durable/journal/internal.d.ts +11 -1
  14. package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +2 -0
  15. package/dist/builtin/workflows/src/extension/index.bundle.mjs +106 -50
  16. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +106 -50
  17. package/dist/builtin/workflows/src/index.js +106 -50
  18. package/dist/builtin/workflows/src/local-worker-entry.mjs +106 -50
  19. package/dist/core/storage/database.d.ts +11 -1
  20. package/dist/core/storage/database.d.ts.map +1 -1
  21. package/dist/core/storage/database.js.map +1 -1
  22. package/dist/core/storage/index.d.ts +1 -1
  23. package/dist/core/storage/index.d.ts.map +1 -1
  24. package/dist/core/storage/index.js.map +1 -1
  25. package/dist/core/storage/node-sqlite.d.ts.map +1 -1
  26. package/dist/core/storage/node-sqlite.js +194 -23
  27. package/dist/core/storage/node-sqlite.js.map +1 -1
  28. package/npm-shrinkwrap.json +32 -32
  29. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import { mkdirSync, readdirSync, statSync, unlinkSync, utimesSync, writeFileSync } from "node:fs";
1
+ import { closeSync, mkdirSync, openSync, readdirSync, readFileSync, statSync, unlinkSync, utimesSync, writeFileSync, writeSync, } from "node:fs";
2
2
  import { mkdir, realpath } from "node:fs/promises";
3
3
  import { dirname, join } from "node:path";
4
4
  import { StorageAdapterLoadError, StorageInvalidTextError, StorageRollbackError, StorageTransactionClosedError, StorageUnavailableError, StoreClosedError, } from "./errors.js";
@@ -106,6 +106,118 @@ class SqliteWriteTicket {
106
106
  }
107
107
  }
108
108
  }
109
+ let holderSequence = 0;
110
+ const HOLDER_RECORD = /^held (\d{15})\n/;
111
+ function processAlive(pid) {
112
+ try {
113
+ process.kill(pid, 0);
114
+ return true;
115
+ }
116
+ catch (error) {
117
+ return error.code === "EPERM";
118
+ }
119
+ }
120
+ /**
121
+ * Which process holds the write lock, for the error of a writer that gives up waiting for it. Each connection that
122
+ * takes the lock records when it took it in a file of its own next to the database, named by its process, and marks
123
+ * the record free once it lets go; only the holder writes its record, so records never race. Nothing reads them
124
+ * until a writer gives up: the live record taken most recently names the holder. A connection removes the records
125
+ * of exited processes when it creates its own, so the killed ones do not pile up. Recording is a diagnostic: a
126
+ * record that cannot be written is dropped, never a failed transaction.
127
+ */
128
+ class SqliteHolderRecord {
129
+ descriptor;
130
+ broken = false;
131
+ directory;
132
+ path;
133
+ constructor(databasePath) {
134
+ this.directory = holderDirectory(databasePath);
135
+ holderSequence += 1;
136
+ this.path = join(this.directory, `${process.pid}-${holderSequence}`);
137
+ }
138
+ held() {
139
+ this.write(`held ${String(Date.now()).padStart(15, "0")}\n`);
140
+ }
141
+ free() {
142
+ if (this.descriptor !== undefined)
143
+ this.write(`free ${"0".repeat(15)}\n`);
144
+ }
145
+ close() {
146
+ if (this.descriptor === undefined)
147
+ return;
148
+ try {
149
+ closeSync(this.descriptor);
150
+ unlinkSync(this.path);
151
+ }
152
+ catch {
153
+ // Already gone; a leftover record of an exited process is ignored and removed by whoever reads it.
154
+ }
155
+ this.descriptor = undefined;
156
+ }
157
+ /** Every record has the same length and is written in place, so a reader never sees a shorter, stale tail. */
158
+ write(record) {
159
+ if (this.broken)
160
+ return;
161
+ try {
162
+ if (this.descriptor === undefined) {
163
+ mkdirSync(this.directory, { recursive: true });
164
+ liveHolderRecords(this.directory);
165
+ this.descriptor = openSync(this.path, "w");
166
+ }
167
+ writeSync(this.descriptor, record, 0);
168
+ }
169
+ catch {
170
+ this.broken = true;
171
+ this.close();
172
+ }
173
+ }
174
+ }
175
+ function holderDirectory(databasePath) {
176
+ return `${databasePath}-holders`;
177
+ }
178
+ /** The records of live processes, as pid and the time each took the lock (undefined when free); others are removed. */
179
+ function liveHolderRecords(directory) {
180
+ let names;
181
+ try {
182
+ names = readdirSync(directory);
183
+ }
184
+ catch {
185
+ return [];
186
+ }
187
+ const live = [];
188
+ for (const name of names) {
189
+ const pid = Number(/^(\d+)-/.exec(name)?.[1] ?? Number.NaN);
190
+ if (!Number.isSafeInteger(pid) || pid <= 0)
191
+ continue;
192
+ if (!processAlive(pid)) {
193
+ try {
194
+ unlinkSync(join(directory, name));
195
+ }
196
+ catch {
197
+ // Another connection removed it first.
198
+ }
199
+ continue;
200
+ }
201
+ let record;
202
+ try {
203
+ record = readFileSync(join(directory, name), "utf8");
204
+ }
205
+ catch {
206
+ continue;
207
+ }
208
+ const since = HOLDER_RECORD.exec(record)?.[1];
209
+ live.push({ pid, ...(since === undefined ? {} : { since: Number(since) }) });
210
+ }
211
+ return live;
212
+ }
213
+ /** The live process whose record says it took the write lock most recently, and for how long it has held it. */
214
+ function writeLockHolder(databasePath) {
215
+ let holder;
216
+ for (const { pid, since } of liveHolderRecords(holderDirectory(databasePath)))
217
+ if (since !== undefined && (holder === undefined || since > holder.since))
218
+ holder = { pid, since };
219
+ return holder === undefined ? undefined : { pid: holder.pid, heldMs: Math.max(0, Date.now() - holder.since) };
220
+ }
109
221
  // Share gates across module reloads as well as adapter instances. Only live queues retain file identities.
110
222
  const TRANSACTION_GATES = Symbol.for("atomic-storage/node-sqlite-transaction-gates@1");
111
223
  const gateBag = globalThis;
@@ -152,8 +264,20 @@ const LOCK_RETRY_BASE_DELAY_MS = 5;
152
264
  const LOCK_RETRY_MAX_DELAY_MS = 100;
153
265
  /** A writer at the head of the cross-process queue retries at least this often, so the lock it is owed does not sit idle. */
154
266
  const LOCK_RETRY_HEAD_MAX_DELAY_MS = 20;
267
+ /**
268
+ * Retry cap once a writer has waited out the connection's lock wait for a transaction that waits longer: every waiter
269
+ * polling a stalled lock at the usual rate would burn the CPU the stalled holder needs. It stays well under
270
+ * `TICKET_STALE_MS`, so the writer's place in the queue stays live.
271
+ */
272
+ const LOCK_RETRY_PATIENT_MAX_DELAY_MS = 500;
155
273
  /** Most transactions one group commit carries, so a batch cannot keep the write lock from other processes for long. */
156
274
  const MAX_GROUP_COMMIT_TRANSACTIONS = 128;
275
+ /**
276
+ * Longest a group commit runs its members before it commits them and takes the lock again for the rest: a batch of
277
+ * cheap transactions in a process starved of CPU still lets other processes' writers in between. The bound is
278
+ * checked between members, so one member's own work, however long, is never split.
279
+ */
280
+ const GROUP_COMMIT_HOLD_MS = 100;
157
281
  /** SQLITE_BUSY, including its extended codes: another connection holds the lock this statement needs. */
158
282
  function isSqliteBusy(cause) {
159
283
  const code = cause?.errcode;
@@ -194,6 +318,8 @@ class NodeSqliteDatabase {
194
318
  lockWaitMs;
195
319
  /** Cross-process first-come-first-served order for the write lock; absent for in-memory databases. */
196
320
  writeQueue;
321
+ /** This connection's record of when it holds the write lock, named in the error of a writer that gives up. */
322
+ holderRecord;
197
323
  constructor(connection, descriptor, ownsConnection = true, transactionIdentity = connection, lockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS) {
198
324
  this.lockWaitMs = lockWaitMs;
199
325
  this.transactionIdentity = transactionIdentity;
@@ -201,8 +327,10 @@ class NodeSqliteDatabase {
201
327
  this.connection = connection;
202
328
  this.descriptor = descriptor;
203
329
  this.executor = this.createExecutor(() => true);
204
- if (typeof transactionIdentity === "string")
330
+ if (typeof transactionIdentity === "string") {
205
331
  this.writeQueue = new SqliteWriteQueue(transactionIdentity);
332
+ this.holderRecord = new SqliteHolderRecord(transactionIdentity);
333
+ }
206
334
  }
207
335
  driver(operation) {
208
336
  try {
@@ -251,10 +379,12 @@ class NodeSqliteDatabase {
251
379
  * SQLITE_BUSY, so the attempt is retried after a timer. A refused writer queues with writers in other processes
252
380
  * and attempts the lock only when no earlier writer is still waiting, so none starves (#3978). The wait ends only
253
381
  * when no other connection has committed for `lockWaitMs`, whether this writer is still queued or already trying
254
- * the lock: a queued writer counts only real commits as progress, not older tickets ahead of it. Every other
255
- * failure, including a writers' queue that cannot be used, rejects at once with its cause.
382
+ * the lock: a queued writer counts only real commits as progress, not older tickets ahead of it. A transaction that
383
+ * waits longer than the connection's lock wait retries less often past it. The error of a writer that gives up
384
+ * names the process holding the lock. Every other failure, including a writers' queue that cannot be used,
385
+ * rejects at once with its cause.
256
386
  */
257
- async begin() {
387
+ async begin(lockWaitMs = this.lockWaitMs) {
258
388
  let ticket;
259
389
  try {
260
390
  // Writers already waiting in other processes go first.
@@ -270,6 +400,7 @@ class NodeSqliteDatabase {
270
400
  if (!behind) {
271
401
  try {
272
402
  this.tryBegin();
403
+ this.holderRecord?.held();
273
404
  return;
274
405
  }
275
406
  catch (error) {
@@ -289,10 +420,19 @@ class NodeSqliteDatabase {
289
420
  stalledSince = Date.now();
290
421
  }
291
422
  const stalledMs = Date.now() - stalledSince;
292
- if (stalledMs >= this.lockWaitMs)
293
- throw unavailable(this.descriptor, lastCause, `${sqliteFailureDetail(lastCause) ?? "database is locked"}; gave up after ${stalledMs} ms waiting for the write lock${behind ? " in the writers' queue" : ""}, held all that time with no other connection committing`);
294
- const delay = ticket !== undefined && !behind ? Math.min(backoff, LOCK_RETRY_HEAD_MAX_DELAY_MS) : backoff;
295
- backoff = Math.min(LOCK_RETRY_MAX_DELAY_MS, backoff * 2);
423
+ if (stalledMs >= lockWaitMs) {
424
+ const holder = typeof this.transactionIdentity === "string" ? writeLockHolder(this.transactionIdentity) : undefined;
425
+ const heldBy = holder === undefined ? "" : `by process ${holder.pid} (which took it ${holder.heldMs} ms ago) `;
426
+ throw unavailable(this.descriptor, lastCause, `${sqliteFailureDetail(lastCause) ?? "database is locked"}; gave up after ${stalledMs} ms waiting for the write lock${behind ? " in the writers' queue" : ""}, held all that time ${heldBy}with no other connection committing`);
427
+ }
428
+ const patient = stalledMs >= this.lockWaitMs;
429
+ const cap = patient
430
+ ? LOCK_RETRY_PATIENT_MAX_DELAY_MS
431
+ : ticket !== undefined && !behind
432
+ ? LOCK_RETRY_HEAD_MAX_DELAY_MS
433
+ : LOCK_RETRY_MAX_DELAY_MS;
434
+ const delay = Math.min(backoff, cap);
435
+ backoff = Math.min(patient ? LOCK_RETRY_PATIENT_MAX_DELAY_MS : LOCK_RETRY_MAX_DELAY_MS, backoff * 2);
296
436
  await new Promise((resolve) => setTimeout(resolve, delay * (0.5 + Math.random() / 2)));
297
437
  }
298
438
  }
@@ -366,13 +506,19 @@ class NodeSqliteDatabase {
366
506
  * Group commit: transactions queued while earlier work holds the connection join one `BEGIN IMMEDIATE … COMMIT`,
367
507
  * each inside its own savepoint and in the order they were requested. A transaction that throws rolls back only
368
508
  * its savepoint and rejects only its caller; every caller settles after the shared commit, so durability is the
369
- * same as a transaction of its own. Under load one lock acquisition and one sync serve the whole batch.
509
+ * same as a transaction of its own. Under load one lock acquisition and one sync serve the whole batch. A batch
510
+ * waits for the lock as long as the most patient of its transactions.
370
511
  */
371
- transaction(callback) {
512
+ transaction(callback, options) {
372
513
  if (this.closing)
373
514
  return Promise.reject(new StoreClosedError(this.descriptor));
374
515
  return new Promise((resolve, reject) => {
375
- const queued = { callback, resolve: resolve, reject };
516
+ const queued = {
517
+ callback,
518
+ resolve: resolve,
519
+ reject,
520
+ lockWaitMs: options?.lockWaitMs,
521
+ };
376
522
  if (this.openBatch !== undefined && this.openBatch.length < MAX_GROUP_COMMIT_TRANSACTIONS) {
377
523
  this.openBatch.push(queued);
378
524
  return;
@@ -387,12 +533,22 @@ class NodeSqliteDatabase {
387
533
  commitBatch(batch) {
388
534
  if (this.openBatch === batch)
389
535
  this.openBatch = undefined;
390
- return gateTransaction(this.transactionIdentity, () => batch.length === 1 ? this.commitAlone(batch[0]) : this.commitMembers(batch));
536
+ return gateTransaction(this.transactionIdentity, async () => {
537
+ try {
538
+ await (batch.length === 1 ? this.commitAlone(batch[0]) : this.commitMembers(batch));
539
+ }
540
+ finally {
541
+ this.holderRecord?.free();
542
+ }
543
+ });
544
+ }
545
+ lockWait(batch) {
546
+ return Math.max(...batch.map((queued) => queued.lockWaitMs ?? this.lockWaitMs));
391
547
  }
392
548
  /** A transaction with nobody queued behind it commits on its own, without savepoints. */
393
549
  async commitAlone(queued) {
394
550
  try {
395
- await this.begin();
551
+ await this.begin(this.lockWait([queued]));
396
552
  }
397
553
  catch (cause) {
398
554
  queued.reject(cause);
@@ -417,17 +573,24 @@ class NodeSqliteDatabase {
417
573
  queued.reject(cause);
418
574
  }
419
575
  }
576
+ /**
577
+ * Runs the batch's members in one transaction, for at most `GROUP_COMMIT_HOLD_MS`: members left when it runs out
578
+ * wait for the lock again, in a transaction of their own, still ahead of anything queued after them.
579
+ */
420
580
  async commitMembers(batch) {
421
581
  try {
422
- await this.begin();
582
+ await this.begin(this.lockWait(batch));
423
583
  }
424
584
  catch (cause) {
425
585
  for (const queued of batch)
426
586
  queued.reject(cause);
427
587
  return;
428
588
  }
589
+ const began = performance.now();
429
590
  const outcomes = [];
430
591
  for (const queued of batch) {
592
+ if (outcomes.length > 0 && performance.now() - began >= GROUP_COMMIT_HOLD_MS)
593
+ break;
431
594
  const savepoint = `atomic_group_${outcomes.length}`;
432
595
  let active = true;
433
596
  try {
@@ -450,24 +613,31 @@ class NodeSqliteDatabase {
450
613
  outcomes.push({ ok: false, error: cause });
451
614
  }
452
615
  }
616
+ const ran = batch.slice(0, outcomes.length);
617
+ const remaining = batch.slice(outcomes.length);
618
+ let commitCause;
619
+ let committed = true;
453
620
  try {
454
621
  await this.executor.exec("COMMIT");
455
622
  }
456
- catch (commitCause) {
623
+ catch (cause) {
624
+ committed = false;
625
+ commitCause = cause;
457
626
  await this.rollbackQuietly();
458
- batch.forEach((queued, index) => {
459
- const outcome = outcomes[index];
460
- queued.reject(outcome.ok ? commitCause : outcome.error);
461
- });
462
- return;
463
627
  }
464
- batch.forEach((queued, index) => {
628
+ // Let go of the record too: members left over wait for the lock again, and another process may take it first.
629
+ this.holderRecord?.free();
630
+ ran.forEach((queued, index) => {
465
631
  const outcome = outcomes[index];
466
- if (outcome.ok)
632
+ if (!committed)
633
+ queued.reject(outcome.ok ? commitCause : outcome.error);
634
+ else if (outcome.ok)
467
635
  queued.resolve(outcome.value);
468
636
  else
469
637
  queued.reject(outcome.error);
470
638
  });
639
+ if (remaining.length > 0)
640
+ await this.commitMembers(remaining);
471
641
  }
472
642
  /**
473
643
  * A savepoint that cannot be rolled back leaves the whole transaction unusable: earlier members lose their
@@ -498,6 +668,7 @@ class NodeSqliteDatabase {
498
668
  if (!this.closePromise) {
499
669
  this.closing = true;
500
670
  this.closePromise = this.tail.then(() => this.driver(() => {
671
+ this.holderRecord?.close();
501
672
  if (this.ownsConnection)
502
673
  this.connection.close();
503
674
  finalizeReleasedStatements();
@@ -1 +1 @@
1
- {"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../../src/core/storage/node-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, readdirSync, statSync, unlinkSync, utimesSync, writeFileSync } from \"node:fs\";\nimport { mkdir, realpath } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteRow, SqliteValue, StorageDescriptor } from \"./database.js\";\nimport {\n\tStorageAdapterLoadError,\n\ttype StorageFailureCause,\n\tStorageInvalidTextError,\n\tStorageRollbackError,\n\tStorageTransactionClosedError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\n\n/** A ticket its owner has not refreshed for this long belongs to a process that died or stopped waiting. */\nconst TICKET_STALE_MS = 2_000;\n/** Stale tickets older than this are removed by whichever writer notices them. */\nconst TICKET_REMOVE_AFTER_MS = 10 * TICKET_STALE_MS;\n\nlet ticketSequence = 0;\n\nfunction ticketName(): string {\n\tticketSequence += 1;\n\treturn `${String(Date.now()).padStart(15, \"0\")}-${process.pid}-${ticketSequence}`;\n}\n\n/**\n * First come, first served for SQLite's write lock across processes. SQLite has no queue for `BEGIN IMMEDIATE`: a\n * writer that polls after `SQLITE_BUSY` loses to one that begins the moment the lock is free, and a busy process\n * can take the lock again and again while another waits for its whole deadline (#3978). A writer that has been\n * refused takes a ticket, a file named by the time it started waiting, in a directory next to the database; it then\n * attempts the lock only once no live older ticket is ahead of it, and a writer that arrives while tickets wait\n * queues behind them instead of overtaking. Uncontended writers only list an absent or empty directory.\n */\nclass SqliteWriteQueue {\n\tprivate readonly directory: string;\n\n\tconstructor(databasePath: string) {\n\t\tthis.directory = `${databasePath}-writers`;\n\t}\n\n\t/** Whether another writer's live ticket is waiting, so a new writer must queue behind it. */\n\tothersWaiting(): boolean {\n\t\treturn this.liveTickets().length > 0;\n\t}\n\n\tjoin(): SqliteWriteTicket {\n\t\tmkdirSync(this.directory, { recursive: true });\n\t\tconst name = ticketName();\n\t\tconst path = join(this.directory, name);\n\t\twriteFileSync(path, \"\", { flag: \"wx\" });\n\t\treturn new SqliteWriteTicket(this, name, path);\n\t}\n\n\t/** Live tickets, oldest first; stale ones long abandoned are removed on the way. */\n\tliveTickets(except?: string): string[] {\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(this.directory);\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tconst now = Date.now();\n\t\tconst live: string[] = [];\n\t\tfor (const name of names) {\n\t\t\tif (name === except) continue;\n\t\t\tlet age: number;\n\t\t\ttry {\n\t\t\t\tage = now - statSync(join(this.directory, name)).mtimeMs;\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (age < TICKET_STALE_MS) live.push(name);\n\t\t\telse if (age > TICKET_REMOVE_AFTER_MS) {\n\t\t\t\ttry {\n\t\t\t\t\tunlinkSync(join(this.directory, name));\n\t\t\t\t} catch {\n\t\t\t\t\t// Another writer removed it first.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn live.sort();\n\t}\n}\n\nclass SqliteWriteTicket {\n\tprivate left = false;\n\tprivate readonly queue: SqliteWriteQueue;\n\tprivate readonly name: string;\n\tprivate readonly path: string;\n\n\tconstructor(queue: SqliteWriteQueue, name: string, path: string) {\n\t\tthis.queue = queue;\n\t\tthis.name = name;\n\t\tthis.path = path;\n\t}\n\n\t/** Marks this ticket live and reports whether an older live ticket is still ahead of it. */\n\tbehindOthers(): boolean {\n\t\tif (this.left) return false;\n\t\tconst now = new Date();\n\t\ttry {\n\t\t\tutimesSync(this.path, now, now);\n\t\t} catch {\n\t\t\t// The ticket was removed as stale while this writer stalled: take the place it would have had.\n\t\t\twriteFileSync(this.path, \"\");\n\t\t}\n\t\treturn this.queue.liveTickets(this.name).some((other) => other < this.name);\n\t}\n\n\tleave(): void {\n\t\tif (this.left) return;\n\t\tthis.left = true;\n\t\ttry {\n\t\t\tunlinkSync(this.path);\n\t\t} catch {\n\t\t\t// Already removed.\n\t\t}\n\t}\n}\n\ninterface TransactionGates {\n\treadonly files: Map<string, Promise<void>>;\n\treadonly connections: WeakMap<DatabaseSync, Promise<void>>;\n}\n\n// Share gates across module reloads as well as adapter instances. Only live queues retain file identities.\nconst TRANSACTION_GATES = Symbol.for(\"atomic-storage/node-sqlite-transaction-gates@1\");\nconst gateBag = globalThis as typeof globalThis & Record<symbol, TransactionGates | undefined>;\nconst gates: TransactionGates = gateBag[TRANSACTION_GATES] ?? { files: new Map(), connections: new WeakMap() };\ngateBag[TRANSACTION_GATES] = gates;\n\nfunction gateTransaction<T>(identity: string | DatabaseSync, operation: () => Promise<T>): Promise<T> {\n\tconst prior = typeof identity === \"string\" ? gates.files.get(identity) : gates.connections.get(identity);\n\tconst result = (prior ?? Promise.resolve()).then(operation);\n\tconst settled = result.then(\n\t\t() => {},\n\t\t() => {},\n\t);\n\tif (typeof identity === \"string\") gates.files.set(identity, settled);\n\telse gates.connections.set(identity, settled);\n\tvoid settled.then(() => {\n\t\tif (typeof identity === \"string\") {\n\t\t\tif (gates.files.get(identity) === settled) gates.files.delete(identity);\n\t\t} else if (gates.connections.get(identity) === settled) gates.connections.delete(identity);\n\t});\n\treturn result;\n}\n\n/** Copies binary parameters so queued work binds the bytes the caller passed, not later buffer contents. */\nfunction snapshotParams(params: readonly SqliteValue[]): SqliteValue[] {\n\treturn params.map((value) => (value instanceof Uint8Array ? new Uint8Array(value) : value));\n}\n\n/**\n * Bun's `DatabaseSync.close()` defers closing the file until garbage collection finalizes every statement the\n * connection prepared, so the database, WAL and shared-memory files stay open (and locked on Windows). The adapter\n * keeps no statement references, so a synchronous collection finalizes them and releases the files. Node finalizes\n * statements inside `close()` and has no `Bun` global.\n */\nfunction finalizeReleasedStatements(): void {\n\t(globalThis as { Bun?: { gc(force: boolean): void } }).Bun?.gc(true);\n}\n\n/**\n * Default for how long a transaction keeps retrying `BEGIN IMMEDIATE` while the write lock is held and nobody makes\n * progress through it: every commit by another connection restarts the wait, so only a lock held without commits\n * for this long fails the transaction.\n */\nconst DEFAULT_NODE_SQLITE_LOCK_WAIT_MS = 30_000;\nconst LOCK_RETRY_BASE_DELAY_MS = 5;\nconst LOCK_RETRY_MAX_DELAY_MS = 100;\n/** A writer at the head of the cross-process queue retries at least this often, so the lock it is owed does not sit idle. */\nconst LOCK_RETRY_HEAD_MAX_DELAY_MS = 20;\n/** Most transactions one group commit carries, so a batch cannot keep the write lock from other processes for long. */\nconst MAX_GROUP_COMMIT_TRANSACTIONS = 128;\n\ninterface QueuedTransaction {\n\treadonly callback: (transaction: SqliteExecutor) => Promise<unknown>;\n\treadonly resolve: (value: unknown) => void;\n\treadonly reject: (error: unknown) => void;\n}\n\ntype TransactionOutcome =\n\t| { readonly ok: true; readonly value: unknown }\n\t| { readonly ok: false; readonly error: unknown };\n\n/** SQLITE_BUSY, including its extended codes: another connection holds the lock this statement needs. */\nfunction isSqliteBusy(cause: unknown): boolean {\n\tconst code = (cause as { errcode?: unknown } | null | undefined)?.errcode;\n\treturn typeof code === \"number\" && (code & 0xff) === 5;\n}\n\n/** The driver's own reason, kept in the error message so it survives relays that forward only `message`. */\nfunction sqliteFailureDetail(cause: unknown): string | undefined {\n\tif (!(cause instanceof Error) || cause.message === \"\") return undefined;\n\tconst code = (cause as { errcode?: unknown }).errcode;\n\treturn typeof code === \"number\" ? `${cause.message} (SQLite code ${code})` : cause.message;\n}\n\nfunction unavailable(descriptor: StorageDescriptor, cause: unknown, detail = sqliteFailureDetail(cause)) {\n\treturn new StorageUnavailableError(descriptor, cause as StorageFailureCause, detail);\n}\n\nfunction normalizeRow(row: Record<string, SqliteValue>): SqliteRow {\n\treturn Object.fromEntries(\n\t\tObject.entries(row).map(([key, value]) => [\n\t\t\tkey,\n\t\t\ttypeof value === \"bigint\" &&\n\t\t\tvalue >= -BigInt(Number.MAX_SAFE_INTEGER) &&\n\t\t\tvalue <= BigInt(Number.MAX_SAFE_INTEGER)\n\t\t\t\t? Number(value)\n\t\t\t\t: value instanceof Uint8Array\n\t\t\t\t\t? new Uint8Array(value)\n\t\t\t\t\t: value,\n\t\t]),\n\t);\n}\n\nclass NodeSqliteDatabase implements SqliteDatabase {\n\treadonly descriptor: StorageDescriptor;\n\tprivate readonly connection: DatabaseSync;\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate openBatch?: QueuedTransaction[];\n\tprivate closing = false;\n\tprivate closePromise?: Promise<void>;\n\tprivate readonly executor: SqliteExecutor;\n\n\tprivate readonly ownsConnection: boolean;\n\tprivate readonly transactionIdentity: string | DatabaseSync;\n\tprivate readonly lockWaitMs: number;\n\t/** Cross-process first-come-first-served order for the write lock; absent for in-memory databases. */\n\tprivate readonly writeQueue?: SqliteWriteQueue;\n\n\tconstructor(\n\t\tconnection: DatabaseSync,\n\t\tdescriptor: StorageDescriptor,\n\t\townsConnection = true,\n\t\ttransactionIdentity: string | DatabaseSync = connection,\n\t\tlockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS,\n\t) {\n\t\tthis.lockWaitMs = lockWaitMs;\n\t\tthis.transactionIdentity = transactionIdentity;\n\t\tthis.ownsConnection = ownsConnection;\n\t\tthis.connection = connection;\n\t\tthis.descriptor = descriptor;\n\t\tthis.executor = this.createExecutor(() => true);\n\t\tif (typeof transactionIdentity === \"string\") this.writeQueue = new SqliteWriteQueue(transactionIdentity);\n\t}\n\n\tprivate driver<T>(operation: () => T): T {\n\t\ttry {\n\t\t\treturn operation();\n\t\t} catch (cause) {\n\t\t\tthrow unavailable(this.descriptor, cause);\n\t\t}\n\t}\n\n\t/**\n\t * One non-blocking `BEGIN IMMEDIATE`. node:sqlite runs `busy_timeout` synchronously, so a lock held by another\n\t * process would freeze this process's event loop for the whole timeout. The attempt runs with `busy_timeout=0`\n\t * and the connection's own value is restored before returning or throwing, so single statements outside a\n\t * transaction keep it. Callers reach this only through `enqueue` and the transaction gate, so nothing else runs\n\t * on the connection in between.\n\t */\n\tprivate tryBegin(): void {\n\t\tthis.driver(() => {\n\t\t\tconst configured = Number(this.connection.prepare(\"PRAGMA busy_timeout\").get()?.timeout ?? 0);\n\t\t\tthis.connection.exec(\"PRAGMA busy_timeout=0\");\n\t\t\tlet began = false;\n\t\t\ttry {\n\t\t\t\tthis.connection.exec(\"BEGIN IMMEDIATE\");\n\t\t\t\tbegan = true;\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tthis.connection.exec(`PRAGMA busy_timeout=${configured}`);\n\t\t\t\t} catch (restoreFailure) {\n\t\t\t\t\t// Never hand back a transaction on a connection whose lock wait is no longer the configured one.\n\t\t\t\t\tif (began) this.connection.exec(\"ROLLBACK\");\n\t\t\t\t\t// biome-ignore lint/correctness/noUnsafeFinally: a failed restore must replace the attempt's outcome.\n\t\t\t\t\tthrow restoreFailure;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Changes whenever another connection commits to the database: the lock is being used, not held idle. */\n\tprivate dataVersion(): number {\n\t\treturn this.driver(() => Number(this.connection.prepare(\"PRAGMA data_version\").get()?.data_version ?? 0));\n\t}\n\n\t/**\n\t * Takes the write lock without blocking the event loop. Nothing has run yet when `BEGIN IMMEDIATE` reports\n\t * SQLITE_BUSY, so the attempt is retried after a timer. A refused writer queues with writers in other processes\n\t * and attempts the lock only when no earlier writer is still waiting, so none starves (#3978). The wait ends only\n\t * when no other connection has committed for `lockWaitMs`, whether this writer is still queued or already trying\n\t * the lock: a queued writer counts only real commits as progress, not older tickets ahead of it. Every other\n\t * failure, including a writers' queue that cannot be used, rejects at once with its cause.\n\t */\n\tprivate async begin(): Promise<void> {\n\t\tlet ticket: SqliteWriteTicket | undefined;\n\t\ttry {\n\t\t\t// Writers already waiting in other processes go first.\n\t\t\tif (this.queueOp(() => this.writeQueue?.othersWaiting())) ticket = this.queueOp(() => this.writeQueue?.join());\n\t\t\t// Read only once this writer waits, so an uncontended transaction pays nothing for it.\n\t\t\tlet version = ticket === undefined ? undefined : this.dataVersion();\n\t\t\tlet stalledSince = Date.now();\n\t\t\tlet backoff = LOCK_RETRY_BASE_DELAY_MS;\n\t\t\tlet lastCause: unknown;\n\t\t\tfor (;;) {\n\t\t\t\tconst behind = ticket !== undefined && this.queueOp(() => ticket!.behindOthers());\n\t\t\t\tif (!behind) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.tryBegin();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst cause = error instanceof StorageUnavailableError ? error.cause : undefined;\n\t\t\t\t\t\tif (!isSqliteBusy(cause)) throw error;\n\t\t\t\t\t\tlastCause = cause;\n\t\t\t\t\t\tticket ??= this.queueOp(() => this.writeQueue?.join());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Only another connection's commit is progress; a queued writer measures its stall the same way.\n\t\t\t\tconst current = this.dataVersion();\n\t\t\t\tif (version === undefined) version = current;\n\t\t\t\telse if (current !== version) {\n\t\t\t\t\tversion = current;\n\t\t\t\t\tstalledSince = Date.now();\n\t\t\t\t}\n\t\t\t\tconst stalledMs = Date.now() - stalledSince;\n\t\t\t\tif (stalledMs >= this.lockWaitMs)\n\t\t\t\t\tthrow unavailable(\n\t\t\t\t\t\tthis.descriptor,\n\t\t\t\t\t\tlastCause,\n\t\t\t\t\t\t`${sqliteFailureDetail(lastCause) ?? \"database is locked\"}; gave up after ${stalledMs} ms waiting for the write lock${behind ? \" in the writers' queue\" : \"\"}, held all that time with no other connection committing`,\n\t\t\t\t\t);\n\t\t\t\tconst delay = ticket !== undefined && !behind ? Math.min(backoff, LOCK_RETRY_HEAD_MAX_DELAY_MS) : backoff;\n\t\t\t\tbackoff = Math.min(LOCK_RETRY_MAX_DELAY_MS, backoff * 2);\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay * (0.5 + Math.random() / 2)));\n\t\t\t}\n\t\t} finally {\n\t\t\tticket?.leave();\n\t\t}\n\t}\n\n\t/** Runs a writers'-queue file operation; a failure (an unwritable queue directory, say) is a storage failure. */\n\tprivate queueOp<T>(operation: () => T): T {\n\t\ttry {\n\t\t\treturn operation();\n\t\t} catch (cause) {\n\t\t\tthrow unavailable(\n\t\t\t\tthis.descriptor,\n\t\t\t\tcause,\n\t\t\t\t`the writers' queue next to the database is unusable: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate createExecutor(active: () => boolean): SqliteExecutor {\n\t\tconst execute = async <T>(operation: () => T, params: readonly SqliteValue[] = []): Promise<T> => {\n\t\t\tif (!active()) throw new StorageTransactionClosedError();\n\t\t\tconst invalidIndex = params.findIndex((value) => typeof value === \"string\" && value.includes(\"\\0\"));\n\t\t\tif (invalidIndex !== -1) throw new StorageInvalidTextError(invalidIndex);\n\t\t\treturn this.driver(operation);\n\t\t};\n\t\tconst statement = (sql: string) => {\n\t\t\tconst prepared = this.connection.prepare(sql);\n\t\t\tprepared.setReadBigInts(true);\n\t\t\treturn prepared;\n\t\t};\n\t\treturn {\n\t\t\texec: (sql) => execute(() => this.connection.exec(sql)),\n\t\t\trun: (sql, ...params) => execute(() => ({ changes: Number(statement(sql).run(...params).changes) }), params),\n\t\t\tget: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(() => {\n\t\t\t\t\tconst row = statement(sql).get(...params);\n\t\t\t\t\treturn row === undefined ? undefined : (normalizeRow(row) as T);\n\t\t\t\t}, params),\n\t\t\tall: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tstatement(sql)\n\t\t\t\t\t\t\t.all(...params)\n\t\t\t\t\t\t\t.map((row) => normalizeRow(row) as T),\n\t\t\t\t\tparams,\n\t\t\t\t),\n\t\t};\n\t}\n\n\tprivate enqueue<T>(operation: () => Promise<T>): Promise<T> {\n\t\tif (this.closing) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tconst result = this.tail.then(operation);\n\t\tthis.tail = result.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\treturn result;\n\t}\n\n\t/** A statement queued after open transactions runs after them, so later transactions start a new batch. */\n\tprivate enqueueStatement<T>(operation: () => Promise<T>): Promise<T> {\n\t\tthis.openBatch = undefined;\n\t\treturn this.enqueue(operation);\n\t}\n\n\texec(sql: string): Promise<void> {\n\t\treturn this.enqueueStatement(() => this.executor.exec(sql));\n\t}\n\n\trun(sql: string, ...params: readonly SqliteValue[]) {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueueStatement(() => this.executor.run(sql, ...bound));\n\t}\n\n\tget<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T | undefined> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueueStatement(() => this.executor.get<T>(sql, ...bound));\n\t}\n\n\tall<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T[]> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueueStatement(() => this.executor.all<T>(sql, ...bound));\n\t}\n\n\t/**\n\t * Group commit: transactions queued while earlier work holds the connection join one `BEGIN IMMEDIATE … COMMIT`,\n\t * each inside its own savepoint and in the order they were requested. A transaction that throws rolls back only\n\t * its savepoint and rejects only its caller; every caller settles after the shared commit, so durability is the\n\t * same as a transaction of its own. Under load one lock acquisition and one sync serve the whole batch.\n\t */\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\tif (this.closing) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst queued: QueuedTransaction = { callback, resolve: resolve as (value: unknown) => void, reject };\n\t\t\tif (this.openBatch !== undefined && this.openBatch.length < MAX_GROUP_COMMIT_TRANSACTIONS) {\n\t\t\t\tthis.openBatch.push(queued);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.startBatch([queued]);\n\t\t});\n\t}\n\n\tprivate startBatch(batch: QueuedTransaction[]): void {\n\t\tthis.openBatch = batch;\n\t\tvoid this.enqueue(() => this.commitBatch(batch));\n\t}\n\n\tprivate commitBatch(batch: QueuedTransaction[]): Promise<void> {\n\t\tif (this.openBatch === batch) this.openBatch = undefined;\n\t\treturn gateTransaction(this.transactionIdentity, () =>\n\t\t\tbatch.length === 1 ? this.commitAlone(batch[0]!) : this.commitMembers(batch),\n\t\t);\n\t}\n\n\t/** A transaction with nobody queued behind it commits on its own, without savepoints. */\n\tprivate async commitAlone(queued: QueuedTransaction): Promise<void> {\n\t\ttry {\n\t\t\tawait this.begin();\n\t\t} catch (cause) {\n\t\t\tqueued.reject(cause);\n\t\t\treturn;\n\t\t}\n\t\tlet active = true;\n\t\ttry {\n\t\t\tconst value = await queued.callback(this.createExecutor(() => active));\n\t\t\tactive = false;\n\t\t\tawait this.executor.exec(\"COMMIT\");\n\t\t\tqueued.resolve(value);\n\t\t} catch (cause) {\n\t\t\tactive = false;\n\t\t\ttry {\n\t\t\t\tawait this.executor.exec(\"ROLLBACK\");\n\t\t\t} catch (rollbackCause) {\n\t\t\t\tqueued.reject(new StorageRollbackError(cause as StorageFailureCause, rollbackCause as StorageFailureCause));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tqueued.reject(cause);\n\t\t}\n\t}\n\n\tprivate async commitMembers(batch: QueuedTransaction[]): Promise<void> {\n\t\ttry {\n\t\t\tawait this.begin();\n\t\t} catch (cause) {\n\t\t\tfor (const queued of batch) queued.reject(cause);\n\t\t\treturn;\n\t\t}\n\t\tconst outcomes: TransactionOutcome[] = [];\n\t\tfor (const queued of batch) {\n\t\t\tconst savepoint = `atomic_group_${outcomes.length}`;\n\t\t\tlet active = true;\n\t\t\ttry {\n\t\t\t\tawait this.executor.exec(`SAVEPOINT ${savepoint}`);\n\t\t\t\tconst value = await queued.callback(this.createExecutor(() => active));\n\t\t\t\tactive = false;\n\t\t\t\tawait this.executor.exec(`RELEASE ${savepoint}`);\n\t\t\t\toutcomes.push({ ok: true, value });\n\t\t\t} catch (cause) {\n\t\t\t\tactive = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.executor.exec(`ROLLBACK TO ${savepoint}`);\n\t\t\t\t\tawait this.executor.exec(`RELEASE ${savepoint}`);\n\t\t\t\t} catch (rollbackCause) {\n\t\t\t\t\tawait this.abandonMembers(batch, outcomes, cause, rollbackCause);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\toutcomes.push({ ok: false, error: cause });\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tawait this.executor.exec(\"COMMIT\");\n\t\t} catch (commitCause) {\n\t\t\tawait this.rollbackQuietly();\n\t\t\tbatch.forEach((queued, index) => {\n\t\t\t\tconst outcome = outcomes[index]!;\n\t\t\t\tqueued.reject(outcome.ok ? commitCause : outcome.error);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tbatch.forEach((queued, index) => {\n\t\t\tconst outcome = outcomes[index]!;\n\t\t\tif (outcome.ok) queued.resolve(outcome.value);\n\t\t\telse queued.reject(outcome.error);\n\t\t});\n\t}\n\n\t/**\n\t * A savepoint that cannot be rolled back leaves the whole transaction unusable: earlier members lose their\n\t * uncommitted writes and fail, the failing member reports both causes, and members that have not run yet get a\n\t * fresh transaction right away, still ahead of anything queued after them, because nothing of theirs has happened.\n\t */\n\tprivate async abandonMembers(\n\t\tbatch: QueuedTransaction[],\n\t\toutcomes: TransactionOutcome[],\n\t\tcause: unknown,\n\t\trollbackCause: unknown,\n\t): Promise<void> {\n\t\tawait this.rollbackQuietly();\n\t\tconst failed = outcomes.length;\n\t\tbatch.slice(0, failed).forEach((queued, index) => {\n\t\t\tconst outcome = outcomes[index]!;\n\t\t\tqueued.reject(outcome.ok ? unavailable(this.descriptor, rollbackCause) : outcome.error);\n\t\t});\n\t\tbatch[failed]!.reject(\n\t\t\tnew StorageRollbackError(cause as StorageFailureCause, rollbackCause as StorageFailureCause),\n\t\t);\n\t\tconst remaining = batch.slice(failed + 1);\n\t\tif (remaining.length > 0) await this.commitMembers(remaining);\n\t}\n\n\tprivate async rollbackQuietly(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.executor.exec(\"ROLLBACK\");\n\t\t} catch {\n\t\t\t// SQLite already rolled the transaction back; there is nothing left to undo.\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (!this.closePromise) {\n\t\t\tthis.closing = true;\n\t\t\tthis.closePromise = this.tail.then(() =>\n\t\t\t\tthis.driver(() => {\n\t\t\t\t\tif (this.ownsConnection) this.connection.close();\n\t\t\t\t\tfinalizeReleasedStatements();\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn this.closePromise;\n\t}\n}\n\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\t{\n\t\tbusyTimeoutMs = 5000,\n\t\tlockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS,\n\t\treadOnly = false,\n\t}: { busyTimeoutMs?: number; lockWaitMs?: number; readOnly?: boolean } = {},\n): Promise<SqliteDatabase> {\n\tconst descriptor = { adapter: \"node-sqlite\", location: path };\n\t// Load node:sqlite on first open: importing it prints Node's experimental warning, which every importer of the\n\t// package entry point would otherwise see.\n\tlet Database: typeof DatabaseSync;\n\ttry {\n\t\t({ DatabaseSync: Database } = await import(\"node:sqlite\"));\n\t} catch (cause) {\n\t\tthrow new StorageAdapterLoadError(\"node:sqlite\", cause as StorageFailureCause);\n\t}\n\tlet connection: DatabaseSync | undefined;\n\ttry {\n\t\tif (!readOnly && path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\t\tconnection = new Database(path, { readOnly });\n\t\tconnection.exec(`PRAGMA busy_timeout=${busyTimeoutMs}`);\n\t\tif (!readOnly) connection.exec(\"PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\");\n\t\tconst location = connection.location();\n\t\tconst identity = location === null ? connection : await realpath(location);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, true, identity, lockWaitMs);\n\t} catch (cause) {\n\t\ttry {\n\t\t\tconnection?.close();\n\t\t} catch {\n\t\t\t// Preserve the opening failure if cleanup also fails.\n\t\t}\n\t\tthrow unavailable(descriptor, cause);\n\t}\n}\n\nexport function wrapNodeSqliteDatabase(connection: DatabaseSync): SqliteDatabase {\n\tconst descriptor = { adapter: \"node-sqlite\", location: \":memory:\" };\n\ttry {\n\t\tdescriptor.location = connection.location() || \":memory:\";\n\t\tconnection.exec(\n\t\t\t\"PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\",\n\t\t);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, false);\n\t} catch (cause) {\n\t\tthrow unavailable(descriptor, cause);\n\t}\n}\n"]}
1
+ {"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../../src/core/storage/node-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcloseSync,\n\tmkdirSync,\n\topenSync,\n\treaddirSync,\n\treadFileSync,\n\tstatSync,\n\tunlinkSync,\n\tutimesSync,\n\twriteFileSync,\n\twriteSync,\n} from \"node:fs\";\nimport { mkdir, realpath } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport type { DatabaseSync } from \"node:sqlite\";\nimport type {\n\tSqliteDatabase,\n\tSqliteExecutor,\n\tSqliteRow,\n\tSqliteTransactionOptions,\n\tSqliteValue,\n\tStorageDescriptor,\n} from \"./database.js\";\nimport {\n\tStorageAdapterLoadError,\n\ttype StorageFailureCause,\n\tStorageInvalidTextError,\n\tStorageRollbackError,\n\tStorageTransactionClosedError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\n\n/** A ticket its owner has not refreshed for this long belongs to a process that died or stopped waiting. */\nconst TICKET_STALE_MS = 2_000;\n/** Stale tickets older than this are removed by whichever writer notices them. */\nconst TICKET_REMOVE_AFTER_MS = 10 * TICKET_STALE_MS;\n\nlet ticketSequence = 0;\n\nfunction ticketName(): string {\n\tticketSequence += 1;\n\treturn `${String(Date.now()).padStart(15, \"0\")}-${process.pid}-${ticketSequence}`;\n}\n\n/**\n * First come, first served for SQLite's write lock across processes. SQLite has no queue for `BEGIN IMMEDIATE`: a\n * writer that polls after `SQLITE_BUSY` loses to one that begins the moment the lock is free, and a busy process\n * can take the lock again and again while another waits for its whole deadline (#3978). A writer that has been\n * refused takes a ticket, a file named by the time it started waiting, in a directory next to the database; it then\n * attempts the lock only once no live older ticket is ahead of it, and a writer that arrives while tickets wait\n * queues behind them instead of overtaking. Uncontended writers only list an absent or empty directory.\n */\nclass SqliteWriteQueue {\n\tprivate readonly directory: string;\n\n\tconstructor(databasePath: string) {\n\t\tthis.directory = `${databasePath}-writers`;\n\t}\n\n\t/** Whether another writer's live ticket is waiting, so a new writer must queue behind it. */\n\tothersWaiting(): boolean {\n\t\treturn this.liveTickets().length > 0;\n\t}\n\n\tjoin(): SqliteWriteTicket {\n\t\tmkdirSync(this.directory, { recursive: true });\n\t\tconst name = ticketName();\n\t\tconst path = join(this.directory, name);\n\t\twriteFileSync(path, \"\", { flag: \"wx\" });\n\t\treturn new SqliteWriteTicket(this, name, path);\n\t}\n\n\t/** Live tickets, oldest first; stale ones long abandoned are removed on the way. */\n\tliveTickets(except?: string): string[] {\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(this.directory);\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tconst now = Date.now();\n\t\tconst live: string[] = [];\n\t\tfor (const name of names) {\n\t\t\tif (name === except) continue;\n\t\t\tlet age: number;\n\t\t\ttry {\n\t\t\t\tage = now - statSync(join(this.directory, name)).mtimeMs;\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (age < TICKET_STALE_MS) live.push(name);\n\t\t\telse if (age > TICKET_REMOVE_AFTER_MS) {\n\t\t\t\ttry {\n\t\t\t\t\tunlinkSync(join(this.directory, name));\n\t\t\t\t} catch {\n\t\t\t\t\t// Another writer removed it first.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn live.sort();\n\t}\n}\n\nclass SqliteWriteTicket {\n\tprivate left = false;\n\tprivate readonly queue: SqliteWriteQueue;\n\tprivate readonly name: string;\n\tprivate readonly path: string;\n\n\tconstructor(queue: SqliteWriteQueue, name: string, path: string) {\n\t\tthis.queue = queue;\n\t\tthis.name = name;\n\t\tthis.path = path;\n\t}\n\n\t/** Marks this ticket live and reports whether an older live ticket is still ahead of it. */\n\tbehindOthers(): boolean {\n\t\tif (this.left) return false;\n\t\tconst now = new Date();\n\t\ttry {\n\t\t\tutimesSync(this.path, now, now);\n\t\t} catch {\n\t\t\t// The ticket was removed as stale while this writer stalled: take the place it would have had.\n\t\t\twriteFileSync(this.path, \"\");\n\t\t}\n\t\treturn this.queue.liveTickets(this.name).some((other) => other < this.name);\n\t}\n\n\tleave(): void {\n\t\tif (this.left) return;\n\t\tthis.left = true;\n\t\ttry {\n\t\t\tunlinkSync(this.path);\n\t\t} catch {\n\t\t\t// Already removed.\n\t\t}\n\t}\n}\n\nlet holderSequence = 0;\nconst HOLDER_RECORD = /^held (\\d{15})\\n/;\n\nfunction processAlive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error) {\n\t\treturn (error as NodeJS.ErrnoException).code === \"EPERM\";\n\t}\n}\n\n/**\n * Which process holds the write lock, for the error of a writer that gives up waiting for it. Each connection that\n * takes the lock records when it took it in a file of its own next to the database, named by its process, and marks\n * the record free once it lets go; only the holder writes its record, so records never race. Nothing reads them\n * until a writer gives up: the live record taken most recently names the holder. A connection removes the records\n * of exited processes when it creates its own, so the killed ones do not pile up. Recording is a diagnostic: a\n * record that cannot be written is dropped, never a failed transaction.\n */\nclass SqliteHolderRecord {\n\tprivate descriptor?: number;\n\tprivate broken = false;\n\tprivate readonly directory: string;\n\tprivate readonly path: string;\n\n\tconstructor(databasePath: string) {\n\t\tthis.directory = holderDirectory(databasePath);\n\t\tholderSequence += 1;\n\t\tthis.path = join(this.directory, `${process.pid}-${holderSequence}`);\n\t}\n\n\theld(): void {\n\t\tthis.write(`held ${String(Date.now()).padStart(15, \"0\")}\\n`);\n\t}\n\n\tfree(): void {\n\t\tif (this.descriptor !== undefined) this.write(`free ${\"0\".repeat(15)}\\n`);\n\t}\n\n\tclose(): void {\n\t\tif (this.descriptor === undefined) return;\n\t\ttry {\n\t\t\tcloseSync(this.descriptor);\n\t\t\tunlinkSync(this.path);\n\t\t} catch {\n\t\t\t// Already gone; a leftover record of an exited process is ignored and removed by whoever reads it.\n\t\t}\n\t\tthis.descriptor = undefined;\n\t}\n\n\t/** Every record has the same length and is written in place, so a reader never sees a shorter, stale tail. */\n\tprivate write(record: string): void {\n\t\tif (this.broken) return;\n\t\ttry {\n\t\t\tif (this.descriptor === undefined) {\n\t\t\t\tmkdirSync(this.directory, { recursive: true });\n\t\t\t\tliveHolderRecords(this.directory);\n\t\t\t\tthis.descriptor = openSync(this.path, \"w\");\n\t\t\t}\n\t\t\twriteSync(this.descriptor, record, 0);\n\t\t} catch {\n\t\t\tthis.broken = true;\n\t\t\tthis.close();\n\t\t}\n\t}\n}\n\nfunction holderDirectory(databasePath: string): string {\n\treturn `${databasePath}-holders`;\n}\n\n/** The records of live processes, as pid and the time each took the lock (undefined when free); others are removed. */\nfunction liveHolderRecords(directory: string): { readonly pid: number; readonly since?: number }[] {\n\tlet names: string[];\n\ttry {\n\t\tnames = readdirSync(directory);\n\t} catch {\n\t\treturn [];\n\t}\n\tconst live: { pid: number; since?: number }[] = [];\n\tfor (const name of names) {\n\t\tconst pid = Number(/^(\\d+)-/.exec(name)?.[1] ?? Number.NaN);\n\t\tif (!Number.isSafeInteger(pid) || pid <= 0) continue;\n\t\tif (!processAlive(pid)) {\n\t\t\ttry {\n\t\t\t\tunlinkSync(join(directory, name));\n\t\t\t} catch {\n\t\t\t\t// Another connection removed it first.\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tlet record: string;\n\t\ttry {\n\t\t\trecord = readFileSync(join(directory, name), \"utf8\");\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tconst since = HOLDER_RECORD.exec(record)?.[1];\n\t\tlive.push({ pid, ...(since === undefined ? {} : { since: Number(since) }) });\n\t}\n\treturn live;\n}\n\n/** The live process whose record says it took the write lock most recently, and for how long it has held it. */\nfunction writeLockHolder(databasePath: string): { readonly pid: number; readonly heldMs: number } | undefined {\n\tlet holder: { pid: number; since: number } | undefined;\n\tfor (const { pid, since } of liveHolderRecords(holderDirectory(databasePath)))\n\t\tif (since !== undefined && (holder === undefined || since > holder.since)) holder = { pid, since };\n\treturn holder === undefined ? undefined : { pid: holder.pid, heldMs: Math.max(0, Date.now() - holder.since) };\n}\n\ninterface TransactionGates {\n\treadonly files: Map<string, Promise<void>>;\n\treadonly connections: WeakMap<DatabaseSync, Promise<void>>;\n}\n\n// Share gates across module reloads as well as adapter instances. Only live queues retain file identities.\nconst TRANSACTION_GATES = Symbol.for(\"atomic-storage/node-sqlite-transaction-gates@1\");\nconst gateBag = globalThis as typeof globalThis & Record<symbol, TransactionGates | undefined>;\nconst gates: TransactionGates = gateBag[TRANSACTION_GATES] ?? { files: new Map(), connections: new WeakMap() };\ngateBag[TRANSACTION_GATES] = gates;\n\nfunction gateTransaction<T>(identity: string | DatabaseSync, operation: () => Promise<T>): Promise<T> {\n\tconst prior = typeof identity === \"string\" ? gates.files.get(identity) : gates.connections.get(identity);\n\tconst result = (prior ?? Promise.resolve()).then(operation);\n\tconst settled = result.then(\n\t\t() => {},\n\t\t() => {},\n\t);\n\tif (typeof identity === \"string\") gates.files.set(identity, settled);\n\telse gates.connections.set(identity, settled);\n\tvoid settled.then(() => {\n\t\tif (typeof identity === \"string\") {\n\t\t\tif (gates.files.get(identity) === settled) gates.files.delete(identity);\n\t\t} else if (gates.connections.get(identity) === settled) gates.connections.delete(identity);\n\t});\n\treturn result;\n}\n\n/** Copies binary parameters so queued work binds the bytes the caller passed, not later buffer contents. */\nfunction snapshotParams(params: readonly SqliteValue[]): SqliteValue[] {\n\treturn params.map((value) => (value instanceof Uint8Array ? new Uint8Array(value) : value));\n}\n\n/**\n * Bun's `DatabaseSync.close()` defers closing the file until garbage collection finalizes every statement the\n * connection prepared, so the database, WAL and shared-memory files stay open (and locked on Windows). The adapter\n * keeps no statement references, so a synchronous collection finalizes them and releases the files. Node finalizes\n * statements inside `close()` and has no `Bun` global.\n */\nfunction finalizeReleasedStatements(): void {\n\t(globalThis as { Bun?: { gc(force: boolean): void } }).Bun?.gc(true);\n}\n\n/**\n * Default for how long a transaction keeps retrying `BEGIN IMMEDIATE` while the write lock is held and nobody makes\n * progress through it: every commit by another connection restarts the wait, so only a lock held without commits\n * for this long fails the transaction.\n */\nconst DEFAULT_NODE_SQLITE_LOCK_WAIT_MS = 30_000;\nconst LOCK_RETRY_BASE_DELAY_MS = 5;\nconst LOCK_RETRY_MAX_DELAY_MS = 100;\n/** A writer at the head of the cross-process queue retries at least this often, so the lock it is owed does not sit idle. */\nconst LOCK_RETRY_HEAD_MAX_DELAY_MS = 20;\n/**\n * Retry cap once a writer has waited out the connection's lock wait for a transaction that waits longer: every waiter\n * polling a stalled lock at the usual rate would burn the CPU the stalled holder needs. It stays well under\n * `TICKET_STALE_MS`, so the writer's place in the queue stays live.\n */\nconst LOCK_RETRY_PATIENT_MAX_DELAY_MS = 500;\n/** Most transactions one group commit carries, so a batch cannot keep the write lock from other processes for long. */\nconst MAX_GROUP_COMMIT_TRANSACTIONS = 128;\n/**\n * Longest a group commit runs its members before it commits them and takes the lock again for the rest: a batch of\n * cheap transactions in a process starved of CPU still lets other processes' writers in between. The bound is\n * checked between members, so one member's own work, however long, is never split.\n */\nconst GROUP_COMMIT_HOLD_MS = 100;\n\ninterface QueuedTransaction {\n\treadonly callback: (transaction: SqliteExecutor) => Promise<unknown>;\n\treadonly resolve: (value: unknown) => void;\n\treadonly reject: (error: unknown) => void;\n\treadonly lockWaitMs?: number;\n}\n\ntype TransactionOutcome =\n\t| { readonly ok: true; readonly value: unknown }\n\t| { readonly ok: false; readonly error: unknown };\n\n/** SQLITE_BUSY, including its extended codes: another connection holds the lock this statement needs. */\nfunction isSqliteBusy(cause: unknown): boolean {\n\tconst code = (cause as { errcode?: unknown } | null | undefined)?.errcode;\n\treturn typeof code === \"number\" && (code & 0xff) === 5;\n}\n\n/** The driver's own reason, kept in the error message so it survives relays that forward only `message`. */\nfunction sqliteFailureDetail(cause: unknown): string | undefined {\n\tif (!(cause instanceof Error) || cause.message === \"\") return undefined;\n\tconst code = (cause as { errcode?: unknown }).errcode;\n\treturn typeof code === \"number\" ? `${cause.message} (SQLite code ${code})` : cause.message;\n}\n\nfunction unavailable(descriptor: StorageDescriptor, cause: unknown, detail = sqliteFailureDetail(cause)) {\n\treturn new StorageUnavailableError(descriptor, cause as StorageFailureCause, detail);\n}\n\nfunction normalizeRow(row: Record<string, SqliteValue>): SqliteRow {\n\treturn Object.fromEntries(\n\t\tObject.entries(row).map(([key, value]) => [\n\t\t\tkey,\n\t\t\ttypeof value === \"bigint\" &&\n\t\t\tvalue >= -BigInt(Number.MAX_SAFE_INTEGER) &&\n\t\t\tvalue <= BigInt(Number.MAX_SAFE_INTEGER)\n\t\t\t\t? Number(value)\n\t\t\t\t: value instanceof Uint8Array\n\t\t\t\t\t? new Uint8Array(value)\n\t\t\t\t\t: value,\n\t\t]),\n\t);\n}\n\nclass NodeSqliteDatabase implements SqliteDatabase {\n\treadonly descriptor: StorageDescriptor;\n\tprivate readonly connection: DatabaseSync;\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate openBatch?: QueuedTransaction[];\n\tprivate closing = false;\n\tprivate closePromise?: Promise<void>;\n\tprivate readonly executor: SqliteExecutor;\n\n\tprivate readonly ownsConnection: boolean;\n\tprivate readonly transactionIdentity: string | DatabaseSync;\n\tprivate readonly lockWaitMs: number;\n\t/** Cross-process first-come-first-served order for the write lock; absent for in-memory databases. */\n\tprivate readonly writeQueue?: SqliteWriteQueue;\n\t/** This connection's record of when it holds the write lock, named in the error of a writer that gives up. */\n\tprivate readonly holderRecord?: SqliteHolderRecord;\n\n\tconstructor(\n\t\tconnection: DatabaseSync,\n\t\tdescriptor: StorageDescriptor,\n\t\townsConnection = true,\n\t\ttransactionIdentity: string | DatabaseSync = connection,\n\t\tlockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS,\n\t) {\n\t\tthis.lockWaitMs = lockWaitMs;\n\t\tthis.transactionIdentity = transactionIdentity;\n\t\tthis.ownsConnection = ownsConnection;\n\t\tthis.connection = connection;\n\t\tthis.descriptor = descriptor;\n\t\tthis.executor = this.createExecutor(() => true);\n\t\tif (typeof transactionIdentity === \"string\") {\n\t\t\tthis.writeQueue = new SqliteWriteQueue(transactionIdentity);\n\t\t\tthis.holderRecord = new SqliteHolderRecord(transactionIdentity);\n\t\t}\n\t}\n\n\tprivate driver<T>(operation: () => T): T {\n\t\ttry {\n\t\t\treturn operation();\n\t\t} catch (cause) {\n\t\t\tthrow unavailable(this.descriptor, cause);\n\t\t}\n\t}\n\n\t/**\n\t * One non-blocking `BEGIN IMMEDIATE`. node:sqlite runs `busy_timeout` synchronously, so a lock held by another\n\t * process would freeze this process's event loop for the whole timeout. The attempt runs with `busy_timeout=0`\n\t * and the connection's own value is restored before returning or throwing, so single statements outside a\n\t * transaction keep it. Callers reach this only through `enqueue` and the transaction gate, so nothing else runs\n\t * on the connection in between.\n\t */\n\tprivate tryBegin(): void {\n\t\tthis.driver(() => {\n\t\t\tconst configured = Number(this.connection.prepare(\"PRAGMA busy_timeout\").get()?.timeout ?? 0);\n\t\t\tthis.connection.exec(\"PRAGMA busy_timeout=0\");\n\t\t\tlet began = false;\n\t\t\ttry {\n\t\t\t\tthis.connection.exec(\"BEGIN IMMEDIATE\");\n\t\t\t\tbegan = true;\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tthis.connection.exec(`PRAGMA busy_timeout=${configured}`);\n\t\t\t\t} catch (restoreFailure) {\n\t\t\t\t\t// Never hand back a transaction on a connection whose lock wait is no longer the configured one.\n\t\t\t\t\tif (began) this.connection.exec(\"ROLLBACK\");\n\t\t\t\t\t// biome-ignore lint/correctness/noUnsafeFinally: a failed restore must replace the attempt's outcome.\n\t\t\t\t\tthrow restoreFailure;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Changes whenever another connection commits to the database: the lock is being used, not held idle. */\n\tprivate dataVersion(): number {\n\t\treturn this.driver(() => Number(this.connection.prepare(\"PRAGMA data_version\").get()?.data_version ?? 0));\n\t}\n\n\t/**\n\t * Takes the write lock without blocking the event loop. Nothing has run yet when `BEGIN IMMEDIATE` reports\n\t * SQLITE_BUSY, so the attempt is retried after a timer. A refused writer queues with writers in other processes\n\t * and attempts the lock only when no earlier writer is still waiting, so none starves (#3978). The wait ends only\n\t * when no other connection has committed for `lockWaitMs`, whether this writer is still queued or already trying\n\t * the lock: a queued writer counts only real commits as progress, not older tickets ahead of it. A transaction that\n\t * waits longer than the connection's lock wait retries less often past it. The error of a writer that gives up\n\t * names the process holding the lock. Every other failure, including a writers' queue that cannot be used,\n\t * rejects at once with its cause.\n\t */\n\tprivate async begin(lockWaitMs = this.lockWaitMs): Promise<void> {\n\t\tlet ticket: SqliteWriteTicket | undefined;\n\t\ttry {\n\t\t\t// Writers already waiting in other processes go first.\n\t\t\tif (this.queueOp(() => this.writeQueue?.othersWaiting())) ticket = this.queueOp(() => this.writeQueue?.join());\n\t\t\t// Read only once this writer waits, so an uncontended transaction pays nothing for it.\n\t\t\tlet version = ticket === undefined ? undefined : this.dataVersion();\n\t\t\tlet stalledSince = Date.now();\n\t\t\tlet backoff = LOCK_RETRY_BASE_DELAY_MS;\n\t\t\tlet lastCause: unknown;\n\t\t\tfor (;;) {\n\t\t\t\tconst behind = ticket !== undefined && this.queueOp(() => ticket!.behindOthers());\n\t\t\t\tif (!behind) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.tryBegin();\n\t\t\t\t\t\tthis.holderRecord?.held();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst cause = error instanceof StorageUnavailableError ? error.cause : undefined;\n\t\t\t\t\t\tif (!isSqliteBusy(cause)) throw error;\n\t\t\t\t\t\tlastCause = cause;\n\t\t\t\t\t\tticket ??= this.queueOp(() => this.writeQueue?.join());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Only another connection's commit is progress; a queued writer measures its stall the same way.\n\t\t\t\tconst current = this.dataVersion();\n\t\t\t\tif (version === undefined) version = current;\n\t\t\t\telse if (current !== version) {\n\t\t\t\t\tversion = current;\n\t\t\t\t\tstalledSince = Date.now();\n\t\t\t\t}\n\t\t\t\tconst stalledMs = Date.now() - stalledSince;\n\t\t\t\tif (stalledMs >= lockWaitMs) {\n\t\t\t\t\tconst holder =\n\t\t\t\t\t\ttypeof this.transactionIdentity === \"string\" ? writeLockHolder(this.transactionIdentity) : undefined;\n\t\t\t\t\tconst heldBy =\n\t\t\t\t\t\tholder === undefined ? \"\" : `by process ${holder.pid} (which took it ${holder.heldMs} ms ago) `;\n\t\t\t\t\tthrow unavailable(\n\t\t\t\t\t\tthis.descriptor,\n\t\t\t\t\t\tlastCause,\n\t\t\t\t\t\t`${sqliteFailureDetail(lastCause) ?? \"database is locked\"}; gave up after ${stalledMs} ms waiting for the write lock${behind ? \" in the writers' queue\" : \"\"}, held all that time ${heldBy}with no other connection committing`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst patient = stalledMs >= this.lockWaitMs;\n\t\t\t\tconst cap = patient\n\t\t\t\t\t? LOCK_RETRY_PATIENT_MAX_DELAY_MS\n\t\t\t\t\t: ticket !== undefined && !behind\n\t\t\t\t\t\t? LOCK_RETRY_HEAD_MAX_DELAY_MS\n\t\t\t\t\t\t: LOCK_RETRY_MAX_DELAY_MS;\n\t\t\t\tconst delay = Math.min(backoff, cap);\n\t\t\t\tbackoff = Math.min(patient ? LOCK_RETRY_PATIENT_MAX_DELAY_MS : LOCK_RETRY_MAX_DELAY_MS, backoff * 2);\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay * (0.5 + Math.random() / 2)));\n\t\t\t}\n\t\t} finally {\n\t\t\tticket?.leave();\n\t\t}\n\t}\n\n\t/** Runs a writers'-queue file operation; a failure (an unwritable queue directory, say) is a storage failure. */\n\tprivate queueOp<T>(operation: () => T): T {\n\t\ttry {\n\t\t\treturn operation();\n\t\t} catch (cause) {\n\t\t\tthrow unavailable(\n\t\t\t\tthis.descriptor,\n\t\t\t\tcause,\n\t\t\t\t`the writers' queue next to the database is unusable: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate createExecutor(active: () => boolean): SqliteExecutor {\n\t\tconst execute = async <T>(operation: () => T, params: readonly SqliteValue[] = []): Promise<T> => {\n\t\t\tif (!active()) throw new StorageTransactionClosedError();\n\t\t\tconst invalidIndex = params.findIndex((value) => typeof value === \"string\" && value.includes(\"\\0\"));\n\t\t\tif (invalidIndex !== -1) throw new StorageInvalidTextError(invalidIndex);\n\t\t\treturn this.driver(operation);\n\t\t};\n\t\tconst statement = (sql: string) => {\n\t\t\tconst prepared = this.connection.prepare(sql);\n\t\t\tprepared.setReadBigInts(true);\n\t\t\treturn prepared;\n\t\t};\n\t\treturn {\n\t\t\texec: (sql) => execute(() => this.connection.exec(sql)),\n\t\t\trun: (sql, ...params) => execute(() => ({ changes: Number(statement(sql).run(...params).changes) }), params),\n\t\t\tget: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(() => {\n\t\t\t\t\tconst row = statement(sql).get(...params);\n\t\t\t\t\treturn row === undefined ? undefined : (normalizeRow(row) as T);\n\t\t\t\t}, params),\n\t\t\tall: <T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]) =>\n\t\t\t\texecute(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tstatement(sql)\n\t\t\t\t\t\t\t.all(...params)\n\t\t\t\t\t\t\t.map((row) => normalizeRow(row) as T),\n\t\t\t\t\tparams,\n\t\t\t\t),\n\t\t};\n\t}\n\n\tprivate enqueue<T>(operation: () => Promise<T>): Promise<T> {\n\t\tif (this.closing) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tconst result = this.tail.then(operation);\n\t\tthis.tail = result.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\treturn result;\n\t}\n\n\t/** A statement queued after open transactions runs after them, so later transactions start a new batch. */\n\tprivate enqueueStatement<T>(operation: () => Promise<T>): Promise<T> {\n\t\tthis.openBatch = undefined;\n\t\treturn this.enqueue(operation);\n\t}\n\n\texec(sql: string): Promise<void> {\n\t\treturn this.enqueueStatement(() => this.executor.exec(sql));\n\t}\n\n\trun(sql: string, ...params: readonly SqliteValue[]) {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueueStatement(() => this.executor.run(sql, ...bound));\n\t}\n\n\tget<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T | undefined> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueueStatement(() => this.executor.get<T>(sql, ...bound));\n\t}\n\n\tall<T extends SqliteRow>(sql: string, ...params: readonly SqliteValue[]): Promise<T[]> {\n\t\tconst bound = snapshotParams(params);\n\t\treturn this.enqueueStatement(() => this.executor.all<T>(sql, ...bound));\n\t}\n\n\t/**\n\t * Group commit: transactions queued while earlier work holds the connection join one `BEGIN IMMEDIATE … COMMIT`,\n\t * each inside its own savepoint and in the order they were requested. A transaction that throws rolls back only\n\t * its savepoint and rejects only its caller; every caller settles after the shared commit, so durability is the\n\t * same as a transaction of its own. Under load one lock acquisition and one sync serve the whole batch. A batch\n\t * waits for the lock as long as the most patient of its transactions.\n\t */\n\ttransaction<T>(\n\t\tcallback: (transaction: SqliteExecutor) => Promise<T>,\n\t\toptions?: SqliteTransactionOptions,\n\t): Promise<T> {\n\t\tif (this.closing) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst queued: QueuedTransaction = {\n\t\t\t\tcallback,\n\t\t\t\tresolve: resolve as (value: unknown) => void,\n\t\t\t\treject,\n\t\t\t\tlockWaitMs: options?.lockWaitMs,\n\t\t\t};\n\t\t\tif (this.openBatch !== undefined && this.openBatch.length < MAX_GROUP_COMMIT_TRANSACTIONS) {\n\t\t\t\tthis.openBatch.push(queued);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.startBatch([queued]);\n\t\t});\n\t}\n\n\tprivate startBatch(batch: QueuedTransaction[]): void {\n\t\tthis.openBatch = batch;\n\t\tvoid this.enqueue(() => this.commitBatch(batch));\n\t}\n\n\tprivate commitBatch(batch: QueuedTransaction[]): Promise<void> {\n\t\tif (this.openBatch === batch) this.openBatch = undefined;\n\t\treturn gateTransaction(this.transactionIdentity, async () => {\n\t\t\ttry {\n\t\t\t\tawait (batch.length === 1 ? this.commitAlone(batch[0]!) : this.commitMembers(batch));\n\t\t\t} finally {\n\t\t\t\tthis.holderRecord?.free();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate lockWait(batch: readonly QueuedTransaction[]): number {\n\t\treturn Math.max(...batch.map((queued) => queued.lockWaitMs ?? this.lockWaitMs));\n\t}\n\n\t/** A transaction with nobody queued behind it commits on its own, without savepoints. */\n\tprivate async commitAlone(queued: QueuedTransaction): Promise<void> {\n\t\ttry {\n\t\t\tawait this.begin(this.lockWait([queued]));\n\t\t} catch (cause) {\n\t\t\tqueued.reject(cause);\n\t\t\treturn;\n\t\t}\n\t\tlet active = true;\n\t\ttry {\n\t\t\tconst value = await queued.callback(this.createExecutor(() => active));\n\t\t\tactive = false;\n\t\t\tawait this.executor.exec(\"COMMIT\");\n\t\t\tqueued.resolve(value);\n\t\t} catch (cause) {\n\t\t\tactive = false;\n\t\t\ttry {\n\t\t\t\tawait this.executor.exec(\"ROLLBACK\");\n\t\t\t} catch (rollbackCause) {\n\t\t\t\tqueued.reject(new StorageRollbackError(cause as StorageFailureCause, rollbackCause as StorageFailureCause));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tqueued.reject(cause);\n\t\t}\n\t}\n\n\t/**\n\t * Runs the batch's members in one transaction, for at most `GROUP_COMMIT_HOLD_MS`: members left when it runs out\n\t * wait for the lock again, in a transaction of their own, still ahead of anything queued after them.\n\t */\n\tprivate async commitMembers(batch: QueuedTransaction[]): Promise<void> {\n\t\ttry {\n\t\t\tawait this.begin(this.lockWait(batch));\n\t\t} catch (cause) {\n\t\t\tfor (const queued of batch) queued.reject(cause);\n\t\t\treturn;\n\t\t}\n\t\tconst began = performance.now();\n\t\tconst outcomes: TransactionOutcome[] = [];\n\t\tfor (const queued of batch) {\n\t\t\tif (outcomes.length > 0 && performance.now() - began >= GROUP_COMMIT_HOLD_MS) break;\n\t\t\tconst savepoint = `atomic_group_${outcomes.length}`;\n\t\t\tlet active = true;\n\t\t\ttry {\n\t\t\t\tawait this.executor.exec(`SAVEPOINT ${savepoint}`);\n\t\t\t\tconst value = await queued.callback(this.createExecutor(() => active));\n\t\t\t\tactive = false;\n\t\t\t\tawait this.executor.exec(`RELEASE ${savepoint}`);\n\t\t\t\toutcomes.push({ ok: true, value });\n\t\t\t} catch (cause) {\n\t\t\t\tactive = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.executor.exec(`ROLLBACK TO ${savepoint}`);\n\t\t\t\t\tawait this.executor.exec(`RELEASE ${savepoint}`);\n\t\t\t\t} catch (rollbackCause) {\n\t\t\t\t\tawait this.abandonMembers(batch, outcomes, cause, rollbackCause);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\toutcomes.push({ ok: false, error: cause });\n\t\t\t}\n\t\t}\n\t\tconst ran = batch.slice(0, outcomes.length);\n\t\tconst remaining = batch.slice(outcomes.length);\n\t\tlet commitCause: unknown;\n\t\tlet committed = true;\n\t\ttry {\n\t\t\tawait this.executor.exec(\"COMMIT\");\n\t\t} catch (cause) {\n\t\t\tcommitted = false;\n\t\t\tcommitCause = cause;\n\t\t\tawait this.rollbackQuietly();\n\t\t}\n\t\t// Let go of the record too: members left over wait for the lock again, and another process may take it first.\n\t\tthis.holderRecord?.free();\n\t\tran.forEach((queued, index) => {\n\t\t\tconst outcome = outcomes[index]!;\n\t\t\tif (!committed) queued.reject(outcome.ok ? commitCause : outcome.error);\n\t\t\telse if (outcome.ok) queued.resolve(outcome.value);\n\t\t\telse queued.reject(outcome.error);\n\t\t});\n\t\tif (remaining.length > 0) await this.commitMembers(remaining);\n\t}\n\n\t/**\n\t * A savepoint that cannot be rolled back leaves the whole transaction unusable: earlier members lose their\n\t * uncommitted writes and fail, the failing member reports both causes, and members that have not run yet get a\n\t * fresh transaction right away, still ahead of anything queued after them, because nothing of theirs has happened.\n\t */\n\tprivate async abandonMembers(\n\t\tbatch: QueuedTransaction[],\n\t\toutcomes: TransactionOutcome[],\n\t\tcause: unknown,\n\t\trollbackCause: unknown,\n\t): Promise<void> {\n\t\tawait this.rollbackQuietly();\n\t\tconst failed = outcomes.length;\n\t\tbatch.slice(0, failed).forEach((queued, index) => {\n\t\t\tconst outcome = outcomes[index]!;\n\t\t\tqueued.reject(outcome.ok ? unavailable(this.descriptor, rollbackCause) : outcome.error);\n\t\t});\n\t\tbatch[failed]!.reject(\n\t\t\tnew StorageRollbackError(cause as StorageFailureCause, rollbackCause as StorageFailureCause),\n\t\t);\n\t\tconst remaining = batch.slice(failed + 1);\n\t\tif (remaining.length > 0) await this.commitMembers(remaining);\n\t}\n\n\tprivate async rollbackQuietly(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.executor.exec(\"ROLLBACK\");\n\t\t} catch {\n\t\t\t// SQLite already rolled the transaction back; there is nothing left to undo.\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (!this.closePromise) {\n\t\t\tthis.closing = true;\n\t\t\tthis.closePromise = this.tail.then(() =>\n\t\t\t\tthis.driver(() => {\n\t\t\t\t\tthis.holderRecord?.close();\n\t\t\t\t\tif (this.ownsConnection) this.connection.close();\n\t\t\t\t\tfinalizeReleasedStatements();\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn this.closePromise;\n\t}\n}\n\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\t{\n\t\tbusyTimeoutMs = 5000,\n\t\tlockWaitMs = DEFAULT_NODE_SQLITE_LOCK_WAIT_MS,\n\t\treadOnly = false,\n\t}: { busyTimeoutMs?: number; lockWaitMs?: number; readOnly?: boolean } = {},\n): Promise<SqliteDatabase> {\n\tconst descriptor = { adapter: \"node-sqlite\", location: path };\n\t// Load node:sqlite on first open: importing it prints Node's experimental warning, which every importer of the\n\t// package entry point would otherwise see.\n\tlet Database: typeof DatabaseSync;\n\ttry {\n\t\t({ DatabaseSync: Database } = await import(\"node:sqlite\"));\n\t} catch (cause) {\n\t\tthrow new StorageAdapterLoadError(\"node:sqlite\", cause as StorageFailureCause);\n\t}\n\tlet connection: DatabaseSync | undefined;\n\ttry {\n\t\tif (!readOnly && path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\t\tconnection = new Database(path, { readOnly });\n\t\tconnection.exec(`PRAGMA busy_timeout=${busyTimeoutMs}`);\n\t\tif (!readOnly) connection.exec(\"PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\");\n\t\tconst location = connection.location();\n\t\tconst identity = location === null ? connection : await realpath(location);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, true, identity, lockWaitMs);\n\t} catch (cause) {\n\t\ttry {\n\t\t\tconnection?.close();\n\t\t} catch {\n\t\t\t// Preserve the opening failure if cleanup also fails.\n\t\t}\n\t\tthrow unavailable(descriptor, cause);\n\t}\n}\n\nexport function wrapNodeSqliteDatabase(connection: DatabaseSync): SqliteDatabase {\n\tconst descriptor = { adapter: \"node-sqlite\", location: \":memory:\" };\n\ttry {\n\t\tdescriptor.location = connection.location() || \":memory:\";\n\t\tconnection.exec(\n\t\t\t\"PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON\",\n\t\t);\n\t\treturn new NodeSqliteDatabase(connection, descriptor, false);\n\t} catch (cause) {\n\t\tthrow unavailable(descriptor, cause);\n\t}\n}\n"]}