11pub mod task;
22use captains_log:: filter:: LogFilter ;
33use crossfire:: oneshot:: oneshot;
4- use crossfire:: * ;
54use orb:: AsyncRuntime ;
65pub use razor_rpc_macros:: { endpoint_async, endpoint_client} ;
76pub use razor_stream:: client:: ClientCaller ;
87pub use task:: * ;
98
109use crate :: Codec ;
11- use crate :: error:: { EncodedErr , RpcErrCodec , RpcError , RpcIntErr } ;
10+ use crate :: error:: { RpcErrCodec , RpcError , RpcIntErr } ;
1211pub use razor_stream:: client:: {
1312 ClientCallerBlocking , ClientConfig , ClientFacts , ClientTransport , ConnPool , FailoverPool ,
1413} ;
8887 async move {
8988 let ( tx, rx) = oneshot :: < APIClientReq > ( ) ;
9089 let codec = <Self as ClientCaller >:: get_codec ( self ) ;
91- self . send_req ( make_req ( & codec, service_method, req, tx) ) . await ;
92- process_res ( & codec, rx. recv_async ( ) . await )
90+ let mut task = APIClientReq :: new ( & codec, service_method, req) ;
91+ task. set_noti ( tx) ;
92+ self . send_req ( task) . await ;
93+ if let Ok ( mut task) = rx. recv_async ( ) . await {
94+ return task. process_res ( & codec) ;
95+ } else {
96+ return Err ( RpcIntErr :: Internal . into ( ) ) ;
97+ }
9398 }
9499 }
95100}
@@ -111,141 +116,59 @@ where
111116 let codec = <Self as ClientCaller >:: get_codec ( self ) ;
112117 let mut retry_count = 0 ;
113118 let max_retries = self . get_retry_limit ( ) ;
114- let mut last_index: usize = 0 ;
115-
119+ let mut task = APIClientReq :: new ( & codec, service_method, req) ;
120+ let ( tx, mut rx) = oneshot :: < APIClientReq > ( ) ;
121+ task. set_noti ( tx) ;
122+ self . send_req ( task) . await ;
116123 loop {
117- let ( tx, rx) = oneshot :: < APIClientReq > ( ) ;
118- let mut api_req = make_req ( & codec, service_method, req, tx) ;
119- // Set routing info for retry
120- if retry_count > 0 {
121- api_req. routing_info = Some ( task:: RoutingInfo { cluster_ver : 0 , last_index } ) ;
122- }
123- self . send_req ( api_req) . await ;
124- let result = process_res :: < _ , Resp , E > ( & codec, rx. recv_async ( ) . await ) ;
125-
126- match result {
127- Ok ( resp) => return Ok ( resp) ,
128- Err ( RpcError :: User ( e) ) => {
129- match e. should_failover ( ) {
130- Ok ( Some ( redirect_addr) ) => {
131- if retry_count < max_retries {
132- retry_count += 1 ;
133- // Retry to specific address
134- let ( tx, rx) = oneshot :: < APIClientReq > ( ) ;
135- let api_req = make_req ( & codec, service_method, req, tx) ;
136- self . resubmit (
137- api_req,
138- Some ( redirect_addr. to_string ( ) ) ,
139- last_index,
140- )
141- . await ;
142- // Update last_index for next iteration
143- last_index = 0 ; // Will be updated by resubmit
144- continue ;
124+ if let Ok ( mut task) = rx. recv_async ( ) . await {
125+ let result = task. process_res :: < _ , Resp , E > ( & codec) ;
126+ match result {
127+ Ok ( resp) => return Ok ( resp) ,
128+ Err ( RpcError :: Rpc ( e) ) => {
129+ // RpcIntErr less than Method is retriable by FailoverPool internally
130+ return Err ( RpcError :: Rpc ( e) ) ;
131+ }
132+ Err ( RpcError :: User ( e) ) => {
133+ retry_count += 1 ;
134+ match e. should_failover ( ) {
135+ Ok ( Some ( redirect_addr) ) => {
136+ if retry_count < max_retries {
137+ // Retry to specific address
138+ let ( tx, _rx) = oneshot :: < APIClientReq > ( ) ;
139+ task. set_noti ( tx) ;
140+ rx = _rx;
141+ self . resubmit (
142+ task,
143+ Ok ( redirect_addr. to_string ( ) ) ,
144+ retry_count,
145+ None ,
146+ )
147+ . await ;
148+ continue ;
149+ }
145150 }
146- }
147- Ok ( None ) => {
148- if retry_count < max_retries {
149- retry_count += 1 ;
150- // Retry to next node
151- let ( tx, rx) = oneshot :: < APIClientReq > ( ) ;
152- let api_req = make_req ( & codec, service_method, req, tx) ;
153- self . resubmit ( api_req, None , last_index) . await ;
154- last_index += 1 ;
155- continue ;
151+ Ok ( None ) => {
152+ if retry_count < max_retries {
153+ // Retry to next node
154+ let ( tx, _rx) = oneshot :: < APIClientReq > ( ) ;
155+ task. set_noti ( tx) ;
156+ rx = _rx;
157+ let last_index = task. last_index ;
158+ self . resubmit ( task, Err ( last_index) , retry_count, None )
159+ . await ;
160+ continue ;
161+ }
156162 }
163+ Err ( ( ) ) => return Err ( RpcError :: User ( e) ) ,
157164 }
158- Err ( ( ) ) => return Err ( RpcError :: User ( e) ) ,
159- }
160- return Err ( RpcError :: User ( e) ) ;
161- }
162- Err ( RpcError :: Rpc ( e) ) => {
163- // RpcIntErr less than Method is retriable by FailoverPool internally
164- return Err ( RpcError :: Rpc ( e) ) ;
165- }
166- }
167- }
168- }
169- }
170- }
171-
172- /*
173- *
174- BlockingEndpoint trait is provided for user-defined blocking clients
175- Users implement this trait on their client structs to get the call() method
176- pub trait BlockingEndpoint: ClientCallerBlocking<Facts: ClientFacts<Task = APIClientReq>>,
177- {
178- fn call<Req, Resp, E>(
179- &self, service_method: &'static str, req: &Req,
180- ) -> Result<Resp, RpcError<E>>
181- where
182- Req: serde::Serialize + fmt::Debug,
183- Resp: for<'a> serde::Deserialize<'a> + Send + fmt::Debug + 'static + Default,
184- E: RpcErrCodec,
185- {
186- let (tx, rx) = oneshot::<APIClientReq>();
187- let codec = self.codec();
188- self.caller().send_req_blocking(make_req(codec, service_method, req, tx));
189- process_res(codec, rx.recv())
190- }
191- }
192- */
193-
194- #[ inline]
195- fn make_req < C , Req > (
196- codec : & C , service_method : & ' static str , req : & Req , done_tx : oneshot:: TxOneshot < APIClientReq > ,
197- ) -> APIClientReq
198- where
199- C : Codec ,
200- Req : serde:: Serialize + fmt:: Debug ,
201- {
202- let req_buf = codec. encode ( req) . expect ( "encode" ) ;
203- APIClientReq {
204- common : Default :: default ( ) ,
205- req_msg : Some ( req_buf) ,
206- action : service_method. to_string ( ) ,
207- resp : None ,
208- res : None ,
209- noti : Some ( done_tx) ,
210- routing_info : None ,
211- }
212- }
213-
214- #[ inline]
215- fn process_res < C , Resp , E > (
216- codec : & C , task_res : Result < APIClientReq , crossfire:: RecvError > ,
217- ) -> Result < Resp , RpcError < E > >
218- where
219- C : Codec ,
220- Resp : for < ' a > serde:: Deserialize < ' a > + Send + fmt:: Debug + ' static + Default ,
221- E : RpcErrCodec ,
222- {
223- match task_res {
224- Ok ( mut task) => {
225- let res = task. res . take ( ) . unwrap ( ) ;
226- match res {
227- Ok ( ( ) ) => {
228- if let Some ( resp) = task. resp {
229- match codec. decode ( & resp) {
230- Ok ( resp_msg) => Ok ( resp_msg) ,
231- Err ( ( ) ) => Err ( RpcIntErr :: Decode . into ( ) ) ,
165+ return Err ( RpcError :: User ( e) ) ;
232166 }
233- } else {
234- Ok ( Resp :: default ( ) )
235167 }
168+ } else {
169+ return Err ( RpcIntErr :: Internal . into ( ) ) ;
236170 }
237- Err ( EncodedErr :: Rpc ( e) ) => Err ( RpcError :: Rpc ( e) ) ,
238- Err ( EncodedErr :: Num ( n) ) => match E :: decode ( codec, Ok ( n) ) {
239- Ok ( e) => Err ( RpcError :: User ( e) ) ,
240- Err ( ( ) ) => Err ( RpcIntErr :: Decode . into ( ) ) ,
241- } ,
242- Err ( EncodedErr :: Buf ( buf) ) => match E :: decode ( codec, Err ( & buf) ) {
243- Ok ( e) => Err ( RpcError :: User ( e) ) ,
244- Err ( ( ) ) => Err ( RpcIntErr :: Decode . into ( ) ) ,
245- } ,
246- _ => unreachable ! ( ) ,
247171 }
248172 }
249- Err ( _) => Err ( RpcIntErr :: Internal . into ( ) ) ,
250173 }
251174}
0 commit comments