@@ -35,20 +35,20 @@ export async function checkRunningAnalyses({
3535 // Check database for running analyses if user is authenticated
3636 if ( user ) {
3737 try {
38- // Only fetch analyses from the last 24 hours (for checking running analyses)
39- const twentyFourHoursAgo = new Date ( ) ;
40- twentyFourHoursAgo . setHours ( twentyFourHoursAgo . getHours ( ) - 24 ) ;
38+ // Fetch ALL analyses from today in a single query
39+ const today = new Date ( ) ;
40+ today . setHours ( 0 , 0 , 0 , 0 ) ;
4141
42- const { data, error } = await supabase
42+ const { data : todayAnalyses , error } = await supabase
4343 . from ( 'analysis_history' )
44- . select ( 'ticker, analysis_status, full_analysis, created_at, id, decision, agent_insights, rebalance_request_id, is_canceled ' )
44+ . select ( '* ' )
4545 . eq ( 'user_id' , user . id )
46- . gte ( 'created_at' , twentyFourHoursAgo . toISOString ( ) ) // Only last 24 hours
46+ . gte ( 'created_at' , today . toISOString ( ) ) // All of today's analyses
4747 . order ( 'created_at' , { ascending : false } ) ;
4848
49- if ( ! error && data ) {
50- // Filter to only actually running analyses using centralized logic
51- const runningData = data . filter ( item => {
49+ if ( ! error && todayAnalyses ) {
50+ // Filter for running analyses in memory (no additional query)
51+ const runningData = todayAnalyses . filter ( item => {
5252 // Convert legacy numeric status if needed
5353 const currentStatus = typeof item . analysis_status === 'number'
5454 ? convertLegacyAnalysisStatus ( item . analysis_status )
@@ -64,13 +64,25 @@ export async function checkRunningAnalyses({
6464 return isRunning ;
6565 } ) ;
6666
67+ // Filter for completed analyses in memory (no additional query)
68+ const completedData = todayAnalyses . filter ( item => {
69+ const currentStatus = typeof item . analysis_status === 'number'
70+ ? convertLegacyAnalysisStatus ( item . analysis_status )
71+ : item . analysis_status ;
72+
73+ return ! item . is_canceled &&
74+ currentStatus !== ANALYSIS_STATUS . CANCELLED &&
75+ ! isAnalysisActive ( currentStatus ) ;
76+ } ) ;
77+
6778 // Only log if there are actually running analyses
6879 if ( runningData . length > 0 ) {
6980 console . log ( 'Running analyses from DB:' , runningData . map ( d => ( {
7081 ticker : d . ticker ,
7182 status : d . analysis_status
7283 } ) ) ) ;
7384 }
85+
7486 for ( const item of runningData ) {
7587 running . add ( item . ticker ) ;
7688 }
@@ -80,9 +92,7 @@ export async function checkRunningAnalyses({
8092
8193 // Use the most recent running analysis for display
8294 if ( runningData . length > 0 ) {
83- const mostRecent = runningData . sort ( ( a , b ) =>
84- new Date ( b . created_at ) . getTime ( ) - new Date ( a . created_at ) . getTime ( )
85- ) [ 0 ] ;
95+ const mostRecent = runningData [ 0 ] ; // Already sorted by created_at desc
8696 console . log ( 'Most recent running analysis:' , {
8797 ticker : mostRecent . ticker ,
8898 rebalance_request_id : mostRecent . rebalance_request_id ,
@@ -92,77 +102,44 @@ export async function checkRunningAnalyses({
92102 setActiveAnalysisTicker ( mostRecent . ticker ) ;
93103 const stillRunning = updateWorkflowFromAnalysis ( mostRecent ) ;
94104 setIsAnalyzing ( stillRunning ) ;
105+ } else if ( completedData . length > 0 && ! activeAnalysisTicker ) {
106+ // No running analyses, show most recent completed one
107+ const mostRecentCompleted = completedData [ 0 ] ;
108+ setCurrentAnalysis ( mostRecentCompleted ) ;
109+ setActiveAnalysisTicker ( mostRecentCompleted . ticker ) ;
110+ const stillRunning = updateWorkflowFromAnalysis ( mostRecentCompleted ) ;
111+ setIsAnalyzing ( stillRunning ) ;
95112 }
96- }
97- } catch ( error ) {
98- console . error ( 'Error checking running analyses:' , error ) ;
99- }
100- }
101113
102- // Check if any analyses just completed (were running before but not now)
103- const justCompleted = Array . from ( previousRunningRef . current ) . filter ( ticker => ! running . has ( ticker ) ) ;
104- if ( justCompleted . length > 0 ) {
105- console . log ( 'Analyses completed, reloading for:' , justCompleted ) ;
106-
107- // Fetch the completed analysis data (should be recent)
108- try {
109- // Only look for analyses completed in the last hour
110- const oneHourAgo = new Date ( ) ;
111- oneHourAgo . setHours ( oneHourAgo . getHours ( ) - 1 ) ;
112-
113- const { data, error } = await supabase
114- . from ( 'analysis_history' )
115- . select ( '*' )
116- . eq ( 'user_id' , user ! . id )
117- . eq ( 'is_canceled' , false )
118- . in ( 'ticker' , justCompleted )
119- . neq ( 'analysis_status' , ANALYSIS_STATUS . CANCELLED )
120- . gte ( 'created_at' , oneHourAgo . toISOString ( ) ) // Only recent completions
121- . order ( 'created_at' , { ascending : false } )
122- . limit ( 1 )
123- . maybeSingle ( ) ;
124-
125- if ( ! error && data ) {
126- setCurrentAnalysis ( data ) ;
127- setActiveAnalysisTicker ( data . ticker ) ;
128- const stillRunning = updateWorkflowFromAnalysis ( data ) ;
129- setIsAnalyzing ( stillRunning ) ;
114+ // Check if any analyses just completed (were running before but not now)
115+ const justCompleted = Array . from ( previousRunningRef . current ) . filter ( ticker => ! running . has ( ticker ) ) ;
116+ if ( justCompleted . length > 0 ) {
117+ console . log ( 'Analyses completed, reloading for:' , justCompleted ) ;
118+
119+ // Find the completed analysis from our already-fetched data (no additional query!)
120+ const completedAnalysis = completedData . find ( item => justCompleted . includes ( item . ticker ) ) ;
121+
122+ if ( completedAnalysis ) {
123+ setCurrentAnalysis ( completedAnalysis ) ;
124+ setActiveAnalysisTicker ( completedAnalysis . ticker ) ;
125+ const stillRunning = updateWorkflowFromAnalysis ( completedAnalysis ) ;
126+ setIsAnalyzing ( stillRunning ) ;
127+ }
128+ }
130129 }
131130 } catch ( error ) {
132- console . error ( 'Error fetching completed analysis :' , error ) ;
131+ console . error ( 'Error checking running analyses :' , error ) ;
133132 }
133+ } else {
134+ // User not authenticated
135+ setRunningAnalysesCount ( 0 ) ;
136+ setIsAnalyzing ( false ) ;
134137 }
135138
136139 // If no running analyses and we were analyzing, keep showing the last one
137140 if ( running . size === 0 && previousRunningRef . current . size > 0 ) {
138141 setIsAnalyzing ( false ) ;
139142 // Keep the current analysis display, don't reset
140- } else if ( running . size === 0 && ! activeAnalysisTicker && user ) {
141- // No analyses at all - check for recent completed ones
142- try {
143- const thirtyMinutesAgo = new Date ( ) ;
144- thirtyMinutesAgo . setMinutes ( thirtyMinutesAgo . getMinutes ( ) - 30 ) ;
145-
146- const { data, error } = await supabase
147- . from ( 'analysis_history' )
148- . select ( '*' )
149- . eq ( 'user_id' , user . id )
150- . eq ( 'is_canceled' , false )
151- . neq ( 'analysis_status' , ANALYSIS_STATUS . CANCELLED )
152- . gte ( 'created_at' , thirtyMinutesAgo . toISOString ( ) )
153- . order ( 'created_at' , { ascending : false } )
154- . limit ( 1 )
155- . maybeSingle ( ) ;
156-
157- if ( ! error && data ) {
158- setCurrentAnalysis ( data ) ;
159- setActiveAnalysisTicker ( data . ticker ) ;
160- const stillRunning = updateWorkflowFromAnalysis ( data ) ;
161- setIsAnalyzing ( stillRunning ) ;
162- }
163- } catch ( error ) {
164- console . error ( 'Error fetching recent analysis:' , error ) ;
165- }
166143 }
167144
168145 // Only log if there are running analyses or if status changed
0 commit comments