1- import { useEffect , useRef } from 'react' ;
1+ import { useEffect , useRef , useCallback } from 'react' ;
2+ import { analysisApi } from '../api/analysis' ;
23import type { TaskInfo } from '../types/analysis' ;
34import { useTaskStream } from './useTaskStream' ;
45
@@ -23,13 +24,50 @@ export function useDashboardLifecycle({
2324} : UseDashboardLifecycleOptions ) : void {
2425 const removalTimeoutsRef = useRef < number [ ] > ( [ ] ) ;
2526
27+ // Sync active tasks from the API to reconcile stale store state.
28+ // This handles the case where tasks completed while the component was unmounted.
29+ const syncActiveTasksFromApi = useCallback ( async ( ) => {
30+ try {
31+ const response = await analysisApi . getTasks ( { limit : 50 } ) ;
32+ const serverTasks = response . tasks ?? [ ] ;
33+ const serverActiveIds = new Set < string > ( ) ;
34+
35+ for ( const task of serverTasks ) {
36+ if ( task . status === 'pending' || task . status === 'processing' ) {
37+ serverActiveIds . add ( task . taskId ) ;
38+ // Ensure task exists in store with latest state
39+ syncTaskCreated ( task ) ;
40+ syncTaskUpdated ( task ) ;
41+ } else if ( task . status === 'completed' ) {
42+ // Task completed while we were away - remove it from store
43+ removeTask ( task . taskId ) ;
44+ } else if ( task . status === 'failed' ) {
45+ removeTask ( task . taskId ) ;
46+ }
47+ }
48+
49+ // Remove tasks from store that are no longer in the server response
50+ // (they completed/failed while the component was unmounted)
51+ const { useStockPoolStore } = await import ( '../stores/stockPoolStore' ) ;
52+ const { activeTasks } = useStockPoolStore . getState ( ) ;
53+ for ( const storeTask of activeTasks ) {
54+ if ( ! serverActiveIds . has ( storeTask . taskId ) ) {
55+ removeTask ( storeTask . taskId ) ;
56+ }
57+ }
58+ } catch {
59+ // Silently ignore - SSE will eventually sync state
60+ }
61+ } , [ syncTaskCreated , syncTaskUpdated , removeTask ] ) ;
62+
2663 useEffect ( ( ) => {
2764 if ( ! enabled ) {
2865 return ;
2966 }
3067
3168 void loadInitialHistory ( ) ;
32- } , [ enabled , loadInitialHistory ] ) ;
69+ void syncActiveTasksFromApi ( ) ;
70+ } , [ enabled , loadInitialHistory , syncActiveTasksFromApi ] ) ;
3371
3472 useEffect ( ( ) => {
3573 if ( ! enabled ) {
0 commit comments