@@ -9,6 +9,7 @@ use shared::models::{
99 api:: ApiResponse ,
1010 heartbeat:: { HeartbeatRequest , HeartbeatResponse } ,
1111} ;
12+ use std:: collections:: HashSet ;
1213use std:: str:: FromStr ;
1314
1415async fn heartbeat (
@@ -42,6 +43,40 @@ async fn heartbeat(
4243
4344 app_state. store_context . heartbeat_store . beat ( & heartbeat) ;
4445 if let Some ( metrics) = heartbeat. metrics . clone ( ) {
46+ // Get all previously reported metrics for this node
47+ let previous_metrics = app_state
48+ . store_context
49+ . metrics_store
50+ . get_metrics_for_node ( node_address) ;
51+
52+ // Create a HashSet of new metrics for efficient lookup
53+ let new_metrics_set: HashSet < _ > = metrics
54+ . iter ( )
55+ . map ( |metric| ( & metric. key . task_id , & metric. key . label ) )
56+ . collect ( ) ;
57+
58+ // Clean up stale metrics
59+ for ( task_id, task_metrics) in previous_metrics {
60+ for ( label, _value) in task_metrics {
61+ let prev_key = ( & task_id, & label) ;
62+ if !new_metrics_set. contains ( & prev_key) {
63+ // Remove from Prometheus metrics
64+ app_state. metrics . remove_compute_task_gauge (
65+ & node_address. to_string ( ) ,
66+ & task_id,
67+ & label,
68+ ) ;
69+ // Remove from Redis metrics store
70+ app_state. store_context . metrics_store . delete_metric (
71+ & task_id,
72+ & label,
73+ & node_address. to_string ( ) ,
74+ ) ;
75+ }
76+ }
77+ }
78+
79+ // Store new metrics and update Prometheus
4580 app_state
4681 . store_context
4782 . metrics_store
@@ -82,6 +117,8 @@ pub fn heartbeat_routes() -> Scope {
82117
83118#[ cfg( test) ]
84119mod tests {
120+ use std:: collections:: HashMap ;
121+
85122 use super :: * ;
86123 use crate :: api:: tests:: helper:: create_test_app_state;
87124
@@ -158,6 +195,59 @@ mod tests {
158195 let metrics = app_state. metrics . export_metrics ( ) . unwrap ( ) ;
159196 assert ! ( metrics. contains( "performance/batch_avg_seq_length" ) ) ;
160197 assert ! ( metrics. contains( "performance/batch_min_seq_length" ) ) ;
198+ assert ! ( metrics. contains( "long-task-1234" ) ) ;
199+
200+ let heartbeat_two = json ! ( { "address" : address, "metrics" : [
201+ { "key" : { "task_id" : "long-task-1235" , "label" : "performance/batch_len" } , "value" : 10.0 } ,
202+ { "key" : { "task_id" : "long-task-1235" , "label" : "performance/batch_min_len" } , "value" : 50.0 }
203+ ] } ) ;
204+
205+ let req = test:: TestRequest :: post ( )
206+ . uri ( "/heartbeat" )
207+ . set_json ( & heartbeat_two)
208+ . to_request ( ) ;
209+
210+ let resp = test:: call_service ( & app, req) . await ;
211+ assert_eq ! ( resp. status( ) , StatusCode :: OK ) ;
212+
213+ let metrics = app_state. metrics . export_metrics ( ) . unwrap ( ) ;
214+ assert ! ( metrics. contains( "long-task-1235" ) ) ;
215+ assert ! ( metrics. contains( "performance/batch_len" ) ) ;
216+ assert ! ( metrics. contains( "performance/batch_min_len" ) ) ;
217+ assert ! ( !metrics. contains( "long-task-1234" ) ) ;
218+ let aggregated_metrics = app_state
219+ . store_context
220+ . metrics_store
221+ . get_aggregate_metrics_for_all_tasks ( ) ;
222+ assert_eq ! ( aggregated_metrics. len( ) , 2 ) ;
223+ assert_eq ! ( aggregated_metrics. get( "performance/batch_len" ) , Some ( & 10.0 ) ) ;
224+ assert_eq ! (
225+ aggregated_metrics. get( "performance/batch_min_len" ) ,
226+ Some ( & 50.0 )
227+ ) ;
228+ assert_eq ! (
229+ aggregated_metrics. get( "performance/batch_avg_seq_length" ) ,
230+ None
231+ ) ;
232+
233+ let heartbeat_three = json ! ( { "address" : address, "metrics" : [
234+ ] } ) ;
235+
236+ let req = test:: TestRequest :: post ( )
237+ . uri ( "/heartbeat" )
238+ . set_json ( & heartbeat_three)
239+ . to_request ( ) ;
240+
241+ let resp = test:: call_service ( & app, req) . await ;
242+ assert_eq ! ( resp. status( ) , StatusCode :: OK ) ;
243+
244+ let metrics = app_state. metrics . export_metrics ( ) . unwrap ( ) ;
245+ let aggregated_metrics = app_state
246+ . store_context
247+ . metrics_store
248+ . get_aggregate_metrics_for_all_tasks ( ) ;
249+ assert_eq ! ( aggregated_metrics, HashMap :: new( ) ) ;
250+ assert_eq ! ( metrics, "" ) ;
161251 }
162252
163253 #[ actix_web:: test]
0 commit comments