fix: emergency automation fix - stop runaway trading loops

- Replace automation service with emergency rate-limited version
- Add 5-minute minimum interval between automation starts
- Implement forced Chromium process cleanup on stop
- Backup broken automation service as .broken file
- Emergency service prevents multiple simultaneous automations
- Fixed 1400+ Chromium process accumulation issue
- Tested and confirmed: rate limiting works, processes stay at 0
This commit is contained in:
mindesbunister
2025-07-24 20:33:20 +02:00
parent ab8fb7c202
commit 1e4f305657
23 changed files with 3837 additions and 193 deletions

View File

@@ -1,7 +1,8 @@
import { NextResponse } from 'next/server'
import { batchScreenshotService, BatchScreenshotConfig } from '../../../lib/enhanced-screenshot-batch'
import { createBatchScreenshotService, BatchScreenshotConfig } from '../../../lib/enhanced-screenshot-batch'
import { batchAIAnalysisService } from '../../../lib/ai-analysis-batch'
import { progressTracker } from '../../../lib/progress-tracker'
import { automationService } from '../../../lib/automation-service-simple'
export async function POST(request) {
try {
@@ -29,6 +30,22 @@ export async function POST(request) {
mode
})
// Check for open positions before starting analysis
try {
const hasPositions = await automationService.hasOpenPositions();
if (hasPositions) {
console.log('⏸️ Stopping analysis - open positions detected');
return NextResponse.json({
success: false,
error: 'Analysis stopped - open positions detected',
message: 'Cannot start new analysis while positions are open'
}, { status: 400 });
}
} catch (error) {
console.error('Error checking positions:', error);
// Continue analysis if position check fails (fail-safe)
}
// ALWAYS use batch processing first - even for automation mode
// Then integrate with automation service if needed
@@ -94,7 +111,9 @@ export async function POST(request) {
console.log('🔧 Using optimized batch config:', batchConfig)
const captureStartTime = Date.now()
const screenshotBatches = await batchScreenshotService.captureMultipleTimeframes(batchConfig)
// Create a dedicated batch service instance for this request
const batchService = createBatchScreenshotService(sessionId)
const screenshotBatches = await batchService.captureMultipleTimeframes(batchConfig)
const captureTime = ((Date.now() - captureStartTime) / 1000).toFixed(1)
console.log(`✅ BATCH CAPTURE COMPLETED in ${captureTime}s`)
@@ -267,7 +286,10 @@ export async function POST(request) {
} finally {
// Cleanup batch screenshot service
try {
await batchScreenshotService.cleanup()
// Ensure cleanup happens
if (typeof batchService !== 'undefined') {
await batchService.cleanup()
}
console.log('🧹 Batch screenshot service cleaned up')
} catch (cleanupError) {
console.error('Warning: Batch cleanup failed:', cleanupError)

View File

@@ -1,41 +1,18 @@
import { NextResponse } from 'next/server'
import { automationService } from '@/lib/automation-service-simple'
import { emergencyAutomation } from '@/lib/emergency-automation'
export async function POST(request) {
try {
const config = await request.json()
console.log('🚨 EMERGENCY: Automation start request received')
// Add a default userId for now (in production, get from auth)
const automationConfig = {
userId: 'default-user',
...config,
// Map asset to symbol if asset is provided
symbol: config.asset || config.symbol,
// Map simulation to mode
mode: config.simulation ? 'SIMULATION' : (config.mode || 'SIMULATION'),
// stopLossPercent and takeProfitPercent removed - AI calculates these automatically
// Map tradeSize to tradingAmount
tradingAmount: config.tradeSize || config.tradingAmount,
// Set defaults for missing fields
maxDailyTrades: config.maxDailyTrades || 5,
dexProvider: config.dexProvider || 'DRIFT',
selectedTimeframes: config.selectedTimeframes || [config.timeframe || '1h']
}
const result = await emergencyAutomation.start(config)
const success = await automationService.startAutomation(automationConfig)
if (success) {
return NextResponse.json({ success: true, message: 'Automation started successfully' })
} else {
return NextResponse.json({ success: false, error: 'Failed to start automation' }, { status: 500 })
}
return Response.json(result)
} catch (error) {
console.error('Start automation error:', error)
return NextResponse.json({
success: false,
error: 'Internal server error',
message: error.message,
stack: error.stack
console.error('Emergency start failed:', error)
return Response.json({
success: false,
message: 'Emergency start failed: ' + error.message
}, { status: 500 })
}
}

View File

@@ -1,41 +1,17 @@
import { NextResponse } from 'next/server'
import { automationService } from '../../../../lib/automation-service-simple'
import { emergencyAutomation } from '../../../../lib/emergency-automation'
export async function GET() {
try {
// Get status from the automation service directly (includes timing and individual results)
const status = await automationService.getStatus()
const status = emergencyAutomation.getStatus()
if (!status) {
return NextResponse.json({
success: true,
status: {
isActive: false,
mode: 'SIMULATION',
symbol: 'SOLUSD',
timeframe: '1h',
totalTrades: 0,
successfulTrades: 0,
winRate: 0,
totalPnL: 0,
errorCount: 0,
nextAnalysisIn: 0,
analysisInterval: 3600,
currentCycle: 0,
individualTimeframeResults: []
}
})
}
return NextResponse.json({
return Response.json({
success: true,
status: status
status
})
} catch (error) {
console.error('Automation status error:', error)
return NextResponse.json({
return Response.json({
success: false,
error: 'Failed to get automation status'
error: error.message
}, { status: 500 })
}
}

View File

@@ -1,44 +1,25 @@
import { NextResponse } from 'next/server'
import { automationService } from '@/lib/automation-service-simple'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
import { emergencyAutomation } from '@/lib/emergency-automation'
export async function POST() {
try {
console.log('🛑 Stop automation request received')
console.log('🚨 EMERGENCY: Stop request received')
// Stop the automation service
console.log('🛑 Calling automationService.stopAutomation()')
const success = await automationService.stopAutomation()
console.log('🛑 Stop automation result:', success)
const result = await emergencyAutomation.stop()
// Also update all active automation sessions in database to INACTIVE
console.log('🛑 Updating database sessions to STOPPED')
const updateResult = await prisma.automationSession.updateMany({
where: {
status: 'ACTIVE'
},
data: {
status: 'STOPPED', // Use STOPPED instead of INACTIVE for clarity
updatedAt: new Date()
}
})
console.log('🛑 Database update result:', updateResult)
console.log('🛑 All automation sessions marked as STOPPED in database')
if (success) {
return NextResponse.json({ success: true, message: 'Automation stopped successfully' })
} else {
return NextResponse.json({ success: false, error: 'Failed to stop automation' }, { status: 500 })
// Also force kill any remaining processes
try {
const { execSync } = require('child_process')
execSync('pkill -f "chrome|chromium" 2>/dev/null || true')
console.log('✅ EMERGENCY: Cleanup completed')
} catch (cleanupError) {
console.error('Cleanup error:', cleanupError.message)
}
return Response.json(result)
} catch (error) {
console.error('Stop automation error:', error)
return NextResponse.json({
success: false,
error: 'Internal server error',
message: error.message
return Response.json({
success: false,
message: error.message
}, { status: 500 })
}
}

View File

@@ -23,6 +23,23 @@ export async function GET(request: NextRequest) {
console.log('📋 Config:', testConfig)
// Check for open positions before starting test automation
console.log('\n🔍 Checking for open positions...')
try {
const hasPositions = await automationService.hasOpenPositions();
if (hasPositions) {
console.log('⏸️ Test aborted - open positions detected');
return NextResponse.json({
success: false,
error: 'Cannot test automation while positions are open',
message: 'Please close existing positions before running automation tests'
}, { status: 400 });
}
console.log('✅ No open positions, proceeding with test...')
} catch (error) {
console.error('⚠️ Error checking positions, continuing test anyway:', error);
}
// Test starting automation
console.log('\n🚀 Starting automation...')
const startResult = await automationService.startAutomation(testConfig)