Fix race condition in progress tracking EventSource

- Add debugging logs to progress stream endpoint
- Create placeholder session when EventSource connects before API call
- Prevents 404 errors when EventSource tries to connect to non-existent session
- Ensures progress tracking works correctly even with timing issues

This fixes the issue where UI remained stuck on 'TradingView Authentication'
even though backend was correctly progressing through all steps.
This commit is contained in:
mindesbunister
2025-07-17 13:02:41 +02:00
parent 142d271c2c
commit 01f4a9f89a

View File

@@ -7,35 +7,50 @@ export async function GET(
) { ) {
const { sessionId } = await params const { sessionId } = await params
console.log(`🔍 [STREAM] Starting EventSource stream for session: ${sessionId}`)
console.log(`🔍 [STREAM] Current active sessions:`, progressTracker.getActiveSessions())
// Create a readable stream for Server-Sent Events // Create a readable stream for Server-Sent Events
const encoder = new TextEncoder() const encoder = new TextEncoder()
const stream = new ReadableStream({ const stream = new ReadableStream({
start(controller) { start(controller) {
console.log(`🔍 Starting EventSource stream for session: ${sessionId}`) console.log(`🔍 [STREAM] Stream controller started for session: ${sessionId}`)
// Send initial progress if session exists // Send initial progress if session exists
const initialProgress = progressTracker.getProgress(sessionId) const initialProgress = progressTracker.getProgress(sessionId)
if (initialProgress) { if (initialProgress) {
console.log(`🔍 Sending initial progress for ${sessionId}:`, initialProgress.currentStep) console.log(`🔍 [STREAM] Sending initial progress for ${sessionId}:`, initialProgress.currentStep)
const data = `data: ${JSON.stringify(initialProgress)}\n\n` const data = `data: ${JSON.stringify(initialProgress)}\n\n`
controller.enqueue(encoder.encode(data)) controller.enqueue(encoder.encode(data))
} else { } else {
// Send a connection established message even if no progress yet console.log(`🔍 [STREAM] No initial progress found for ${sessionId}, creating placeholder session`)
// Create a placeholder session if it doesn't exist to handle race condition
const placeholderSteps = [
{ id: 'init', title: 'Initializing Analysis', description: 'Starting AI-powered trading analysis...', status: 'pending' as const },
{ id: 'auth', title: 'TradingView Authentication', description: 'Logging into TradingView accounts', status: 'pending' as const },
{ id: 'navigation', title: 'Chart Navigation', description: 'Navigating to chart layouts', status: 'pending' as const },
{ id: 'loading', title: 'Chart Data Loading', description: 'Waiting for chart data and indicators', status: 'pending' as const },
{ id: 'capture', title: 'Screenshot Capture', description: 'Capturing high-quality screenshots', status: 'pending' as const },
{ id: 'analysis', title: 'AI Analysis', description: 'Analyzing screenshots with AI', status: 'pending' as const }
]
progressTracker.createSession(sessionId, placeholderSteps)
// Send a connection established message
const connectMsg = `data: ${JSON.stringify({ type: 'connected', sessionId })}\n\n` const connectMsg = `data: ${JSON.stringify({ type: 'connected', sessionId })}\n\n`
controller.enqueue(encoder.encode(connectMsg)) controller.enqueue(encoder.encode(connectMsg))
} }
// Listen for progress updates // Listen for progress updates
const progressHandler = (progress: any) => { const progressHandler = (progress: any) => {
console.log(`🔍 Streaming progress update for ${sessionId}:`, progress.currentStep) console.log(`🔍 [STREAM] Streaming progress update for ${sessionId}:`, progress.currentStep)
const data = `data: ${JSON.stringify(progress)}\n\n` const data = `data: ${JSON.stringify(progress)}\n\n`
controller.enqueue(encoder.encode(data)) controller.enqueue(encoder.encode(data))
} }
// Listen for completion // Listen for completion
const completeHandler = () => { const completeHandler = () => {
console.log(`🔍 Streaming completion for ${sessionId}`) console.log(`🔍 [STREAM] Streaming completion for ${sessionId}`)
const data = `data: ${JSON.stringify({ type: 'complete' })}\n\n` const data = `data: ${JSON.stringify({ type: 'complete' })}\n\n`
controller.enqueue(encoder.encode(data)) controller.enqueue(encoder.encode(data))
controller.close() controller.close()
@@ -45,8 +60,11 @@ export async function GET(
progressTracker.on(`progress:${sessionId}`, progressHandler) progressTracker.on(`progress:${sessionId}`, progressHandler)
progressTracker.on(`progress:${sessionId}:complete`, completeHandler) progressTracker.on(`progress:${sessionId}:complete`, completeHandler)
console.log(`🔍 [STREAM] Event listeners registered for ${sessionId}`)
// Cleanup on stream close // Cleanup on stream close
request.signal.addEventListener('abort', () => { request.signal.addEventListener('abort', () => {
console.log(`🔍 [STREAM] Stream aborted for ${sessionId}`)
progressTracker.off(`progress:${sessionId}`, progressHandler) progressTracker.off(`progress:${sessionId}`, progressHandler)
progressTracker.off(`progress:${sessionId}:complete`, completeHandler) progressTracker.off(`progress:${sessionId}:complete`, completeHandler)
controller.close() controller.close()