@@ -47,7 +47,9 @@ use aruna_operations::metadata::projector::{
4747use aruna_operations:: mutate_realm_placement:: {
4848 MutateRealmPlacementConfig , MutateRealmPlacementOperation , RealmPlacementMutation ,
4949} ;
50- use aruna_operations:: placement:: { PlacementResolutionContext , plan_target_placement} ;
50+ use aruna_operations:: placement:: {
51+ PlacementResolutionContext , plan_target_placement, resolve_shard_holders,
52+ } ;
5153use aruna_operations:: sync_placement:: sort_node_ids;
5254use aruna_operations:: task_incoming:: initialize_task_incoming;
5355use aruna_operations:: update_metadata_document:: {
@@ -122,8 +124,7 @@ async fn metadata_creation_replicates_to_all_three_holders()
122124}
123125
124126#[ tokio:: test]
125- async fn metadata_replan_refreshes_replacement_holder_indexes ( )
126- -> Result < ( ) , Box < dyn std:: error:: Error > > {
127+ async fn replan_reaches_replacement ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
127128 let realm_id = RealmId ( [ 46u8 ; 32 ] ) ;
128129 let ( nodes, _config) = build_realm_nodes ( & realm_id, 4 ) . await ?;
129130 let group_id = Ulid :: new ( ) ;
@@ -221,34 +222,29 @@ async fn metadata_replan_refreshes_replacement_holder_indexes()
221222 nodes[ 0 ] . context . as_ref ( ) ,
222223 )
223224 . await ?;
224- let mut final_holders = plan_target_placement ( & updated_config, & target, placement_context)
225- . expect ( "updated metadata lifecycle placement resolves" )
226- . holders ;
225+ let plan = plan_target_placement ( & updated_config, & target, placement_context)
226+ . expect ( "updated metadata lifecycle placement resolves" ) ;
227+ let placement = plan. placement ;
228+ let mut final_holders = plan. holders ;
227229 sort_node_ids ( & mut final_holders) ;
228230 let replacement = final_holders
229231 . iter ( )
230232 . copied ( )
231233 . find ( |node_id| !initial_holders. contains ( node_id) )
232234 . expect ( "replan selects a replacement holder" ) ;
233235
234- wait_for_persisted_holder_set (
235- & nodes,
236- & final_holders,
237- group_id,
238- document_id,
239- & final_holders,
240- )
241- . await ?;
236+ let live_holders = resolve_shard_holders ( & updated_config, & placement) ;
237+ assert ! ( live_holders. contains( & replacement) ) ;
238+ assert ! ( !live_holders. contains( & obsolete) ) ;
239+
242240 let replacement_node = nodes
243241 . iter ( )
244242 . find ( |node| node. net . node_id ( ) == replacement)
245243 . expect ( "replacement fixture node exists" ) ;
246- let ( registry, holders) = read_persisted_holder_set ( replacement_node, group_id, document_id)
247- . await ?
248- . expect ( "replacement persisted metadata indexes" ) ;
249- assert ! ( same_holder_set( & registry. holder_node_ids, & final_holders) ) ;
250- assert ! ( same_holder_set( & holders, & final_holders) ) ;
251- assert ! ( !holders. contains( & obsolete) ) ;
244+ // holder_node_ids is an event-time stamp; freshness is the shard guarantee (#395).
245+ let registry =
246+ wait_for_persisted_update ( replacement_node, group_id, document_id, latest_update_id)
247+ . await ?;
252248 assert_eq ! ( registry. last_event_id, latest_update_id) ;
253249 let refreshed_event =
254250 read_metadata_event_log_value ( replacement_node, document_id, latest_update_id)
@@ -868,6 +864,31 @@ async fn read_persisted_holder_set(
868864 }
869865}
870866
867+ async fn wait_for_persisted_update (
868+ node : & TestNode ,
869+ group_id : Ulid ,
870+ document_id : Ulid ,
871+ expected_event_id : Ulid ,
872+ ) -> Result < MetadataRegistryRecord , Box < dyn std:: error:: Error > > {
873+ let deadline = Instant :: now ( ) + CONVERGENCE_TIMEOUT ;
874+ loop {
875+ let last = match read_persisted_holder_set ( node, group_id, document_id) . await ? {
876+ Some ( ( registry, _) ) if registry. last_event_id == expected_event_id => {
877+ return Ok ( registry) ;
878+ }
879+ Some ( ( registry, _) ) => format ! ( "last_event_id={}" , registry. last_event_id) ,
880+ None => "missing" . to_string ( ) ,
881+ } ;
882+ if Instant :: now ( ) >= deadline {
883+ return Err ( format ! (
884+ "replacement did not converge to update {expected_event_id}: {last}"
885+ )
886+ . into ( ) ) ;
887+ }
888+ sleep ( Duration :: from_millis ( 50 ) ) . await ;
889+ }
890+ }
891+
871892async fn wait_for_persisted_holder_set (
872893 nodes : & [ TestNode ] ,
873894 node_ids : & [ aruna_core:: NodeId ] ,
0 commit comments