diff --git a/lib/aggressive-cleanup.ts b/lib/aggressive-cleanup.ts index c7743a9..c89bcb9 100644 --- a/lib/aggressive-cleanup.ts +++ b/lib/aggressive-cleanup.ts @@ -296,55 +296,107 @@ class AggressiveCleanup { async signalAnalysisCycleComplete(): Promise { console.log('๐ŸŽฏ Analysis cycle completion signal received') - // Wait a bit longer to ensure all processes have had time to close - console.log('โณ Waiting 3 seconds for graceful process shutdown...') - await new Promise(resolve => setTimeout(resolve, 3000)) + // Wait for graceful shutdown of analysis-related processes + console.log('โณ Waiting 5 seconds for graceful process shutdown...') + await new Promise(resolve => setTimeout(resolve, 5000)) - // Force cleanup of any remaining processes - console.log('๐Ÿงน Running forced cleanup after analysis cycle completion...') - await this.forceCleanupAfterCycle() + // Check if there are any active progress sessions first + const activeSessions = await this.checkActiveAnalysisSessions() + if (activeSessions > 0) { + console.log(`โš ๏ธ Found ${activeSessions} active analysis sessions, skipping aggressive cleanup`) + return + } + + // Only run cleanup if no active sessions + console.log('๐Ÿงน No active sessions detected, running post-analysis cleanup...') + await this.cleanupPostAnalysisProcesses() } - private async forceCleanupAfterCycle(): Promise { - console.log('๐Ÿšจ Force cleanup after analysis cycle - cleaning all browser processes') + private async checkActiveAnalysisSessions(): Promise { + // Check if progress tracker has any active sessions + try { + // This is a simple check - in a real scenario you might want to check actual session state + const { stdout } = await execAsync('pgrep -f "automation-.*-.*" | wc -l') + return parseInt(stdout.trim()) || 0 + } catch (error) { + return 0 + } + } + + private async cleanupPostAnalysisProcesses(): Promise { + console.log('๐Ÿšจ Post-analysis cleanup - targeting orphaned browser processes') try { // Find all chromium processes const chromiumProcesses = await this.findChromiumProcesses() - if (chromiumProcesses.length > 0) { - console.log(`๐Ÿ” Found ${chromiumProcesses.length} chromium processes to clean after cycle completion`) - - // Force kill all chromium processes after cycle is complete - for (const pid of chromiumProcesses) { + if (chromiumProcesses.length === 0) { + console.log('โœ… No chromium processes found to clean up') + return + } + + console.log(`๐Ÿ” Found ${chromiumProcesses.length} chromium processes`) + + // Filter out processes that are too new (less than 2 minutes old) + const oldProcesses = await this.filterOldProcesses(chromiumProcesses, 2 * 60) // 2 minutes + + if (oldProcesses.length === 0) { + console.log('โœ… All chromium processes are recent, not cleaning up') + return + } + + console.log(`๐Ÿงน Cleaning up ${oldProcesses.length} old chromium processes`) + + // Try graceful shutdown first + for (const pid of oldProcesses) { + try { + console.log(`๏ฟฝ Attempting graceful shutdown of process ${pid}`) + await execAsync(`kill -TERM ${pid}`) + } catch (error) { + console.log(`โ„น๏ธ Process ${pid} may already be terminated`) + } + } + + // Wait for graceful shutdown + await new Promise(resolve => setTimeout(resolve, 3000)) + + // Check which processes are still running and force kill only those + const stillRunning = await this.findStillRunningProcesses(oldProcesses) + + if (stillRunning.length > 0) { + console.log(`๐Ÿ—ก๏ธ Force killing ${stillRunning.length} stubborn processes`) + for (const pid of stillRunning) { try { - console.log(`๐Ÿ—ก๏ธ Force killing process ${pid} (cycle complete)`) await execAsync(`kill -9 ${pid}`) + console.log(`๐Ÿ’€ Force killed process ${pid}`) } catch (error) { - // Process might already be dead - console.log(`โ„น๏ธ Process ${pid} may already be terminated`) + console.log(`โ„น๏ธ Process ${pid} already terminated`) } } - - console.log(`โœ… Forcefully cleaned ${chromiumProcesses.length} processes after cycle completion`) - } else { - console.log('โœ… No chromium processes found - cleanup already complete') } - // Clean up temp directories - try { - await execAsync('rm -rf /tmp/puppeteer_dev_chrome_profile-* 2>/dev/null || true') - await execAsync('rm -rf /dev/shm/.org.chromium.* 2>/dev/null || true') - console.log('โœ… Cleaned up temp directories and shared memory') - } catch (error) { - console.warn('โš ๏ธ Could not clean temp directories:', error) - } + console.log('โœ… Post-analysis cleanup completed') } catch (error) { - console.error('Error in force cleanup after cycle:', error) + console.error('Error in post-analysis cleanup:', error) } } + private async findStillRunningProcesses(pids: string[]): Promise { + const stillRunning: string[] = [] + + for (const pid of pids) { + try { + await execAsync(`kill -0 ${pid}`) // Check if process exists + stillRunning.push(pid) + } catch (error) { + // Process is already dead + } + } + + return stillRunning + } + stop(): void { if (this.cleanupInterval) { clearInterval(this.cleanupInterval) diff --git a/lib/automation-service-simple.ts b/lib/automation-service-simple.ts index 7fc4b77..dfef9e6 100644 --- a/lib/automation-service-simple.ts +++ b/lib/automation-service-simple.ts @@ -210,8 +210,8 @@ export class AutomationService { private async runPostCycleCleanup(reason: string): Promise { console.log(`๐Ÿงน Running post-cycle cleanup (reason: ${reason})`) - // Small delay to ensure all analysis processes have finished - await new Promise(resolve => setTimeout(resolve, 2000)) + // Longer delay to ensure all analysis processes AND trading decision have finished + await new Promise(resolve => setTimeout(resolve, 10000)) // 10 seconds try { // Signal that the complete analysis cycle is done