feat: Fix progress bar hanging and improve UI responsiveness during indexing

Adds strategic yield points and direct stdout writes to prevent progress animation from freezing when the main thread is blocked by synchronous operations. Introduces 'finalizing' phase to smooth transition between parsing and resolving steps, ensuring progress reaches 100% completion.
This commit is contained in:
Colby McHenry
2026-04-06 09:50:30 -05:00
parent b768a9aa18
commit 9a2d3d9a13
5 changed files with 55 additions and 9 deletions
+13 -3
View File
@@ -1,6 +1,16 @@
import { parentPort, workerData } from 'worker_threads';
import { writeSync } from 'fs';
import type { ShimmerWorkerMessage } from './types';
// Write directly to fd 1 (stdout) instead of writeStdout().
// In Node.js worker threads, process.stdout is proxied through the main
// thread's event loop — so if the main thread is blocked (e.g. SQLite),
// stdout writes from the worker queue up and the animation freezes.
// fs.writeSync(1, ...) is a direct kernel syscall that bypasses this.
function writeStdout(s: string): void {
writeSync(1, s);
}
const SPINNER_GLYPHS = ['·', '✢', '✳', '✶', '✻', '✽'];
const ANIM_INTERVAL = 150;
const FRAMES_PER_GLYPH = 3;
@@ -74,16 +84,16 @@ function render(): void {
line = `${DM}${RST} ${color}${glyph}${RST} ${currentMessage}...`;
}
process.stdout.write(`\r\x1b[K${line}`);
writeStdout(`\r\x1b[K${line}`);
}
function finishPhase(): void {
if (!currentMessage) return;
process.stdout.write(`\r\x1b[K`);
writeStdout(`\r\x1b[K`);
let detail = '';
if (currentPercent >= 0) detail = ' — done';
else if (currentCount > 0) detail = `${formatNumber(currentCount)} found`;
process.stdout.write(`${DM}${RST} ${GRN}${RST} ${currentMessage}${detail}\n`);
writeStdout(`${DM}${RST} ${GRN}${RST} ${currentMessage}${detail}\n`);
currentMessage = '';
currentPercent = -1;
currentCount = 0;