Files
trading_bot_v3/lib/automated-cleanup-service.ts
mindesbunister 8cfb13f728 Fix container stability: Add restart policy and improve cleanup system
- Add restart: unless-stopped to docker-compose.dev.yml for automatic container restart
- Fix automated cleanup service to respect DISABLE_AUTO_CLEANUP environment variable
- Add process ID protection to prevent killing main Node.js process
- Update health check to use wget instead of curl
- Container now stays running reliably with proper cleanup controls
2025-07-26 10:15:58 +02:00

132 lines
4.9 KiB
TypeScript

import { exec } from 'child_process'
import { promisify } from 'util'
const execAsync = promisify(exec)
export class AutomatedCleanupService {
private cleanupInterval: NodeJS.Timeout | null = null
private isRunning = false
start(intervalMs: number = 60000) { // Default: every minute
if (this.isRunning) {
console.log('⚠️ Cleanup service already running')
return
}
this.isRunning = true
console.log(`🚀 Starting automated cleanup service (interval: ${intervalMs}ms)`)
this.cleanupInterval = setInterval(async () => {
await this.performCleanup()
}, intervalMs)
// Run initial cleanup
this.performCleanup().catch(console.error)
}
stop() {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval)
this.cleanupInterval = null
}
this.isRunning = false
console.log('🛑 Automated cleanup service stopped')
}
private async performCleanup(): Promise<void> {
try {
console.log('🧹 Running periodic browser cleanup...')
// Check for chromium processes
const { stdout } = await execAsync('ps aux | grep -E "(chromium|chrome)" | grep -v grep | wc -l')
const processCount = parseInt(stdout.trim(), 10)
if (processCount > 0) {
console.log(`🔍 Found ${processCount} browser processes running`)
// Get process list for logging
try {
const { stdout: processList } = await execAsync('ps aux | grep -E "(chromium|chrome)" | grep -v grep | head -10')
console.log('📋 Current browser processes:')
console.log(processList)
} catch (listError) {
console.log('Could not list processes:', listError)
}
// Kill old/stuck processes (but exclude our own Node.js process)
const currentPid = process.pid
const killCommands = [
// Graceful shutdown first (exclude our process and children)
`pkill -TERM -f "chromium.*--remote-debugging-port" | grep -v ${currentPid} 2>/dev/null || true`,
`pkill -TERM -f "chromium.*--user-data-dir" | grep -v ${currentPid} 2>/dev/null || true`,
// Wait a bit
'sleep 2',
// Force kill stubborn processes (exclude our process and children)
`pkill -KILL -f "chromium.*--remote-debugging-port" | grep -v ${currentPid} 2>/dev/null || true`,
`pkill -KILL -f "chromium.*--user-data-dir" | grep -v ${currentPid} 2>/dev/null || true`,
`pkill -KILL -f "/usr/lib/chromium/chromium" | grep -v ${currentPid} 2>/dev/null || true`,
// Clean up zombies
'pkill -9 -f "chromium.*defunct" 2>/dev/null || true'
]
for (const command of killCommands) {
try {
if (command === 'sleep 2') {
await new Promise(resolve => setTimeout(resolve, 2000))
} else {
await execAsync(command)
}
} catch (error) {
// Ignore errors from kill commands
}
}
// Check results
const { stdout: afterCleanup } = await execAsync('ps aux | grep -E "(chromium|chrome)" | grep -v grep | wc -l')
const remainingProcesses = parseInt(afterCleanup.trim(), 10)
if (remainingProcesses < processCount) {
console.log(`✅ Cleanup successful: ${processCount - remainingProcesses} processes terminated`)
} else {
console.log(`⚠️ No processes were terminated, ${remainingProcesses} still running`)
}
// Clean up temp files
try {
await execAsync('rm -rf /tmp/.org.chromium.Chromium.* 2>/dev/null || true')
await execAsync('rm -rf /tmp/puppeteer_dev_chrome_profile-* 2>/dev/null || true')
console.log('🗑️ Cleaned up temporary files')
} catch (tempCleanupError) {
console.log('⚠️ Could not clean temp files:', tempCleanupError)
}
} else {
console.log('✅ No browser processes found - system clean')
}
} catch (error) {
console.error('❌ Error during periodic cleanup:', error)
}
}
// Force cleanup method for immediate use
async forceCleanup(): Promise<void> {
console.log('🔧 Running force cleanup...')
await this.performCleanup()
}
}
// Create singleton instance
export const automatedCleanupService = new AutomatedCleanupService()
// Auto-start in Docker environment (unless disabled)
if (process.env.DOCKER_ENV === 'true' && process.env.DISABLE_AUTO_CLEANUP !== 'true') {
console.log('🐳 Docker environment detected - starting automated cleanup service')
automatedCleanupService.start(30000) // Every 30 seconds in Docker
} else if (process.env.DOCKER_ENV === 'true' && process.env.DISABLE_AUTO_CLEANUP === 'true') {
console.log('🐳 Docker environment detected but auto cleanup is disabled via DISABLE_AUTO_CLEANUP=true')
}