@@ -50,12 +50,14 @@ use futures::future::Either;
5050use futures:: Future ;
5151use futures:: StreamExt ;
5252use log:: error;
53+ use log:: info;
5354use log:: warn;
5455use parking_lot:: RwLock ;
5556use rand:: thread_rng;
5657use rand:: Rng ;
5758use serde:: Deserialize ;
5859use serde:: Serialize ;
60+ use tokio:: time:: sleep;
5961
6062use crate :: servers:: flight:: FlightClient ;
6163
@@ -81,11 +83,11 @@ pub trait ClusterHelper {
8183
8284 fn get_nodes ( & self ) -> Vec < Arc < NodeInfo > > ;
8385
84- async fn do_action < T : Serialize + Send , Res : for < ' de > Deserialize < ' de > + Send > (
86+ async fn do_action < T : Serialize + Send + Clone , Res : for < ' de > Deserialize < ' de > + Send > (
8587 & self ,
8688 path : & str ,
8789 message : HashMap < String , T > ,
88- timeout : u64 ,
90+ flight_params : FlightParams ,
8991 ) -> Result < HashMap < String , Res > > ;
9092}
9193
@@ -118,11 +120,11 @@ impl ClusterHelper for Cluster {
118120 self . nodes . to_vec ( )
119121 }
120122
121- async fn do_action < T : Serialize + Send , Res : for < ' de > Deserialize < ' de > + Send > (
123+ async fn do_action < T : Serialize + Send + Clone , Res : for < ' de > Deserialize < ' de > + Send > (
122124 & self ,
123125 path : & str ,
124126 message : HashMap < String , T > ,
125- timeout : u64 ,
127+ flight_params : FlightParams ,
126128 ) -> Result < HashMap < String , Res > > {
127129 fn get_node < ' a > ( nodes : & ' a [ Arc < NodeInfo > ] , id : & str ) -> Result < & ' a Arc < NodeInfo > > {
128130 for node in nodes {
@@ -137,23 +139,47 @@ impl ClusterHelper for Cluster {
137139 ) ) )
138140 }
139141
140- let mut response = HashMap :: with_capacity ( message. len ( ) ) ;
142+ let mut futures = Vec :: with_capacity ( message. len ( ) ) ;
141143 for ( id, message) in message {
142144 let node = get_node ( & self . nodes , & id) ?;
143145
144- let config = GlobalConfig :: instance ( ) ;
145- let flight_address = node. flight_address . clone ( ) ;
146- let node_secret = node. secret . clone ( ) ;
147-
148- let mut conn = create_client ( & config, & flight_address) . await ?;
149- response. insert (
150- id,
151- conn. do_action :: < _ , Res > ( path, node_secret, message, timeout)
152- . await ?,
153- ) ;
146+ futures. push ( {
147+ let config = GlobalConfig :: instance ( ) ;
148+ let flight_address = node. flight_address . clone ( ) ;
149+ let node_secret = node. secret . clone ( ) ;
150+
151+ async move {
152+ let mut attempt = 0 ;
153+
154+ loop {
155+ let mut conn = create_client ( & config, & flight_address) . await ?;
156+ match conn
157+ . do_action :: < _ , Res > (
158+ path,
159+ node_secret. clone ( ) ,
160+ message. clone ( ) ,
161+ flight_params. timeout ,
162+ )
163+ . await
164+ {
165+ Ok ( result) => return Ok ( ( id, result) ) ,
166+ Err ( e)
167+ if e. code ( ) == ErrorCode :: CANNOT_CONNECT_NODE
168+ && attempt < flight_params. retry_times =>
169+ {
170+ // only retry when error is network problem
171+ info ! ( "retry do_action, attempt: {}" , attempt) ;
172+ attempt += 1 ;
173+ sleep ( Duration :: from_secs ( flight_params. retry_interval ) ) . await ;
174+ }
175+ Err ( e) => return Err ( e) ,
176+ }
177+ }
178+ }
179+ } ) ;
154180 }
155-
156- Ok ( response )
181+ let responses : Vec < ( String , Res ) > = futures :: future :: try_join_all ( futures ) . await ? ;
182+ Ok ( responses . into_iter ( ) . collect :: < HashMap < String , Res > > ( ) )
157183 }
158184}
159185
@@ -537,3 +563,10 @@ pub async fn create_client(config: &InnerConfig, address: &str) -> Result<Flight
537563 ConnectionFactory :: create_rpc_channel ( address. to_owned ( ) , timeout, rpc_tls_config) . await ?,
538564 ) ) )
539565}
566+
567+ #[ derive( Clone , Copy , Debug ) ]
568+ pub struct FlightParams {
569+ pub ( crate ) timeout : u64 ,
570+ pub ( crate ) retry_times : u64 ,
571+ pub ( crate ) retry_interval : u64 ,
572+ }
0 commit comments