@@ -13,10 +13,21 @@ use tokio::sync::{mpsc, oneshot};
13
13
#[ cfg( feature = "http2" ) ]
14
14
use crate :: { body:: Incoming , proto:: h2:: client:: ResponseFutMap } ;
15
15
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 > > > ;
18
17
pub ( crate ) type Promise < T > = oneshot:: Receiver < Result < T , crate :: Error > > ;
19
18
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
+
20
31
pub ( crate ) fn channel < T , U > ( ) -> ( Sender < T , U > , Receiver < T , U > ) {
21
32
let ( tx, rx) = mpsc:: unbounded_channel ( ) ;
22
33
let ( giver, taker) = want:: new ( ) ;
@@ -92,7 +103,7 @@ impl<T, U> Sender<T, U> {
92
103
}
93
104
}
94
105
95
- #[ cfg( test ) ]
106
+ #[ cfg( feature = "http1" ) ]
96
107
pub ( crate ) fn try_send ( & mut self , val : T ) -> Result < RetryPromise < T , U > , T > {
97
108
if !self . can_send ( ) {
98
109
return Err ( val) ;
@@ -135,7 +146,6 @@ impl<T, U> UnboundedSender<T, U> {
135
146
self . giver . is_canceled ( )
136
147
}
137
148
138
- #[ cfg( test) ]
139
149
pub ( crate ) fn try_send ( & mut self , val : T ) -> Result < RetryPromise < T , U > , T > {
140
150
let ( tx, rx) = oneshot:: channel ( ) ;
141
151
self . inner
@@ -210,17 +220,17 @@ struct Envelope<T, U>(Option<(T, Callback<T, U>)>);
210
220
impl < T , U > Drop for Envelope < T , U > {
211
221
fn drop ( & mut self ) {
212
222
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
+ } ) ) ;
217
227
}
218
228
}
219
229
}
220
230
221
231
pub ( crate ) enum Callback < T , U > {
222
232
#[ allow( unused) ]
223
- Retry ( Option < oneshot:: Sender < Result < U , ( crate :: Error , Option < T > ) > > > ) ,
233
+ Retry ( Option < oneshot:: Sender < Result < U , TrySendError < T > > > > ) ,
224
234
NoRetry ( Option < oneshot:: Sender < Result < U , crate :: Error > > > ) ,
225
235
}
226
236
@@ -229,7 +239,10 @@ impl<T, U> Drop for Callback<T, U> {
229
239
match self {
230
240
Callback :: Retry ( tx) => {
231
241
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
+ } ) ) ;
233
246
}
234
247
}
235
248
Callback :: NoRetry ( tx) => {
@@ -269,18 +282,34 @@ impl<T, U> Callback<T, U> {
269
282
}
270
283
}
271
284
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 > > ) {
273
286
match self {
274
287
Callback :: Retry ( ref mut tx) => {
275
288
let _ = tx. take ( ) . unwrap ( ) . send ( val) ;
276
289
}
277
290
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 ) ) ;
279
292
}
280
293
}
281
294
}
282
295
}
283
296
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
+
284
313
#[ cfg( feature = "http2" ) ]
285
314
pin_project ! {
286
315
pub struct SendWhen <B >
@@ -325,8 +354,8 @@ where
325
354
trace ! ( "send_when canceled" ) ;
326
355
Poll :: Ready ( ( ) )
327
356
}
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 } ) ) ;
330
359
Poll :: Ready ( ( ) )
331
360
}
332
361
}
@@ -389,8 +418,8 @@ mod tests {
389
418
let err = fulfilled
390
419
. expect ( "fulfilled" )
391
420
. 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 ( _) ) => ( ) ,
394
423
e => panic ! ( "expected Error::Cancel(_), found {:?}" , e) ,
395
424
}
396
425
}
0 commit comments