1
1
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
2
2
use std:: sync:: { mpsc, Arc } ;
3
- use std:: { net, thread, time} ;
3
+ use std:: { net, thread, time:: Duration } ;
4
4
5
+ use actix_rt:: { net:: TcpStream , time:: sleep} ;
5
6
use actix_server:: Server ;
6
7
use actix_service:: fn_service;
7
8
use actix_utils:: future:: ok;
@@ -37,7 +38,7 @@ fn test_bind() {
37
38
} ) ;
38
39
let ( _, sys) = rx. recv ( ) . unwrap ( ) ;
39
40
40
- thread:: sleep ( time :: Duration :: from_millis ( 500 ) ) ;
41
+ thread:: sleep ( Duration :: from_millis ( 500 ) ) ;
41
42
assert ! ( net:: TcpStream :: connect( addr) . is_ok( ) ) ;
42
43
sys. stop ( ) ;
43
44
let _ = h. join ( ) ;
@@ -64,7 +65,7 @@ fn test_listen() {
64
65
} ) ;
65
66
let sys = rx. recv ( ) . unwrap ( ) ;
66
67
67
- thread:: sleep ( time :: Duration :: from_millis ( 500 ) ) ;
68
+ thread:: sleep ( Duration :: from_millis ( 500 ) ) ;
68
69
assert ! ( net:: TcpStream :: connect( addr) . is_ok( ) ) ;
69
70
sys. stop ( ) ;
70
71
let _ = h. join ( ) ;
@@ -73,11 +74,11 @@ fn test_listen() {
73
74
#[ test]
74
75
#[ cfg( unix) ]
75
76
fn test_start ( ) {
77
+ use std:: io:: Read ;
78
+
76
79
use actix_codec:: { BytesCodec , Framed } ;
77
- use actix_rt:: net:: TcpStream ;
78
80
use bytes:: Bytes ;
79
81
use futures_util:: sink:: SinkExt ;
80
- use std:: io:: Read ;
81
82
82
83
let addr = unused_addr ( ) ;
83
84
let ( tx, rx) = mpsc:: channel ( ) ;
@@ -112,16 +113,16 @@ fn test_start() {
112
113
113
114
// pause
114
115
let _ = srv. pause ( ) ;
115
- thread:: sleep ( time :: Duration :: from_millis ( 200 ) ) ;
116
+ thread:: sleep ( Duration :: from_millis ( 200 ) ) ;
116
117
let mut conn = net:: TcpStream :: connect ( addr) . unwrap ( ) ;
117
- conn. set_read_timeout ( Some ( time :: Duration :: from_millis ( 100 ) ) )
118
+ conn. set_read_timeout ( Some ( Duration :: from_millis ( 100 ) ) )
118
119
. unwrap ( ) ;
119
120
let res = conn. read_exact ( & mut buf) ;
120
121
assert ! ( res. is_err( ) ) ;
121
122
122
123
// resume
123
124
let _ = srv. resume ( ) ;
124
- thread:: sleep ( time :: Duration :: from_millis ( 100 ) ) ;
125
+ thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
125
126
assert ! ( net:: TcpStream :: connect( addr) . is_ok( ) ) ;
126
127
assert ! ( net:: TcpStream :: connect( addr) . is_ok( ) ) ;
127
128
assert ! ( net:: TcpStream :: connect( addr) . is_ok( ) ) ;
@@ -133,10 +134,10 @@ fn test_start() {
133
134
134
135
// stop
135
136
let _ = srv. stop ( false ) ;
136
- thread:: sleep ( time :: Duration :: from_millis ( 100 ) ) ;
137
+ thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
137
138
assert ! ( net:: TcpStream :: connect( addr) . is_err( ) ) ;
138
139
139
- thread:: sleep ( time :: Duration :: from_millis ( 100 ) ) ;
140
+ thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
140
141
sys. stop ( ) ;
141
142
let _ = h. join ( ) ;
142
143
}
@@ -182,7 +183,7 @@ fn test_configure() {
182
183
let _ = sys. run ( ) ;
183
184
} ) ;
184
185
let ( _, sys) = rx. recv ( ) . unwrap ( ) ;
185
- thread:: sleep ( time :: Duration :: from_millis ( 500 ) ) ;
186
+ thread:: sleep ( Duration :: from_millis ( 500 ) ) ;
186
187
187
188
assert ! ( net:: TcpStream :: connect( addr1) . is_ok( ) ) ;
188
189
assert ! ( net:: TcpStream :: connect( addr2) . is_ok( ) ) ;
@@ -200,7 +201,6 @@ async fn test_max_concurrent_connections() {
200
201
// The limit test on the other hand is only for concurrent tcp stream limiting a work
201
202
// thread accept.
202
203
203
- use actix_rt:: net:: TcpStream ;
204
204
use tokio:: io:: AsyncWriteExt ;
205
205
206
206
let addr = unused_addr ( ) ;
@@ -226,7 +226,7 @@ async fn test_max_concurrent_connections() {
226
226
let counter = counter. clone ( ) ;
227
227
async move {
228
228
counter. fetch_add ( 1 , Ordering :: SeqCst ) ;
229
- actix_rt :: time :: sleep ( time :: Duration :: from_secs ( 20 ) ) . await ;
229
+ sleep ( Duration :: from_secs ( 20 ) ) . await ;
230
230
counter. fetch_sub ( 1 , Ordering :: SeqCst ) ;
231
231
Ok :: < ( ) , ( ) > ( ( ) )
232
232
}
@@ -249,7 +249,7 @@ async fn test_max_concurrent_connections() {
249
249
conns. push ( conn) ;
250
250
}
251
251
252
- actix_rt :: time :: sleep ( time :: Duration :: from_secs ( 5 ) ) . await ;
252
+ sleep ( Duration :: from_secs ( 5 ) ) . await ;
253
253
254
254
// counter would remain at 3 even with 12 successful connection.
255
255
// and 9 of them remain in backlog.
@@ -268,9 +268,7 @@ async fn test_max_concurrent_connections() {
268
268
#[ actix_rt:: test]
269
269
async fn test_service_restart ( ) {
270
270
use std:: task:: { Context , Poll } ;
271
- use std:: time:: Duration ;
272
271
273
- use actix_rt:: { net:: TcpStream , time:: sleep} ;
274
272
use actix_service:: { fn_factory, Service } ;
275
273
use futures_core:: future:: LocalBoxFuture ;
276
274
use tokio:: io:: AsyncWriteExt ;
@@ -438,3 +436,143 @@ async fn test_service_restart() {
438
436
let _ = server. stop ( false ) ;
439
437
let _ = h. join ( ) . unwrap ( ) ;
440
438
}
439
+
440
+ #[ actix_rt:: test]
441
+ async fn worker_restart ( ) {
442
+ use actix_service:: { Service , ServiceFactory } ;
443
+ use futures_core:: future:: LocalBoxFuture ;
444
+ use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
445
+
446
+ struct TestServiceFactory ( Arc < AtomicUsize > ) ;
447
+
448
+ impl ServiceFactory < TcpStream > for TestServiceFactory {
449
+ type Response = ( ) ;
450
+ type Error = ( ) ;
451
+ type Config = ( ) ;
452
+ type Service = TestService ;
453
+ type InitError = ( ) ;
454
+ type Future = LocalBoxFuture < ' static , Result < Self :: Service , Self :: InitError > > ;
455
+
456
+ fn new_service ( & self , _: Self :: Config ) -> Self :: Future {
457
+ let counter = self . 0 . fetch_add ( 1 , Ordering :: Relaxed ) ;
458
+
459
+ Box :: pin ( async move { Ok ( TestService ( counter) ) } )
460
+ }
461
+ }
462
+
463
+ struct TestService ( usize ) ;
464
+
465
+ impl Service < TcpStream > for TestService {
466
+ type Response = ( ) ;
467
+ type Error = ( ) ;
468
+ type Future = LocalBoxFuture < ' static , Result < Self :: Response , Self :: Error > > ;
469
+
470
+ actix_service:: always_ready!( ) ;
471
+
472
+ fn call ( & self , stream : TcpStream ) -> Self :: Future {
473
+ let counter = self . 0 ;
474
+
475
+ let mut stream = stream. into_std ( ) . unwrap ( ) ;
476
+ use std:: io:: Write ;
477
+ let str = counter. to_string ( ) ;
478
+ let buf = str. as_bytes ( ) ;
479
+
480
+ let mut written = 0 ;
481
+
482
+ while written < buf. len ( ) {
483
+ if let Ok ( n) = stream. write ( & buf[ written..] ) {
484
+ written += n;
485
+ }
486
+ }
487
+ stream. flush ( ) . unwrap ( ) ;
488
+ stream. shutdown ( net:: Shutdown :: Write ) . unwrap ( ) ;
489
+
490
+ // force worker 2 to restart service once.
491
+ if counter == 2 {
492
+ panic ! ( "panic on purpose" )
493
+ } else {
494
+ Box :: pin ( async { Ok ( ( ) ) } )
495
+ }
496
+ }
497
+ }
498
+
499
+ let addr = unused_addr ( ) ;
500
+ let ( tx, rx) = mpsc:: channel ( ) ;
501
+
502
+ let counter = Arc :: new ( AtomicUsize :: new ( 1 ) ) ;
503
+ let h = thread:: spawn ( move || {
504
+ let counter = counter. clone ( ) ;
505
+ actix_rt:: System :: new ( ) . block_on ( async {
506
+ let server = Server :: build ( )
507
+ . disable_signals ( )
508
+ . bind ( "addr" , addr, move || TestServiceFactory ( counter. clone ( ) ) )
509
+ . unwrap ( )
510
+ . workers ( 2 )
511
+ . run ( ) ;
512
+
513
+ let _ = tx. send ( ( server. clone ( ) , actix_rt:: System :: current ( ) ) ) ;
514
+ server. await
515
+ } )
516
+ } ) ;
517
+
518
+ let ( server, sys) = rx. recv ( ) . unwrap ( ) ;
519
+
520
+ sleep ( Duration :: from_secs ( 3 ) ) . await ;
521
+
522
+ let mut buf = [ 0 ; 8 ] ;
523
+
524
+ // worker 1 would not restart and return it's id consistently.
525
+ let mut stream = TcpStream :: connect ( addr) . await . unwrap ( ) ;
526
+ let n = stream. read ( & mut buf) . await . unwrap ( ) ;
527
+ let id = String :: from_utf8_lossy ( & buf[ 0 ..n] ) ;
528
+ assert_eq ! ( "1" , id) ;
529
+ stream. shutdown ( ) . await . unwrap ( ) ;
530
+
531
+ // worker 2 dead after return response.
532
+ let mut stream = TcpStream :: connect ( addr) . await . unwrap ( ) ;
533
+ let n = stream. read ( & mut buf) . await . unwrap ( ) ;
534
+ let id = String :: from_utf8_lossy ( & buf[ 0 ..n] ) ;
535
+ assert_eq ! ( "2" , id) ;
536
+ stream. shutdown ( ) . await . unwrap ( ) ;
537
+
538
+ // request to worker 1
539
+ let mut stream = TcpStream :: connect ( addr) . await . unwrap ( ) ;
540
+ let n = stream. read ( & mut buf) . await . unwrap ( ) ;
541
+ let id = String :: from_utf8_lossy ( & buf[ 0 ..n] ) ;
542
+ assert_eq ! ( "1" , id) ;
543
+ stream. shutdown ( ) . await . unwrap ( ) ;
544
+
545
+ // TODO: Remove sleep if it can pass CI.
546
+ sleep ( Duration :: from_secs ( 3 ) ) . await ;
547
+
548
+ // worker 2 restarting and work goes to worker 1.
549
+ let mut stream = TcpStream :: connect ( addr) . await . unwrap ( ) ;
550
+ let n = stream. read ( & mut buf) . await . unwrap ( ) ;
551
+ let id = String :: from_utf8_lossy ( & buf[ 0 ..n] ) ;
552
+ assert_eq ! ( "1" , id) ;
553
+ stream. shutdown ( ) . await . unwrap ( ) ;
554
+
555
+ // TODO: Remove sleep if it can pass CI.
556
+ sleep ( Duration :: from_secs ( 3 ) ) . await ;
557
+
558
+ // worker 2 restarted but worker 1 was still the next to accept connection.
559
+ let mut stream = TcpStream :: connect ( addr) . await . unwrap ( ) ;
560
+ let n = stream. read ( & mut buf) . await . unwrap ( ) ;
561
+ let id = String :: from_utf8_lossy ( & buf[ 0 ..n] ) ;
562
+ assert_eq ! ( "1" , id) ;
563
+ stream. shutdown ( ) . await . unwrap ( ) ;
564
+
565
+ // TODO: Remove sleep if it can pass CI.
566
+ sleep ( Duration :: from_secs ( 3 ) ) . await ;
567
+
568
+ // worker 2 accept connection again but it's id is 3.
569
+ let mut stream = TcpStream :: connect ( addr) . await . unwrap ( ) ;
570
+ let n = stream. read ( & mut buf) . await . unwrap ( ) ;
571
+ let id = String :: from_utf8_lossy ( & buf[ 0 ..n] ) ;
572
+ assert_eq ! ( "3" , id) ;
573
+ stream. shutdown ( ) . await . unwrap ( ) ;
574
+
575
+ sys. stop ( ) ;
576
+ let _ = server. stop ( false ) ;
577
+ let _ = h. join ( ) . unwrap ( ) ;
578
+ }
0 commit comments