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:
@@ -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)
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user