@@ -108,8 +108,10 @@ enum Frame<M> {
108108#[ derive( Debug , Serialize , Deserialize , EnumAsInner ) ]
109109enum NetRxResponse {
110110 Ack ( u64 ) ,
111- /// This channel is closed with the given reason. NetTx should stop reconnecting.
111+ /// This session is rejected with the given reason. NetTx should stop reconnecting.
112112 Reject ( String ) ,
113+ /// This channel is closed.
114+ Closed ,
113115}
114116
115117fn serialize_response ( response : NetRxResponse ) -> Result < Bytes , bincode:: Error > {
@@ -1625,6 +1627,9 @@ mod tests {
16251627 handle. await . unwrap ( ) . unwrap ( ) ;
16261628 // mpsc is closed too and there should be no unread message left.
16271629 assert ! ( rx. recv( ) . await . is_none( ) ) ;
1630+ // should send NetRxResponse::Closed before stopping server.
1631+ let bytes = reader. next ( ) . await . unwrap ( ) . unwrap ( ) ;
1632+ assert ! ( deserialize_response( bytes) . unwrap( ) . is_closed( ) ) ;
16281633 // No more acks from server.
16291634 assert ! ( reader. next( ) . await . unwrap( ) . is_none( ) ) ;
16301635 } ;
@@ -1659,6 +1664,9 @@ mod tests {
16591664 handle. await . unwrap ( ) . unwrap ( ) ;
16601665 // mpsc is closed too and there should be no unread message left.
16611666 assert ! ( rx. recv( ) . await . is_none( ) ) ;
1667+ // should send NetRxResponse::Closed before stopping server.
1668+ let bytes = reader. next ( ) . await . unwrap ( ) . unwrap ( ) ;
1669+ assert ! ( deserialize_response( bytes) . unwrap( ) . is_closed( ) ) ;
16621670 // No more acks from server.
16631671 assert ! ( reader. next( ) . await . unwrap( ) . is_none( ) ) ;
16641672 }
@@ -2398,4 +2406,41 @@ mod tests {
23982406 let bytes = reader. next ( ) . await . unwrap ( ) . unwrap ( ) ;
23992407 assert ! ( deserialize_response( bytes) . unwrap( ) . is_reject( ) ) ;
24002408 }
2409+
2410+ #[ async_timed_test( timeout_secs = 60 ) ]
2411+ // TODO: OSS: called `Result::unwrap()` on an `Err` value: Listen(Tcp([::1]:0), Os { code: 99, kind: AddrNotAvailable, message: "Cannot assign requested address" })
2412+ #[ cfg_attr( not( fbcode_build) , ignore) ]
2413+ async fn test_stop_net_tx_after_stopping_net_rx ( ) {
2414+ hyperactor_telemetry:: initialize_logging_for_test ( ) ;
2415+
2416+ let config = config:: global:: lock ( ) ;
2417+ let _guard =
2418+ config. override_key ( config:: MESSAGE_DELIVERY_TIMEOUT , Duration :: from_secs ( 300 ) ) ;
2419+ let ( addr, mut rx) = tcp:: serve :: < u64 > ( "[::1]:0" . parse ( ) . unwrap ( ) ) . unwrap ( ) ;
2420+ let socket_addr = match addr {
2421+ ChannelAddr :: Tcp ( a) => a,
2422+ _ => panic ! ( "unexpected channel type" ) ,
2423+ } ;
2424+ let tx = tcp:: dial :: < u64 > ( socket_addr) ;
2425+ // NetTx will not establish a connection until it sends the 1st message.
2426+ // Without a live connection, NetTx cannot received the Closed message
2427+ // from NetRx. Therefore, we need to send a message to establish the
2428+ //connection.
2429+ tx. send ( 100 ) . await . unwrap ( ) ;
2430+ assert_eq ! ( rx. recv( ) . await . unwrap( ) , 100 ) ;
2431+ // Drop rx will close the NetRx server.
2432+ rx. 2 . stop ( "testing" ) ;
2433+ assert ! ( rx. recv( ) . await . is_err( ) ) ;
2434+
2435+ // NetTx will only read from the stream when it needs to send a message
2436+ // or wait for an ack. Therefore we need to send a message to trigger that.
2437+ tx. post ( 101 ) ;
2438+ let mut watcher = tx. status ( ) . clone ( ) ;
2439+ // When NetRx exits, it should notify NetTx to exit as well.
2440+ let _ = watcher. wait_for ( |val| * val == TxStatus :: Closed ) . await ;
2441+ // wait_for could return Err due to race between when watch's sender was
2442+ // dropped and when wait_for was called. So we still need to do an
2443+ // equality check.
2444+ assert_eq ! ( * watcher. borrow( ) , TxStatus :: Closed ) ;
2445+ }
24012446}
0 commit comments