@bobfrankston/mailx-store 0.1.49 → 0.1.50
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 +9 -0
- package/db.js +32 -1
- package/package.json +3 -3
package/db.d.ts
CHANGED
|
@@ -400,6 +400,15 @@ export declare class MailxDB {
|
|
|
400
400
|
} | null;
|
|
401
401
|
/** Clear a UID's prefetch-failure record after a successful fetch. */
|
|
402
402
|
clearPrefetchFailure(accountId: string, folderId: number, uid: number): void;
|
|
403
|
+
/** Wipe ALL prefetch-failure backoffs. Called once per boot: the backoff is
|
|
404
|
+
* a within-SESSION optimisation (it stops a poison body being re-fetched
|
|
405
|
+
* every 60s cycle), so a fresh session should give every body another try —
|
|
406
|
+
* the network may have recovered, and crucially a body backed off by a
|
|
407
|
+
* transient cause (a two-writer DB lock, a Dovecot 300s timeout) shouldn't
|
|
408
|
+
* stay suppressed for up to 12h (Bob 2026-06-14: "lots of predownloading
|
|
409
|
+
* not happening"). Genuine poison bodies simply re-fail once and re-back-off
|
|
410
|
+
* for the session — no per-cycle loop. */
|
|
411
|
+
clearAllPrefetchFailures(): number;
|
|
403
412
|
/** Highest server UID we've seen in this folder. After the
|
|
404
413
|
* message_folders refactor, this reads from the membership table
|
|
405
414
|
* rather than messages.uid — a server-side move from this folder
|
package/db.js
CHANGED
|
@@ -419,7 +419,13 @@ export class MailxDB {
|
|
|
419
419
|
// DDL/backfills concurrently would race on the WAL write lock.
|
|
420
420
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
421
421
|
this.db.exec("PRAGMA foreign_keys = ON");
|
|
422
|
-
|
|
422
|
+
// 10s (vs the main thread's 5s): this is the BACKGROUND writer (sync,
|
|
423
|
+
// prefetch); waiting a bit longer for the foreground's lock is fine.
|
|
424
|
+
// NOT higher because busy_timeout BLOCKS this thread synchronously
|
|
425
|
+
// (it can't forward sync events while parked) — for longer holds the
|
|
426
|
+
// prefetch write path uses an ASYNC retry that yields between
|
|
427
|
+
// attempts instead. Fixes prefetch "database is locked" (Bob 2026-06-14).
|
|
428
|
+
this.db.exec("PRAGMA busy_timeout = 10000");
|
|
423
429
|
return;
|
|
424
430
|
}
|
|
425
431
|
if (this.readOnly) {
|
|
@@ -569,6 +575,15 @@ export class MailxDB {
|
|
|
569
575
|
// this column landed. One UPDATE + an id roundtrip per row — cheap
|
|
570
576
|
// at our row counts, runs once per DB upgrade.
|
|
571
577
|
this.backfillUuids();
|
|
578
|
+
// Per-boot: clear prefetch-failure backoffs so transiently-failed bodies
|
|
579
|
+
// (two-writer DB lock, Dovecot timeout) get a fresh try this session
|
|
580
|
+
// instead of staying suppressed for up to 12h. See clearAllPrefetchFailures.
|
|
581
|
+
try {
|
|
582
|
+
const cleared = this.clearAllPrefetchFailures();
|
|
583
|
+
if (cleared > 0)
|
|
584
|
+
console.log(` [db] cleared ${cleared} prefetch-failure backoff(s) for a fresh session`);
|
|
585
|
+
}
|
|
586
|
+
catch { /* non-fatal */ }
|
|
572
587
|
// One-shot cleanup: the retired insertOptimisticSentRow path wrote
|
|
573
588
|
// synthetic-negative-UID rows into Sent. Those rows are stale (the
|
|
574
589
|
// real server-synced row eventually appears with a positive UID),
|
|
@@ -2235,6 +2250,22 @@ export class MailxDB {
|
|
|
2235
2250
|
clearPrefetchFailure(accountId, folderId, uid) {
|
|
2236
2251
|
this.db.prepare("DELETE FROM prefetch_failures WHERE account_id = ? AND folder_id = ? AND uid = ?").run(accountId, folderId, uid);
|
|
2237
2252
|
}
|
|
2253
|
+
/** Wipe ALL prefetch-failure backoffs. Called once per boot: the backoff is
|
|
2254
|
+
* a within-SESSION optimisation (it stops a poison body being re-fetched
|
|
2255
|
+
* every 60s cycle), so a fresh session should give every body another try —
|
|
2256
|
+
* the network may have recovered, and crucially a body backed off by a
|
|
2257
|
+
* transient cause (a two-writer DB lock, a Dovecot 300s timeout) shouldn't
|
|
2258
|
+
* stay suppressed for up to 12h (Bob 2026-06-14: "lots of predownloading
|
|
2259
|
+
* not happening"). Genuine poison bodies simply re-fail once and re-back-off
|
|
2260
|
+
* for the session — no per-cycle loop. */
|
|
2261
|
+
clearAllPrefetchFailures() {
|
|
2262
|
+
try {
|
|
2263
|
+
return this.db.prepare("DELETE FROM prefetch_failures").run().changes;
|
|
2264
|
+
}
|
|
2265
|
+
catch {
|
|
2266
|
+
return 0;
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2238
2269
|
/** Highest server UID we've seen in this folder. After the
|
|
2239
2270
|
* message_folders refactor, this reads from the membership table
|
|
2240
2271
|
* rather than messages.uid — a server-side move from this folder
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx-store",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@bobfrankston/mailx-types": "^0.1.19",
|
|
13
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
13
|
+
"@bobfrankston/mailx-settings": "^0.1.27",
|
|
14
14
|
"@bobfrankston/mailx-bus": "^0.1.2",
|
|
15
15
|
"mailparser": "^3.7.2"
|
|
16
16
|
},
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
".transformedSnapshot": {
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@bobfrankston/mailx-types": "^0.1.19",
|
|
33
|
-
"@bobfrankston/mailx-settings": "^0.1.
|
|
33
|
+
"@bobfrankston/mailx-settings": "^0.1.27",
|
|
34
34
|
"@bobfrankston/mailx-bus": "^0.1.2",
|
|
35
35
|
"mailparser": "^3.7.2"
|
|
36
36
|
}
|