@@ -13,10 +13,21 @@ use tokio::sync::{mpsc, oneshot};
1313#[ cfg( feature = "http2" ) ]
1414use crate :: { body:: Incoming , proto:: h2:: client:: ResponseFutMap } ;
1515
16- #[ cfg( test) ]
17- pub ( crate ) type RetryPromise < T , U > = oneshot:: Receiver < Result < U , ( crate :: Error , Option < T > ) > > ;
16+ pub ( crate ) type RetryPromise < T , U > = oneshot:: Receiver < Result < U , TrySendError < T > > > ;
1817pub ( crate ) type Promise < T > = oneshot:: Receiver < Result < T , crate :: Error > > ;
1918
19+ /// An error when calling `try_send_request`.
20+ ///
21+ /// There is a possibility of an error occuring on a connection in-between the
22+ /// time that a request is queued and when it is actually written to the IO
23+ /// transport. If that happens, it is safe to return the request back to the
24+ /// caller, as it was never fully sent.
25+ #[ derive( Debug ) ]
26+ pub struct TrySendError < T > {
27+ pub ( crate ) error : crate :: Error ,
28+ pub ( crate ) message : Option < T > ,
29+ }
30+
2031pub ( crate ) fn channel < T , U > ( ) -> ( Sender < T , U > , Receiver < T , U > ) {
2132 let ( tx, rx) = mpsc:: unbounded_channel ( ) ;
2233 let ( giver, taker) = want:: new ( ) ;
@@ -92,7 +103,7 @@ impl<T, U> Sender<T, U> {
92103 }
93104 }
94105
95- #[ cfg( test ) ]
106+ #[ cfg( feature = "http1" ) ]
96107 pub ( crate ) fn try_send ( & mut self , val : T ) -> Result < RetryPromise < T , U > , T > {
97108 if !self . can_send ( ) {
98109 return Err ( val) ;
@@ -135,7 +146,6 @@ impl<T, U> UnboundedSender<T, U> {
135146 self . giver . is_canceled ( )
136147 }
137148
138- #[ cfg( test) ]
139149 pub ( crate ) fn try_send ( & mut self , val : T ) -> Result < RetryPromise < T , U > , T > {
140150 let ( tx, rx) = oneshot:: channel ( ) ;
141151 self . inner
@@ -210,17 +220,17 @@ struct Envelope<T, U>(Option<(T, Callback<T, U>)>);
210220impl < T , U > Drop for Envelope < T , U > {
211221 fn drop ( & mut self ) {
212222 if let Some ( ( val, cb) ) = self . 0 . take ( ) {
213- cb. send ( Err ( (
214- crate :: Error :: new_canceled ( ) . with ( "connection closed" ) ,
215- Some ( val) ,
216- ) ) ) ;
223+ cb. send ( Err ( TrySendError {
224+ error : crate :: Error :: new_canceled ( ) . with ( "connection closed" ) ,
225+ message : Some ( val) ,
226+ } ) ) ;
217227 }
218228 }
219229}
220230
221231pub ( crate ) enum Callback < T , U > {
222232 #[ allow( unused) ]
223- Retry ( Option < oneshot:: Sender < Result < U , ( crate :: Error , Option < T > ) > > > ) ,
233+ Retry ( Option < oneshot:: Sender < Result < U , TrySendError < T > > > > ) ,
224234 NoRetry ( Option < oneshot:: Sender < Result < U , crate :: Error > > > ) ,
225235}
226236
@@ -229,7 +239,10 @@ impl<T, U> Drop for Callback<T, U> {
229239 match self {
230240 Callback :: Retry ( tx) => {
231241 if let Some ( tx) = tx. take ( ) {
232- let _ = tx. send ( Err ( ( dispatch_gone ( ) , None ) ) ) ;
242+ let _ = tx. send ( Err ( TrySendError {
243+ error : dispatch_gone ( ) ,
244+ message : None ,
245+ } ) ) ;
233246 }
234247 }
235248 Callback :: NoRetry ( tx) => {
@@ -269,18 +282,34 @@ impl<T, U> Callback<T, U> {
269282 }
270283 }
271284
272- pub ( crate ) fn send ( mut self , val : Result < U , ( crate :: Error , Option < T > ) > ) {
285+ pub ( crate ) fn send ( mut self , val : Result < U , TrySendError < T > > ) {
273286 match self {
274287 Callback :: Retry ( ref mut tx) => {
275288 let _ = tx. take ( ) . unwrap ( ) . send ( val) ;
276289 }
277290 Callback :: NoRetry ( ref mut tx) => {
278- let _ = tx. take ( ) . unwrap ( ) . send ( val. map_err ( |e| e. 0 ) ) ;
291+ let _ = tx. take ( ) . unwrap ( ) . send ( val. map_err ( |e| e. error ) ) ;
279292 }
280293 }
281294 }
282295}
283296
297+ impl < T > TrySendError < T > {
298+ /// Take the message from this error.
299+ ///
300+ /// The message will not always have been recovered. If an error occurs
301+ /// after the message has been serialized onto the connection, it will not
302+ /// be available here.
303+ pub fn take_message ( & mut self ) -> Option < T > {
304+ self . message . take ( )
305+ }
306+
307+ /// Consumes this to return the inner error.
308+ pub fn into_error ( self ) -> crate :: Error {
309+ self . error
310+ }
311+ }
312+
284313#[ cfg( feature = "http2" ) ]
285314pin_project ! {
286315 pub struct SendWhen <B >
@@ -325,8 +354,8 @@ where
325354 trace ! ( "send_when canceled" ) ;
326355 Poll :: Ready ( ( ) )
327356 }
328- Poll :: Ready ( Err ( err ) ) => {
329- call_back. send ( Err ( err ) ) ;
357+ Poll :: Ready ( Err ( ( error , message ) ) ) => {
358+ call_back. send ( Err ( TrySendError { error , message } ) ) ;
330359 Poll :: Ready ( ( ) )
331360 }
332361 }
@@ -389,8 +418,8 @@ mod tests {
389418 let err = fulfilled
390419 . expect ( "fulfilled" )
391420 . expect_err ( "promise should error" ) ;
392- match ( err. 0 . kind ( ) , err. 1 ) {
393- ( & crate :: error :: Kind :: Canceled , Some ( _) ) => ( ) ,
421+ match ( err. error . is_canceled ( ) , err. message ) {
422+ ( true , Some ( _) ) => ( ) ,
394423 e => panic ! ( "expected Error::Cancel(_), found {:?}" , e) ,
395424 }
396425 }
0 commit comments