🎯 Improved cleanup timing - coordinate with complete analysis cycle
- 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
This commit is contained in:
@@ -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<void> {
|
||||
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('<27> 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<void> {
|
||||
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<void> {
|
||||
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 {
|
||||
|
||||
@@ -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<void> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user