1
1
use super :: { ConnectionLike , Runtime } ;
2
2
use crate :: aio:: setup_connection;
3
+ use crate :: aio:: DisconnectNotifier ;
4
+ use crate :: client:: GlideConnectionOptions ;
3
5
use crate :: cmd:: Cmd ;
4
6
#[ cfg( any( feature = "tokio-comp" , feature = "async-std-comp" ) ) ]
5
7
use crate :: parser:: ValueCodec ;
6
8
use crate :: push_manager:: PushManager ;
7
9
use crate :: types:: { RedisError , RedisFuture , RedisResult , Value } ;
8
- use crate :: { cmd, ConnectionInfo , ProtocolVersion , PushInfo , PushKind } ;
10
+ use crate :: { cmd, ConnectionInfo , ProtocolVersion , PushKind } ;
9
11
use :: tokio:: {
10
12
io:: { AsyncRead , AsyncWrite } ,
11
13
sync:: { mpsc, oneshot} ,
@@ -23,6 +25,7 @@ use std::fmt;
23
25
use std:: fmt:: Debug ;
24
26
use std:: io;
25
27
use std:: pin:: Pin ;
28
+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
26
29
use std:: sync:: Arc ;
27
30
use std:: task:: { self , Poll } ;
28
31
use std:: time:: Duration ;
@@ -73,19 +76,11 @@ struct PipelineMessage<S> {
73
76
/// items being output by the `Stream` (the number is specified at time of sending). With the
74
77
/// interface provided by `Pipeline` an easy interface of request to response, hiding the `Stream`
75
78
/// and `Sink`.
79
+ #[ derive( Clone ) ]
76
80
struct Pipeline < SinkItem > {
77
81
sender : mpsc:: Sender < PipelineMessage < SinkItem > > ,
78
-
79
82
push_manager : Arc < ArcSwap < PushManager > > ,
80
- }
81
-
82
- impl < SinkItem > Clone for Pipeline < SinkItem > {
83
- fn clone ( & self ) -> Self {
84
- Pipeline {
85
- sender : self . sender . clone ( ) ,
86
- push_manager : self . push_manager . clone ( ) ,
87
- }
88
- }
83
+ is_stream_closed : Arc < AtomicBool > ,
89
84
}
90
85
91
86
impl < SinkItem > Debug for Pipeline < SinkItem >
@@ -104,14 +99,21 @@ pin_project! {
104
99
in_flight: VecDeque <InFlight >,
105
100
error: Option <RedisError >,
106
101
push_manager: Arc <ArcSwap <PushManager >>,
102
+ disconnect_notifier: Option <Box <dyn DisconnectNotifier >>,
103
+ is_stream_closed: Arc <AtomicBool >,
107
104
}
108
105
}
109
106
110
107
impl < T > PipelineSink < T >
111
108
where
112
109
T : Stream < Item = RedisResult < Value > > + ' static ,
113
110
{
114
- fn new < SinkItem > ( sink_stream : T , push_manager : Arc < ArcSwap < PushManager > > ) -> Self
111
+ fn new < SinkItem > (
112
+ sink_stream : T ,
113
+ push_manager : Arc < ArcSwap < PushManager > > ,
114
+ disconnect_notifier : Option < Box < dyn DisconnectNotifier > > ,
115
+ is_stream_closed : Arc < AtomicBool > ,
116
+ ) -> Self
115
117
where
116
118
T : Sink < SinkItem , Error = RedisError > + Stream < Item = RedisResult < Value > > + ' static ,
117
119
{
@@ -120,6 +122,8 @@ where
120
122
in_flight : VecDeque :: new ( ) ,
121
123
error : None ,
122
124
push_manager,
125
+ disconnect_notifier,
126
+ is_stream_closed,
123
127
}
124
128
}
125
129
@@ -130,7 +134,15 @@ where
130
134
Some ( result) => result,
131
135
// The redis response stream is not going to produce any more items so we `Err`
132
136
// to break out of the `forward` combinator and stop handling requests
133
- None => return Poll :: Ready ( Err ( ( ) ) ) ,
137
+ None => {
138
+ // this is the right place to notify about the passive TCP disconnect
139
+ // In other places we cannot distinguish between the active destruction of MultiplexedConnection and passive disconnect
140
+ if let Some ( disconnect_notifier) = self . as_mut ( ) . project ( ) . disconnect_notifier {
141
+ disconnect_notifier. notify_disconnect ( ) ;
142
+ }
143
+ self . is_stream_closed . store ( true , Ordering :: Relaxed ) ;
144
+ return Poll :: Ready ( Err ( ( ) ) ) ;
145
+ }
134
146
} ;
135
147
self . as_mut ( ) . send_result ( item) ;
136
148
}
@@ -296,7 +308,10 @@ impl<SinkItem> Pipeline<SinkItem>
296
308
where
297
309
SinkItem : Send + ' static ,
298
310
{
299
- fn new < T > ( sink_stream : T ) -> ( Self , impl Future < Output = ( ) > )
311
+ fn new < T > (
312
+ sink_stream : T ,
313
+ disconnect_notifier : Option < Box < dyn DisconnectNotifier > > ,
314
+ ) -> ( Self , impl Future < Output = ( ) > )
300
315
where
301
316
T : Sink < SinkItem , Error = RedisError > + Stream < Item = RedisResult < Value > > + ' static ,
302
317
T : Send + ' static ,
@@ -308,7 +323,13 @@ where
308
323
let ( sender, mut receiver) = mpsc:: channel ( BUFFER_SIZE ) ;
309
324
let push_manager: Arc < ArcSwap < PushManager > > =
310
325
Arc :: new ( ArcSwap :: new ( Arc :: new ( PushManager :: default ( ) ) ) ) ;
311
- let sink = PipelineSink :: new :: < SinkItem > ( sink_stream, push_manager. clone ( ) ) ;
326
+ let is_stream_closed = Arc :: new ( AtomicBool :: new ( false ) ) ;
327
+ let sink = PipelineSink :: new :: < SinkItem > (
328
+ sink_stream,
329
+ push_manager. clone ( ) ,
330
+ disconnect_notifier,
331
+ is_stream_closed. clone ( ) ,
332
+ ) ;
312
333
let f = stream:: poll_fn ( move |cx| receiver. poll_recv ( cx) )
313
334
. map ( Ok )
314
335
. forward ( sink)
@@ -317,6 +338,7 @@ where
317
338
Pipeline {
318
339
sender,
319
340
push_manager,
341
+ is_stream_closed,
320
342
} ,
321
343
f,
322
344
)
@@ -363,6 +385,10 @@ where
363
385
async fn set_push_manager ( & mut self , push_manager : PushManager ) {
364
386
self . push_manager . store ( Arc :: new ( push_manager) ) ;
365
387
}
388
+
389
+ pub fn is_closed ( & self ) -> bool {
390
+ self . is_stream_closed . load ( Ordering :: Relaxed )
391
+ }
366
392
}
367
393
368
394
/// A connection object which can be cloned, allowing requests to be be sent concurrently
@@ -391,7 +417,7 @@ impl MultiplexedConnection {
391
417
pub async fn new < C > (
392
418
connection_info : & ConnectionInfo ,
393
419
stream : C ,
394
- push_sender : Option < mpsc :: UnboundedSender < PushInfo > > ,
420
+ glide_connection_options : GlideConnectionOptions ,
395
421
) -> RedisResult < ( Self , impl Future < Output = ( ) > ) >
396
422
where
397
423
C : Unpin + AsyncRead + AsyncWrite + Send + ' static ,
@@ -400,7 +426,7 @@ impl MultiplexedConnection {
400
426
connection_info,
401
427
stream,
402
428
std:: time:: Duration :: MAX ,
403
- push_sender ,
429
+ glide_connection_options ,
404
430
)
405
431
. await
406
432
}
@@ -411,7 +437,7 @@ impl MultiplexedConnection {
411
437
connection_info : & ConnectionInfo ,
412
438
stream : C ,
413
439
response_timeout : std:: time:: Duration ,
414
- push_sender : Option < mpsc :: UnboundedSender < PushInfo > > ,
440
+ glide_connection_options : GlideConnectionOptions ,
415
441
) -> RedisResult < ( Self , impl Future < Output = ( ) > ) >
416
442
where
417
443
C : Unpin + AsyncRead + AsyncWrite + Send + ' static ,
@@ -429,10 +455,11 @@ impl MultiplexedConnection {
429
455
let codec = ValueCodec :: default ( )
430
456
. framed ( stream)
431
457
. and_then ( |msg| async move { msg } ) ;
432
- let ( mut pipeline, driver) = Pipeline :: new ( codec) ;
458
+ let ( mut pipeline, driver) =
459
+ Pipeline :: new ( codec, glide_connection_options. disconnect_notifier ) ;
433
460
let driver = boxed ( driver) ;
434
461
let pm = PushManager :: default ( ) ;
435
- if let Some ( sender) = push_sender {
462
+ if let Some ( sender) = glide_connection_options . push_sender {
436
463
pm. replace_sender ( sender) ;
437
464
}
438
465
@@ -560,6 +587,10 @@ impl ConnectionLike for MultiplexedConnection {
560
587
fn get_db ( & self ) -> i64 {
561
588
self . db
562
589
}
590
+
591
+ fn is_closed ( & self ) -> bool {
592
+ self . pipeline . is_closed ( )
593
+ }
563
594
}
564
595
impl MultiplexedConnection {
565
596
/// Subscribes to a new channel.
0 commit comments