From cca7303b4729e9cd31fd8f630e8677c987a5ee50 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Sat, 19 Jul 2025 00:44:27 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=AF=20Improved=20cleanup=20timing=20-?= =?UTF-8?q?=20coordinate=20with=20complete=20analysis=20cycle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Moved cleanup trigger from analysis phase to complete automation cycle - Cleanup now runs after trading decision is made (enter/hold/exit) - Added comprehensive post-cycle cleanup that waits for graceful shutdown - Enhanced cleanup coordination with analysis cycle completion signals - Force cleanup after complete cycle to ensure all zombie processes are killed - Added cleanup triggers for all cycle outcomes (trade executed, no opportunity, error, etc.) - Improved timing to wait for browser processes to close properly - Better correlation between analysis completion and process cleanup --- lib/aggressive-cleanup.ts | 95 ++++++++++++++++++++++++++----- lib/automation-service-simple.ts | 38 +++++++++---- prisma/prisma/dev.db | Bin 176128 -> 180224 bytes 3 files changed, 109 insertions(+), 24 deletions(-) diff --git a/lib/aggressive-cleanup.ts b/lib/aggressive-cleanup.ts index df25354..c7743a9 100644 --- a/lib/aggressive-cleanup.ts +++ b/lib/aggressive-cleanup.ts @@ -246,13 +246,13 @@ class AggressiveCleanup { } } - // New method for on-demand cleanup after analysis + // New method for on-demand cleanup after complete automation cycle async runPostAnalysisCleanup(): Promise { - console.log('๐Ÿงน Post-analysis cleanup triggered...') + console.log('๐Ÿงน Post-cycle cleanup triggered (analysis + decision complete)...') - // Small delay to ensure analysis processes are fully closed - console.log('โณ Waiting 3 seconds for analysis processes to close...') - await new Promise(resolve => setTimeout(resolve, 3000)) + // Wait for all browser processes to fully close + console.log('โณ Waiting 5 seconds for all processes to close gracefully...') + await new Promise(resolve => setTimeout(resolve, 5000)) // Check if there are still active sessions before cleaning try { @@ -260,20 +260,89 @@ class AggressiveCleanup { const activeSessions = progressTracker.getActiveSessions() if (activeSessions.length > 0) { - console.log(`โš ๏ธ Post-analysis cleanup: Still ${activeSessions.length} active sessions - deferring cleanup`) + console.log(`โš ๏ธ Post-cycle cleanup: Still ${activeSessions.length} active sessions detected`) + activeSessions.forEach(session => { + const progress = progressTracker.getProgress(session) + if (progress) { + const activeStep = progress.steps.find(step => step.status === 'active') + const currentStep = activeStep ? activeStep.title : 'Unknown' + console.log(` - ${session}: ${currentStep} (Step ${progress.currentStep}/${progress.totalSteps})`) + } + }) - // Schedule a delayed cleanup in case sessions don't clear properly - setTimeout(() => { - console.log('๐Ÿ• Running delayed post-analysis cleanup...') - this.cleanupOrphanedProcesses() - }, 10000) // 10 seconds later - return + // Force cleanup anyway since cycle is complete + console.log('๏ฟฝ Forcing cleanup - analysis cycle is complete regardless of session status') + + // Clean up the session tracker entries that might be stuck + activeSessions.forEach(session => { + console.log(`๐Ÿงน Force clearing stuck session: ${session}`) + progressTracker.deleteSession(session) + }) + } else { + console.log('โœ… No active sessions detected - proceeding with post-cycle cleanup') } } catch (error) { - console.warn('โš ๏ธ Could not check active sessions for post-analysis cleanup:', error) + console.warn('โš ๏ธ Could not check active sessions for post-cycle cleanup:', error) } + // Always run cleanup after complete automation cycle + console.log('๐Ÿงน Running comprehensive post-cycle cleanup...') await this.cleanupOrphanedProcesses() + + console.log('โœ… Post-cycle cleanup completed - all analysis processes should be cleaned up') + } + + // Signal that an analysis cycle is complete and all processes should be cleaned up + 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)) + + // Force cleanup of any remaining processes + console.log('๐Ÿงน Running forced cleanup after analysis cycle completion...') + await this.forceCleanupAfterCycle() + } + + private async forceCleanupAfterCycle(): Promise { + console.log('๐Ÿšจ Force cleanup after analysis cycle - cleaning all 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) { + try { + console.log(`๐Ÿ—ก๏ธ Force killing process ${pid} (cycle complete)`) + await execAsync(`kill -9 ${pid}`) + } catch (error) { + // Process might already be dead + console.log(`โ„น๏ธ Process ${pid} may already be 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) + } + + } catch (error) { + console.error('Error in force cleanup after cycle:', error) + } } stop(): void { diff --git a/lib/automation-service-simple.ts b/lib/automation-service-simple.ts index f6be9d1..7fc4b77 100644 --- a/lib/automation-service-simple.ts +++ b/lib/automation-service-simple.ts @@ -162,6 +162,8 @@ export class AutomationService { const todayTrades = await this.getTodayTradeCount(this.config.userId) if (todayTrades >= this.config.maxDailyTrades) { console.log(`๐Ÿ“Š Daily trade limit reached (${todayTrades}/${this.config.maxDailyTrades})`) + // Run cleanup even when trade limit is reached + await this.runPostCycleCleanup('trade_limit_reached') return } @@ -169,6 +171,8 @@ export class AutomationService { const analysisResult = await this.performAnalysis() if (!analysisResult) { console.log('โŒ Analysis failed, skipping cycle') + // Run cleanup when analysis fails + await this.runPostCycleCleanup('analysis_failed') return } @@ -182,16 +186,39 @@ export class AutomationService { const tradeDecision = await this.makeTradeDecision(analysisResult) if (!tradeDecision) { console.log('๐Ÿ“Š No trading opportunity found') + // Run cleanup when no trading opportunity + await this.runPostCycleCleanup('no_opportunity') return } // Step 6: Execute trade await this.executeTrade(tradeDecision) + + // Run cleanup after successful trade execution + await this.runPostCycleCleanup('trade_executed') } catch (error) { console.error('Error in automation cycle:', error) this.stats.errorCount++ this.stats.lastError = error instanceof Error ? error.message : 'Unknown error' + + // Run cleanup on error + await this.runPostCycleCleanup('error') + } + } + + 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)) + + try { + // Signal that the complete analysis cycle is done + await aggressiveCleanup.signalAnalysisCycleComplete() + console.log(`โœ… Post-cycle cleanup completed for: ${reason}`) + } catch (error) { + console.error('Error in post-cycle cleanup:', error) } } @@ -232,9 +259,6 @@ export class AutomationService { console.log('โŒ No multi-timeframe analysis results') progressTracker.updateStep(sessionId, 'capture', 'error', 'No analysis results captured') progressTracker.deleteSession(sessionId) - - // Run post-analysis cleanup - await aggressiveCleanup.runPostAnalysisCleanup() return null } @@ -248,9 +272,6 @@ export class AutomationService { console.log('โŒ Failed to combine multi-timeframe analysis') progressTracker.updateStep(sessionId, 'analysis', 'error', 'Failed to combine analysis results') progressTracker.deleteSession(sessionId) - - // Run post-analysis cleanup - await aggressiveCleanup.runPostAnalysisCleanup() return null } @@ -265,9 +286,6 @@ export class AutomationService { progressTracker.deleteSession(sessionId) }, 2000) - // Run post-analysis cleanup - await aggressiveCleanup.runPostAnalysisCleanup() - return combinedResult } catch (error) { @@ -277,8 +295,6 @@ export class AutomationService { progressTracker.deleteSession(sessionId) }, 5000) - // Run post-analysis cleanup even on error - await aggressiveCleanup.runPostAnalysisCleanup() return null } } diff --git a/prisma/prisma/dev.db b/prisma/prisma/dev.db index 57bbe1db2f63387b9c6e60487f12f49f28cd4703..e8c5a94266c6f9bc1783e3b22abb9005bf8e9727 100644 GIT binary patch delta 707 zcmZuvOHUI~6rOubErZgB5(pIR1p@*Wn3h%^8VUi8@`yxyK?tFbX*ecu^(octIh<{Hwpu z$vr2lnRg2LVcVJh;W}x{v07Kz8qS4#Q=|l}t1s=gw|r)EfUKKLtbf>wZ|;z;T{cS@ zn&*fUEM<)GI}iP7l2af?MUTd8__8*}^|(9k^G?}rGc4mz!J#9xo`+LdGXO4V z@}a#89^i5d$oTOOF=KHzOz)E-R90nXEg{ojLK+L}NRNUO7adSoJRxQg$~YmFr7|Q{ z(P=0aP@?#76iRW+0abXc2b{&(SV2t;jE2>uLWAO%nxuLn9#=JN`$QV?u?y^Z)QD+n zA{wK;?H!#sJ_HKVT9(sN3iCK4!(>rbHYQGpS|BRYDtE1CvYJMv2~oj1p8cga4aafz z8xe4M7%Fl78Pwx;E7YKKgY@IC4(P@AD^OC=(Ad)8tMht1gG1%l$_L%C{?k3@`a9h* Mc5f>)t^aGsKML&Q_W%F@ delta 164 zcmZo@;BI)pH9?wnA_D`1_Cy7H#)*vyTN4;{b461!(-SQX3=9l&^9-trD=f;gGgC6A zN8~fwPQRbas64$dmoad9a2{h4=h~D