show live email count during gmail sync instead of mbsync log lines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 05:00:18 +00:00
co-authored by Claude Opus 4.6
parent ed67cfa8e9
commit 726c77e346
+27 -9
View File
@@ -246,8 +246,23 @@ const gmailSyncHandler: JobHandler = {
throw new PermanentError(`Failed to start mbsync: ${msg}`);
}
// Stream stderr for live progress
let lastLine = '';
// Periodically count downloaded emails and update progress
let emailCount = 0;
let counting = true;
const countLoop = (async () => {
while (counting) {
await new Promise((r) => setTimeout(r, 3000));
if (!counting) break;
emailCount = await countMaildirFiles(maildirPath);
ctx.updateProgress({
current: emailCount,
total: 0,
label: `Downloading — ${emailCount.toLocaleString()} emails`,
});
}
})();
// Stream stderr for logging
let stderrBuf = '';
const reader = (proc.stderr as ReadableStream<Uint8Array>).getReader();
const decoder = new TextDecoder();
@@ -260,18 +275,15 @@ const gmailSyncHandler: JobHandler = {
const lines = chunk.split('\n');
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed) continue;
lastLine = trimmed;
console.log(`[gmail-sync] mbsync: ${trimmed}`);
}
if (lastLine) {
ctx.updateProgress({ current: 0, total: 0, label: `mbsync: ${lastLine.slice(0, 80)}` });
if (trimmed) console.log(`[gmail-sync] mbsync: ${trimmed}`);
}
}
})();
const exitCode = await proc.exited;
counting = false;
await readLoop;
await countLoop;
if (exitCode !== 0) {
const isOverquota = stderrBuf.includes('OVERQUOTA');
@@ -296,7 +308,13 @@ const gmailSyncHandler: JobHandler = {
throw new Error(`mbsync exited with code ${exitCode}: ${stderrBuf.slice(-500)}`);
}
} else {
console.log('[gmail-sync] mbsync completed successfully');
emailCount = await countMaildirFiles(maildirPath);
console.log(`[gmail-sync] mbsync completed successfully — ${emailCount} emails`);
await ctx.updateProgress({
current: emailCount,
total: emailCount,
label: `Download complete — ${emailCount.toLocaleString()} emails`,
});
}
} finally {
// Always clean up config (contains password)