Fix progress tracking synchronization issues
- Pre-generate sessionId on client side before API call to avoid race conditions - Add small delays in progress tracker to ensure EventSource connection is established - Improve logging and error handling in progress streaming - Add connection confirmation messages in EventSource stream - Fix TypeScript interface to include sessionId in AnalysisProgress This should resolve the lag between actual analysis progress and progress bar display.
This commit is contained in:
@@ -6,13 +6,13 @@ import { progressTracker } from '../../../lib/progress-tracker'
|
|||||||
export async function POST(request) {
|
export async function POST(request) {
|
||||||
try {
|
try {
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
const { symbol, layouts, timeframe, timeframes, selectedLayouts, analyze = true } = body
|
const { symbol, layouts, timeframe, timeframes, selectedLayouts, analyze = true, sessionId: providedSessionId } = body
|
||||||
|
|
||||||
console.log('📊 Enhanced screenshot request:', { symbol, layouts, timeframe, timeframes, selectedLayouts })
|
console.log('📊 Enhanced screenshot request:', { symbol, layouts, timeframe, timeframes, selectedLayouts, providedSessionId })
|
||||||
|
|
||||||
// Generate unique session ID for progress tracking
|
// Use provided sessionId or generate one
|
||||||
const sessionId = `analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
const sessionId = providedSessionId || `analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||||||
console.log('🔍 Created session ID:', sessionId)
|
console.log('🔍 Using session ID:', sessionId)
|
||||||
|
|
||||||
// Create progress tracking session with initial steps
|
// Create progress tracking session with initial steps
|
||||||
const initialSteps = [
|
const initialSteps = [
|
||||||
|
|||||||
@@ -12,21 +12,30 @@ export async function GET(
|
|||||||
|
|
||||||
const stream = new ReadableStream({
|
const stream = new ReadableStream({
|
||||||
start(controller) {
|
start(controller) {
|
||||||
|
console.log(`🔍 Starting EventSource stream 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)
|
||||||
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 {
|
||||||
|
// Send a connection established message even if no progress yet
|
||||||
|
const connectMsg = `data: ${JSON.stringify({ type: 'connected', sessionId })}\n\n`
|
||||||
|
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)
|
||||||
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}`)
|
||||||
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()
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ interface ProgressStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface AnalysisProgress {
|
interface AnalysisProgress {
|
||||||
|
sessionId: string
|
||||||
currentStep: number
|
currentStep: number
|
||||||
totalSteps: number
|
totalSteps: number
|
||||||
steps: ProgressStep[]
|
steps: ProgressStep[]
|
||||||
@@ -82,6 +83,8 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
|
|
||||||
// Real-time progress tracking
|
// Real-time progress tracking
|
||||||
const startProgressTracking = (sessionId: string) => {
|
const startProgressTracking = (sessionId: string) => {
|
||||||
|
console.log(`🔍 Starting progress tracking for session: ${sessionId}`)
|
||||||
|
|
||||||
// Close existing connection
|
// Close existing connection
|
||||||
if (eventSource) {
|
if (eventSource) {
|
||||||
eventSource.close()
|
eventSource.close()
|
||||||
@@ -89,13 +92,23 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
|
|
||||||
const es = new EventSource(`/api/progress/${sessionId}/stream`)
|
const es = new EventSource(`/api/progress/${sessionId}/stream`)
|
||||||
|
|
||||||
|
es.onopen = () => {
|
||||||
|
console.log(`🔍 EventSource connection opened for ${sessionId}`)
|
||||||
|
}
|
||||||
|
|
||||||
es.onmessage = (event) => {
|
es.onmessage = (event) => {
|
||||||
try {
|
try {
|
||||||
const progressData = JSON.parse(event.data)
|
const progressData = JSON.parse(event.data)
|
||||||
|
console.log(`🔍 Received progress update for ${sessionId}:`, progressData)
|
||||||
|
|
||||||
if (progressData.type === 'complete') {
|
if (progressData.type === 'complete') {
|
||||||
|
console.log(`🔍 Analysis complete for ${sessionId}`)
|
||||||
es.close()
|
es.close()
|
||||||
setEventSource(null)
|
setEventSource(null)
|
||||||
|
} else if (progressData.type === 'connected') {
|
||||||
|
console.log(`🔍 EventSource connected for ${sessionId}`)
|
||||||
} else {
|
} else {
|
||||||
|
// Update progress state immediately
|
||||||
setProgress(progressData)
|
setProgress(progressData)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -203,6 +216,11 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
try {
|
try {
|
||||||
if (analysisTimeframes.length === 1) {
|
if (analysisTimeframes.length === 1) {
|
||||||
// Single timeframe analysis with real-time progress
|
// Single timeframe analysis with real-time progress
|
||||||
|
|
||||||
|
// Pre-generate sessionId and start progress tracking BEFORE making the API call
|
||||||
|
const sessionId = `analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||||||
|
startProgressTracking(sessionId)
|
||||||
|
|
||||||
const response = await fetch('/api/enhanced-screenshot', {
|
const response = await fetch('/api/enhanced-screenshot', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@@ -210,7 +228,8 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
symbol: analysisSymbol,
|
symbol: analysisSymbol,
|
||||||
timeframe: analysisTimeframes[0],
|
timeframe: analysisTimeframes[0],
|
||||||
layouts: selectedLayouts,
|
layouts: selectedLayouts,
|
||||||
analyze: true
|
analyze: true,
|
||||||
|
sessionId: sessionId // Pass pre-generated sessionId
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -220,11 +239,6 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
throw new Error(data.error || 'Analysis failed')
|
throw new Error(data.error || 'Analysis failed')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start real-time progress tracking if sessionId is provided
|
|
||||||
if (data.sessionId) {
|
|
||||||
startProgressTracking(data.sessionId)
|
|
||||||
}
|
|
||||||
|
|
||||||
setResult(data)
|
setResult(data)
|
||||||
|
|
||||||
// Call the callback with analysis result if provided
|
// Call the callback with analysis result if provided
|
||||||
|
|||||||
@@ -36,7 +36,12 @@ class ProgressTracker extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.sessions.set(sessionId, progress)
|
this.sessions.set(sessionId, progress)
|
||||||
|
|
||||||
|
// Small delay to ensure EventSource connection is established before emitting
|
||||||
|
setTimeout(() => {
|
||||||
this.emit(`progress:${sessionId}`, progress)
|
this.emit(`progress:${sessionId}`, progress)
|
||||||
|
}, 100)
|
||||||
|
|
||||||
return progress
|
return progress
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +82,11 @@ class ProgressTracker extends EventEmitter {
|
|||||||
|
|
||||||
this.sessions.set(sessionId, updatedProgress)
|
this.sessions.set(sessionId, updatedProgress)
|
||||||
console.log(`🔍 Emitting progress event for ${sessionId}, currentStep: ${updatedProgress.currentStep}`)
|
console.log(`🔍 Emitting progress event for ${sessionId}, currentStep: ${updatedProgress.currentStep}`)
|
||||||
|
|
||||||
|
// Small delay to ensure proper event ordering and prevent race conditions
|
||||||
|
setTimeout(() => {
|
||||||
this.emit(`progress:${sessionId}`, updatedProgress)
|
this.emit(`progress:${sessionId}`, updatedProgress)
|
||||||
|
}, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTimeframeProgress(sessionId: string, current: number, total: number, currentTimeframe?: string): void {
|
updateTimeframeProgress(sessionId: string, current: number, total: number, currentTimeframe?: string): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user