@bobfrankston/mailx-store 0.1.48 → 0.1.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db.d.ts +1 -0
- package/db.js +19 -0
- package/package.json +1 -1
package/db.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class MailxDB {
|
|
|
15
15
|
readonly readOnly: boolean;
|
|
16
16
|
constructor(dbDir: string, opts?: {
|
|
17
17
|
readOnly?: boolean;
|
|
18
|
+
skipMigrations?: boolean;
|
|
18
19
|
});
|
|
19
20
|
/** Fail loud + early if expected columns are missing. Cheap (PRAGMA only
|
|
20
21
|
* runs at startup). The user-facing message names the recovery command. */
|
package/db.js
CHANGED
|
@@ -412,6 +412,16 @@ export class MailxDB {
|
|
|
412
412
|
const dbPath = path.join(dbDir, "mailx.db");
|
|
413
413
|
this.readOnly = !!opts.readOnly;
|
|
414
414
|
this.db = new DatabaseSync(dbPath);
|
|
415
|
+
if (opts.skipMigrations && !opts.readOnly) {
|
|
416
|
+
// Write-capable connection that does NOT run schema/migrations —
|
|
417
|
+
// used by the sync worker, which opens its own writer AFTER the
|
|
418
|
+
// main thread has already built the schema. Two threads running the
|
|
419
|
+
// DDL/backfills concurrently would race on the WAL write lock.
|
|
420
|
+
this.db.exec("PRAGMA journal_mode = WAL");
|
|
421
|
+
this.db.exec("PRAGMA foreign_keys = ON");
|
|
422
|
+
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
415
425
|
if (this.readOnly) {
|
|
416
426
|
// Read-worker connection (Phase 0 read isolation). The main-thread
|
|
417
427
|
// MailxDB has ALREADY created the schema and run every migration /
|
|
@@ -430,10 +440,19 @@ export class MailxDB {
|
|
|
430
440
|
// so readers see committed snapshots with no journal_mode call.
|
|
431
441
|
this.db.exec("PRAGMA foreign_keys = ON");
|
|
432
442
|
this.db.exec("PRAGMA query_only = ON");
|
|
443
|
+
// A reader can briefly collide with a WAL checkpoint; wait, don't throw.
|
|
444
|
+
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
433
445
|
return;
|
|
434
446
|
}
|
|
435
447
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
436
448
|
this.db.exec("PRAGMA foreign_keys = ON");
|
|
449
|
+
// Multi-writer foundation for the sync-worker migration: once sync runs
|
|
450
|
+
// on its own thread with its own write connection, it and the main
|
|
451
|
+
// thread are two writers on one WAL file. WAL serializes writers, so a
|
|
452
|
+
// collision returns SQLITE_BUSY *immediately* by default — busy_timeout
|
|
453
|
+
// makes the loser WAIT for the lock (up to 5s) instead of failing. Safe
|
|
454
|
+
// and inert today (single writer); required before the worker lands.
|
|
455
|
+
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
437
456
|
this.db.exec(SCHEMA);
|
|
438
457
|
this.migrateFtsSchema();
|
|
439
458
|
// Purge phantom uid=0 rows (invalid IMAP UID — empty stub letters, the
|