@@ -11,42 +11,66 @@ const RABBITMQ_CONSUMER_NAMES: [&str; 1] = ["async.operations.all"];
11
11
pub struct WorkerProcess {
12
12
// The consumer name
13
13
consumer : String ,
14
- // The process handle
15
- process : std:: process:: Child ,
14
+ // The process handles
15
+ processes : Vec < std:: process:: Child > ,
16
16
}
17
17
18
18
impl WorkerProcess {
19
19
pub fn terminate ( & mut self ) {
20
20
log:: debug!( "Terminating consumer: {}" , self . consumer) ;
21
- util:: terminate_process_child ( & self . process ) . unwrap ( ) ;
22
- if self . process . try_wait ( ) . unwrap ( ) . is_none ( ) {
23
- self . process . kill ( ) . unwrap ( ) ;
21
+ for p in self . processes . iter_mut ( ) {
22
+ util:: terminate_process_child ( & p) . unwrap ( ) ;
23
+ if p. is_running ( ) {
24
+ log:: debug!( "Force killing consumer: {}" , self . consumer) ;
25
+ p. kill ( ) . unwrap ( ) ;
26
+ }
24
27
}
25
28
}
26
29
27
- pub fn is_running ( & mut self ) -> bool {
28
- match self . process . try_wait ( ) {
29
- Ok ( Some ( _) ) => false ,
30
- Ok ( None ) => true ,
31
- Err ( _) => false ,
30
+ pub fn ensure_running ( & mut self , context : & DaemonContext ) {
31
+ if !self . processes . is_running ( ) {
32
+ self . restart ( context) ;
32
33
}
33
34
}
34
35
35
36
pub fn restart ( & mut self , context : & DaemonContext ) {
36
- if self . is_running ( ) {
37
- self . terminate ( ) ;
37
+ self . terminate ( ) ;
38
+ self . processes = run_worker ( & context, & self . consumer ) . processes ;
39
+ }
40
+ }
41
+
42
+ trait WorkerChildProcess {
43
+ fn is_running ( & mut self ) -> bool ;
44
+ }
45
+
46
+ impl WorkerChildProcess for std:: process:: Child {
47
+ fn is_running ( & mut self ) -> bool {
48
+ match self . try_wait ( ) {
49
+ Ok ( Some ( status) ) => {
50
+ log:: debug!( "Process exited with status {:?}" , status) ;
51
+ return false ;
52
+ }
53
+ Ok ( None ) => true ,
54
+ Err ( err) => {
55
+ log:: debug!( "Process has error {:?}" , err) ;
56
+ return false ;
57
+ }
38
58
}
39
- self . process = run_worker ( & context, & self . consumer ) . process ;
59
+ }
60
+ }
61
+
62
+ impl WorkerChildProcess for Vec < std:: process:: Child > {
63
+ fn is_running ( & mut self ) -> bool {
64
+ self . iter_mut ( ) . all ( |p| p. is_running ( ) )
40
65
}
41
66
}
42
67
43
68
pub fn read_consumer_list ( config : & DaemonConfig ) -> Vec < String > {
44
- // Read consumer list by running bin/magento queue:consumers:list
45
69
let output = Command :: new ( "bin/magento" )
46
70
. current_dir ( & config. magento_dir )
47
71
. arg ( "queue:consumers:list" )
48
72
. output ( )
49
- . expect ( "failed to run bin/magento queue:consumers:list" ) ;
73
+ . expect ( "Failed to run bin/magento queue:consumers:list" ) ;
50
74
51
75
// Split output by newline and convert from u8 sequences to String
52
76
output
@@ -67,30 +91,41 @@ pub fn read_consumer_list(config: &DaemonConfig) -> Vec<String> {
67
91
68
92
pub fn run_worker ( context : & DaemonContext , consumer : & String ) -> WorkerProcess {
69
93
log:: debug!( "Running consumer: {}" , consumer) ;
70
- let mut command = Command :: new ( "bin/magento" ) ;
71
- let command = command
72
- . current_dir ( & context. daemon_config . magento_dir )
73
- . arg ( "queue:consumers:start" )
74
- . arg ( consumer)
75
- . arg ( "--max-messages" )
76
- . arg ( context. consumer_config . max_messages . to_string ( ) ) ;
77
94
95
+ let mut number_of_processes = 1 ;
78
96
if let Some ( processes) = context. consumer_config . multiple_processes . get ( consumer) {
79
- if * processes > 1 {
80
- command. arg ( "--multi-process" ) . arg ( processes. to_string ( ) ) ;
97
+ number_of_processes = * processes;
98
+ }
99
+
100
+ let mut processes = Vec :: < std:: process:: Child > :: new ( ) ;
101
+
102
+ for i in 0 ..number_of_processes {
103
+ let mut command = Command :: new ( "bin/magento" ) ;
104
+ let command = command
105
+ . current_dir ( & context. daemon_config . magento_dir )
106
+ . arg ( "queue:consumers:start" )
107
+ . arg ( consumer)
108
+ . arg ( "--max-messages" )
109
+ . arg ( context. consumer_config . max_messages . to_string ( ) ) ;
110
+
111
+ // We could disable the --multi-process or --single-thread options with a --no-strict-mode flag,
112
+ // but not sure if users need that, so this is the default for now.
113
+ if number_of_processes > 1 {
114
+ command. arg ( "--multi-process" ) ;
115
+ command. arg ( i. to_string ( ) ) ;
81
116
} else {
82
117
command. arg ( "--single-thread" ) ;
83
118
}
84
- } else {
85
- command. arg ( "--single-thread" ) ;
86
- }
87
119
88
- let process = command
89
- . spawn ( )
90
- . expect ( "failed to run bin/magento queue:consumers:start" ) ;
120
+ let process = command
121
+ . spawn ( )
122
+ . expect ( "Failed to run bin/magento queue:consumers:start" ) ;
123
+
124
+ processes. push ( process) ;
125
+ }
91
126
92
127
WorkerProcess {
93
128
consumer : consumer. clone ( ) ,
94
- process ,
129
+ processes ,
95
130
}
96
131
}
0 commit comments