@@ -726,8 +726,9 @@ async fn production_control_plane_to_data_plane_otlp_to_promql() {
726726 . await
727727 . unwrap ( ) ;
728728 assert_eq ! ( first_scalar( & still_warm) , Some ( value) ) ;
729- // Retry the staged successor while queries are in flight. Each
730- // request must retain a complete active snapshot through cutover.
729+ // Retry while queries are in flight. Old-generation reads may finish,
730+ // but the successor must stay cold until its own output is published.
731+ // Reusing the old payload would violate StoredOutputReference identity.
731732 request[ "activation_unix_ms" ] = ( std:: time:: SystemTime :: now ( )
732733 . duration_since ( std:: time:: UNIX_EPOCH )
733734 . unwrap ( )
@@ -750,11 +751,12 @@ async fn production_control_plane_to_data_plane_otlp_to_promql() {
750751 . json ( )
751752 . await
752753 . unwrap ( ) ;
753- assert_eq ! (
754- first_scalar( & response) ,
755- Some ( value) ,
756- "torn serving snapshot: {response}"
757- ) ;
754+ if let Some ( actual) = first_scalar ( & response) {
755+ assert_eq ! ( actual, value, "incorrect old-generation result: {response}" ) ;
756+ } else {
757+ assert_eq ! ( response[ "status" ] , "error" , "{response}" ) ;
758+ assert_eq ! ( response[ "error" ] , "No result for query" , "{response}" ) ;
759+ }
758760 tokio:: time:: sleep ( Duration :: from_millis ( 10 ) ) . await ;
759761 }
760762 } ) ;
@@ -777,6 +779,27 @@ async fn production_control_plane_to_data_plane_otlp_to_promql() {
777779 assert_eq ! ( activated[ "plan_version" ] , 2 ) ;
778780 let ( successor, _collector_socket) = collector. await . unwrap ( ) ;
779781 readers. await . unwrap ( ) ;
782+ let cold_successor: serde_json:: Value = client
783+ . get ( format ! ( "{data_base}/api/v1/query" ) )
784+ . query ( & [
785+ ( "query" , query. to_string ( ) ) ,
786+ ( "time" , ( window_end_ms as f64 / 1000.0 ) . to_string ( ) ) ,
787+ ] )
788+ . send ( )
789+ . await
790+ . unwrap ( )
791+ . json ( )
792+ . await
793+ . unwrap ( ) ;
794+ assert_eq ! ( cold_successor[ "status" ] , "error" , "{cold_successor}" ) ;
795+ assert_eq ! (
796+ cold_successor[ "error" ] , "No result for query" ,
797+ "{cold_successor}"
798+ ) ;
799+ assert ! (
800+ first_scalar( & cold_successor) . is_none( ) ,
801+ "successor reused old state"
802+ ) ;
780803 let old_frame = client
781804 . post ( format ! ( "http://{otlp_http}/v1/metrics" ) )
782805 . header ( "content-type" , "application/x-protobuf" )
0 commit comments