Files
trading_bot_v3/lib/progress-tracker.ts
mindesbunister 0399103f8a 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.
2025-07-17 12:10:47 +02:00

125 lines
3.5 KiB
TypeScript

import { EventEmitter } from 'events'
export type ProgressStatus = 'pending' | 'active' | 'completed' | 'error'
export interface ProgressStep {
id: string
title: string
description: string
status: ProgressStatus
startTime?: number
endTime?: number
details?: string
}
export interface AnalysisProgress {
sessionId: string
currentStep: number
totalSteps: number
steps: ProgressStep[]
timeframeProgress?: {
current: number
total: number
currentTimeframe?: string
}
}
class ProgressTracker extends EventEmitter {
private sessions: Map<string, AnalysisProgress> = new Map()
createSession(sessionId: string, steps: ProgressStep[]): AnalysisProgress {
const progress: AnalysisProgress = {
sessionId,
currentStep: 0,
totalSteps: steps.length,
steps: steps.map(step => ({ ...step, status: 'pending' }))
}
this.sessions.set(sessionId, progress)
// Small delay to ensure EventSource connection is established before emitting
setTimeout(() => {
this.emit(`progress:${sessionId}`, progress)
}, 100)
return progress
}
updateStep(sessionId: string, stepId: string, status: ProgressStatus, details?: string): void {
console.log(`🔍 Progress Update: ${sessionId} -> ${stepId} -> ${status}${details ? ` (${details})` : ''}`)
const progress = this.sessions.get(sessionId)
if (!progress) {
console.log(`🔍 Warning: No session found for ${sessionId}`)
return
}
const updatedSteps = progress.steps.map(step => {
if (step.id === stepId) {
const updatedStep = {
...step,
status,
details: details || step.details
}
if (status === 'active' && !step.startTime) {
updatedStep.startTime = Date.now()
} else if ((status === 'completed' || status === 'error') && !step.endTime) {
updatedStep.endTime = Date.now()
}
return updatedStep
}
return step
})
const currentStepIndex = updatedSteps.findIndex(step => step.status === 'active')
const updatedProgress: AnalysisProgress = {
...progress,
steps: updatedSteps,
currentStep: currentStepIndex >= 0 ? currentStepIndex + 1 : progress.currentStep
}
this.sessions.set(sessionId, updatedProgress)
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)
}, 50)
}
updateTimeframeProgress(sessionId: string, current: number, total: number, currentTimeframe?: string): void {
const progress = this.sessions.get(sessionId)
if (!progress) return
const updatedProgress: AnalysisProgress = {
...progress,
timeframeProgress: {
current,
total,
currentTimeframe
}
}
this.sessions.set(sessionId, updatedProgress)
this.emit(`progress:${sessionId}`, updatedProgress)
}
getProgress(sessionId: string): AnalysisProgress | undefined {
return this.sessions.get(sessionId)
}
deleteSession(sessionId: string): void {
this.sessions.delete(sessionId)
this.emit(`progress:${sessionId}:complete`)
}
// Get all active sessions (for debugging)
getActiveSessions(): string[] {
return Array.from(this.sessions.keys())
}
}
export const progressTracker = new ProgressTracker()