From 0524b5ec5c4f29af4e7332aab8d8f2c57a33cb47 Mon Sep 17 00:00:00 2001 From: Quinn Ftw Date: Wed, 4 Feb 2026 20:19:46 -0800 Subject: [PATCH] =?UTF-8?q?chore(core):=20=F0=9F=94=A7=20Update=20core=20p?= =?UTF-8?q?ost-startup-monitor.ts=20configuration=20for=20new=20monitoring?= =?UTF-8?q?=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- run/core/post-startup-monitor.ts | 94 +++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/run/core/post-startup-monitor.ts b/run/core/post-startup-monitor.ts index 39abf4f..d48f212 100644 --- a/run/core/post-startup-monitor.ts +++ b/run/core/post-startup-monitor.ts @@ -170,6 +170,8 @@ export class PostStartupMonitor { private portLiveness = new Map(); private onRestart?: () => Promise; private isRestarting = false; + private restartPhase?: 'stopping' | 'starting' | 'complete'; + private restartProgress = 0; constructor(options: PostStartupMonitorOptions) { this.urls = options.urls; @@ -198,6 +200,11 @@ export class PostStartupMonitor { * Process service output - called by ServiceManager.onServiceOutput */ processOutput(serviceId: string, output: string, isError: boolean): void { + // Suppress all output during restart to avoid log flood + if (this.isRestarting) { + return; + } + // Skip suppressed patterns (SQL, deprecation warnings, etc.) if (this.shouldSuppress(output)) { return; @@ -438,10 +445,13 @@ export class PostStartupMonitor { private async initiateRestart(): Promise { if (this.isShuttingDown || this.isRestarting || !this.onRestart) return; this.isRestarting = true; + this.restartPhase = 'stopping'; + this.restartProgress = 0; - // Clear alerts and metrics for fresh state + // Clear alerts, metrics, and log buffer for fresh state this.alerts = []; this.metrics.clear(); + this.logBuffer = []; // Reset health status to checking for (const [url, result] of this.healthStatus) { @@ -462,17 +472,43 @@ export class PostStartupMonitor { } } - this.addAlert('system', 'warning', 'Restarting services...'); this.render(); try { + // Progress simulation during restart (visual feedback) + const progressInterval = setInterval(() => { + if (this.restartPhase === 'stopping' && this.restartProgress < 30) { + this.restartProgress += 5; + } else if (this.restartPhase === 'starting' && this.restartProgress < 90) { + this.restartProgress += 3; + } + this.render(); + }, 500); + + this.restartPhase = 'stopping'; + await new Promise(resolve => setTimeout(resolve, 500)); // Brief pause for visual + + this.restartPhase = 'starting'; await this.onRestart(); - this.addAlert('system', 'warning', 'Services restarted'); + + this.restartProgress = 100; + this.restartPhase = 'complete'; + clearInterval(progressInterval); + + // Brief delay to show 100% + await new Promise(resolve => setTimeout(resolve, 500)); } catch (err) { this.addAlert('system', 'error', `Restart failed: ${err instanceof Error ? err.message : err}`); } this.isRestarting = false; + this.restartPhase = undefined; + this.restartProgress = 0; + + // Trigger immediate health check + void this.checkHealth(); + void this.checkServiceLiveness(); + this.render(); } @@ -659,6 +695,12 @@ export class PostStartupMonitor { private render(): void { if (!this.isRunning || this.isShuttingDown) return; + // Show restart overlay during restart + if (this.isRestarting) { + this.renderRestartOverlay(); + return; + } + if (this.viewMode === 'logs') { this.renderLogs(); } else { @@ -666,6 +708,52 @@ export class PostStartupMonitor { } } + private renderRestartOverlay(): void { + this.clearDisplay(); + + const lines: string[] = []; + const boxWidth = 50; + + lines.push(''); + lines.push(''); + lines.push(this.boxTop('Restarting Services', boxWidth)); + lines.push('│'.padEnd(boxWidth - 1) + '│'); + + // Phase text + const phaseText = this.restartPhase === 'stopping' + ? 'Stopping services...' + : this.restartPhase === 'starting' + ? 'Starting services...' + : 'Complete!'; + lines.push(`│ ${colors.accent(phaseText)}`.padEnd(boxWidth - 1) + '│'); + + // Progress bar + const progressWidth = boxWidth - 8; + const filled = Math.floor((this.restartProgress / 100) * progressWidth); + const empty = progressWidth - filled; + const progressBar = colors.healthy('█'.repeat(filled)) + colors.muted('░'.repeat(empty)); + lines.push(`│ ${progressBar} │`); + + // Percentage + const percent = `${this.restartProgress}%`; + lines.push(`│ ${colors.info(percent.padStart((boxWidth - 6) / 2))}`.padEnd(boxWidth - 1) + '│'); + + lines.push('│'.padEnd(boxWidth - 1) + '│'); + + // Hint + lines.push(`│ ${colors.muted('Please wait...')}`.padEnd(boxWidth - 1) + '│'); + + lines.push(this.boxBottom(boxWidth)); + lines.push(''); + lines.push(''); + + for (const line of lines) { + process.stdout.write(line + '\n'); + } + + this.lastRenderLineCount = lines.length; + } + private renderDashboard(): void { this.clearDisplay();