@@ -106,8 +106,10 @@ enum Frame<M> {
106106#[ derive( Debug , Serialize , Deserialize , EnumAsInner ) ]
107107enum NetRxResponse {
108108 Ack ( u64 ) ,
109- /// This channel is closed with the given reason. NetTx should stop reconnecting.
109+ /// This session is rejected with the given reason. NetTx should stop reconnecting.
110110 Reject ( String ) ,
111+ /// This channel is closed.
112+ Closed ,
111113}
112114
113115fn serialize_response ( response : NetRxResponse ) -> Result < Bytes , bincode:: Error > {
@@ -1612,6 +1614,9 @@ mod tests {
16121614 handle. await . unwrap ( ) . unwrap ( ) ;
16131615 // mpsc is closed too and there should be no unread message left.
16141616 assert ! ( rx. recv( ) . await . is_none( ) ) ;
1617+ // should send NetRxResponse::Closed before stopping server.
1618+ let bytes = reader. next ( ) . await . unwrap ( ) . unwrap ( ) ;
1619+ assert ! ( deserialize_response( bytes) . unwrap( ) . is_closed( ) ) ;
16151620 // No more acks from server.
16161621 assert ! ( reader. next( ) . await . unwrap( ) . is_none( ) ) ;
16171622 } ;
@@ -1646,6 +1651,9 @@ mod tests {
16461651 handle. await . unwrap ( ) . unwrap ( ) ;
16471652 // mpsc is closed too and there should be no unread message left.
16481653 assert ! ( rx. recv( ) . await . is_none( ) ) ;
1654+ // should send NetRxResponse::Closed before stopping server.
1655+ let bytes = reader. next ( ) . await . unwrap ( ) . unwrap ( ) ;
1656+ assert ! ( deserialize_response( bytes) . unwrap( ) . is_closed( ) ) ;
16491657 // No more acks from server.
16501658 assert ! ( reader. next( ) . await . unwrap( ) . is_none( ) ) ;
16511659 }
@@ -2385,4 +2393,41 @@ mod tests {
23852393 let bytes = reader. next ( ) . await . unwrap ( ) . unwrap ( ) ;
23862394 assert ! ( deserialize_response( bytes) . unwrap( ) . is_reject( ) ) ;
23872395 }
2396+
2397+ #[ async_timed_test( timeout_secs = 60 ) ]
2398+ // TODO: OSS: called `Result::unwrap()` on an `Err` value: Listen(Tcp([::1]:0), Os { code: 99, kind: AddrNotAvailable, message: "Cannot assign requested address" })
2399+ #[ cfg_attr( not( fbcode_build) , ignore) ]
2400+ async fn test_stop_net_tx_after_stopping_net_rx ( ) {
2401+ hyperactor_telemetry:: initialize_logging_for_test ( ) ;
2402+
2403+ let config = config:: global:: lock ( ) ;
2404+ let _guard =
2405+ config. override_key ( config:: MESSAGE_DELIVERY_TIMEOUT , Duration :: from_secs ( 300 ) ) ;
2406+ let ( addr, mut rx) = tcp:: serve :: < u64 > ( "[::1]:0" . parse ( ) . unwrap ( ) ) . unwrap ( ) ;
2407+ let socket_addr = match addr {
2408+ ChannelAddr :: Tcp ( a) => a,
2409+ _ => panic ! ( "unexpected channel type" ) ,
2410+ } ;
2411+ let tx = tcp:: dial :: < u64 > ( socket_addr) ;
2412+ // NetTx will not establish a connection until it sends the 1st message.
2413+ // Without a live connection, NetTx cannot received the Closed message
2414+ // from NetRx. Therefore, we need to send a message to establish the
2415+ //connection.
2416+ tx. send ( 100 ) . await . unwrap ( ) ;
2417+ assert_eq ! ( rx. recv( ) . await . unwrap( ) , 100 ) ;
2418+ // Drop rx will close the NetRx server.
2419+ rx. 2 . stop ( "testing" ) ;
2420+ assert ! ( rx. recv( ) . await . is_err( ) ) ;
2421+
2422+ // NetTx will only read from the stream when it needs to send a message
2423+ // or wait for an ack. Therefore we need to send a message to trigger that.
2424+ tx. post ( 101 ) ;
2425+ let mut watcher = tx. status ( ) . clone ( ) ;
2426+ // When NetRx exits, it should notify NetTx to exit as well.
2427+ let _ = watcher. wait_for ( |val| * val == TxStatus :: Closed ) . await ;
2428+ // wait_for could return Err due to race between when watch's sender was
2429+ // dropped and when wait_for was called. So we still need to do an
2430+ // equality check.
2431+ assert_eq ! ( * watcher. borrow( ) , TxStatus :: Closed ) ;
2432+ }
23882433}
0 commit comments