fix(mail): BigInt-Serialisierung blockierte Phase-2-Persistierung
imapflow.status() liefert uidValidity als BigInt. Der Code reichte den BigInt in
JSON.stringify (patchFolderScanState) → 'TypeError: Do not know how to serialize
a BigInt' → vom stummen connection-level catch verschluckt → weder
patchFolderScanState noch markFullSweepDone liefen je → folder_scan_state blieb
{} + last_full_sweep_at NULL → inkrementeller Scan aktivierte nie (immer Full-Sweep).
Fix:
- serverUidValidity: Number((status).uidValidity ?? 0) — BigInt → number vor JSON.
- Stumme catches (auth/lock/conn) loggen jetzt; Persist-Calls (patchFolderScanState
x2, markFullSweepDone) in eigene try/catch mit console.error — Diagnostik bleibt
drin für Post-Deploy-Verify.
Lokal verifiziert: Build EXIT 0, imapflow extern.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
cc549c7f17
commit
1f73bd8d8d
@ -78,7 +78,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
let imapAuth: { user: string; accessToken: string } | { user: string; pass: string };
|
let imapAuth: { user: string; accessToken: string } | { user: string; pass: string };
|
||||||
try {
|
try {
|
||||||
imapAuth = await resolveImapAuth(connection, oauthClientIds);
|
imapAuth = await resolveImapAuth(connection, oauthClientIds);
|
||||||
} catch {
|
} catch (authErr) {
|
||||||
|
console.error(`[scan-internal] resolveImapAuth failed for ${connection.email}:`, authErr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +137,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
let lock: any;
|
let lock: any;
|
||||||
try {
|
try {
|
||||||
lock = await imap.getMailboxLock(mb.path);
|
lock = await imap.getMailboxLock(mb.path);
|
||||||
} catch {
|
} catch (lockErr) {
|
||||||
|
console.warn(`[scan-internal] ${connection.email} | ${mb.path} | getMailboxLock failed, skipping folder:`, lockErr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -149,16 +151,25 @@ export default defineEventHandler(async (event) => {
|
|||||||
uidValidity: true,
|
uidValidity: true,
|
||||||
});
|
});
|
||||||
const msgCount = (status as any).messages ?? 0;
|
const msgCount = (status as any).messages ?? 0;
|
||||||
const serverUidValidity: number = (status as any).uidValidity ?? 0;
|
// imapflow liefert uidValidity als BigInt (IMAP-Spec: 32-bit unsigned).
|
||||||
|
// Number() konvertiert BigInt sicher — UIDVALIDITY ist max 2^32-1, weit unter
|
||||||
|
// Number.MAX_SAFE_INTEGER (2^53-1), kein Präzisionsverlust möglich.
|
||||||
|
// Ohne Number() würde JSON.stringify({uidvalidity: BigInt(x)}) werfen und
|
||||||
|
// patchFolderScanState still crashen (verschluckt vom äußeren catch {}).
|
||||||
|
const serverUidValidity: number = Number((status as any).uidValidity ?? 0);
|
||||||
|
|
||||||
if (msgCount === 0) {
|
if (msgCount === 0) {
|
||||||
// Ordner leer — trotzdem Zustand für diesen Ordner persistieren
|
// Ordner leer — trotzdem Zustand für diesen Ordner persistieren
|
||||||
// (verhindert endloses Re-Fetching auf leere Ordner).
|
// (verhindert endloses Re-Fetching auf leere Ordner).
|
||||||
if (serverUidValidity > 0) {
|
if (serverUidValidity > 0) {
|
||||||
await patchFolderScanState(connection.id, mb.path, {
|
try {
|
||||||
lastUid: 0,
|
await patchFolderScanState(connection.id, mb.path, {
|
||||||
uidvalidity: serverUidValidity,
|
lastUid: 0,
|
||||||
});
|
uidvalidity: serverUidValidity,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[scan-internal] persist failed — patchFolderScanState(${mb.path}, empty folder):`, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -353,10 +364,14 @@ export default defineEventHandler(async (event) => {
|
|||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
if (maxUid > 0 && serverUidValidity > 0) {
|
if (maxUid > 0 && serverUidValidity > 0) {
|
||||||
await patchFolderScanState(connection.id, mb.path, {
|
try {
|
||||||
lastUid: maxUid,
|
await patchFolderScanState(connection.id, mb.path, {
|
||||||
uidvalidity: serverUidValidity,
|
lastUid: maxUid,
|
||||||
});
|
uidvalidity: serverUidValidity,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[scan-internal] persist failed — patchFolderScanState(${mb.path}, maxUid=${maxUid}, uidvalidity=${serverUidValidity}):`, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
lock.release();
|
lock.release();
|
||||||
@ -365,12 +380,17 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
// ─── Full-Sweep abschließen ─────────────────────────────────────────────
|
// ─── Full-Sweep abschließen ─────────────────────────────────────────────
|
||||||
if (needsFullSweep) {
|
if (needsFullSweep) {
|
||||||
await markFullSweepDone(connection.id);
|
try {
|
||||||
console.log(`[scan-internal] ${connection.email} | full-sweep complete, lastFullSweepAt updated`);
|
await markFullSweepDone(connection.id);
|
||||||
|
console.log(`[scan-internal] ${connection.email} | full-sweep complete, lastFullSweepAt updated`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`[scan-internal] persist failed — markFullSweepDone(${connection.id}):`, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await imap.logout();
|
await imap.logout();
|
||||||
} catch {
|
} catch (connErr) {
|
||||||
|
console.error(`[scan-internal] connection-level error for ${connection.email}:`, connErr);
|
||||||
try {
|
try {
|
||||||
await imap.logout();
|
await imap.logout();
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user