@@ -3,7 +3,7 @@ use std::sync::Arc;
3
3
use slog:: { error, warn, Logger } ;
4
4
5
5
use mithril_common:: { logging:: LoggerExtensions , StdResult } ;
6
- use tokio:: sync:: Mutex ;
6
+ use tokio:: { select , sync:: watch :: Receiver } ;
7
7
8
8
use super :: { CertifierService , SignatureConsumer } ;
9
9
@@ -15,48 +15,37 @@ pub trait SignatureProcessor: Sync + Send {
15
15
async fn process_signatures ( & self ) -> StdResult < ( ) > ;
16
16
17
17
/// Starts the processor, which will run indefinitely, processing signatures as they arrive.
18
- async fn run ( & self ) -> StdResult < ( ) > {
19
- loop {
20
- self . process_signatures ( ) . await ?;
21
- }
22
- }
23
-
24
- /// Stops the processor. This method should be called to gracefully shut down the processor.
25
- async fn stop ( & self ) -> StdResult < ( ) > ;
18
+ async fn run ( & self ) -> StdResult < ( ) > ;
26
19
}
27
20
28
21
/// A sequential signature processor receives messages and processes them sequentially
29
22
pub struct SequentialSignatureProcessor {
30
23
consumer : Arc < dyn SignatureConsumer > ,
31
24
certifier : Arc < dyn CertifierService > ,
25
+ stop_rx : Receiver < ( ) > ,
32
26
logger : Logger ,
33
- stop : Mutex < bool > ,
34
27
}
35
28
36
29
impl SequentialSignatureProcessor {
37
30
/// Creates a new `SignatureProcessor` instance.
38
31
pub fn new (
39
32
consumer : Arc < dyn SignatureConsumer > ,
40
33
certifier : Arc < dyn CertifierService > ,
34
+ stop_rx : Receiver < ( ) > ,
41
35
logger : Logger ,
42
36
) -> Self {
43
37
Self {
44
38
consumer,
45
39
certifier,
40
+ stop_rx,
46
41
logger : logger. new_with_component_name :: < Self > ( ) ,
47
- stop : Mutex :: new ( false ) ,
48
42
}
49
43
}
50
44
}
51
45
52
46
#[ async_trait:: async_trait]
53
47
impl SignatureProcessor for SequentialSignatureProcessor {
54
48
async fn process_signatures ( & self ) -> StdResult < ( ) > {
55
- if * self . stop . lock ( ) . await {
56
- warn ! ( self . logger, "Stopped signature processor" ) ;
57
- return Ok ( ( ) ) ;
58
- }
59
-
60
49
match self . consumer . get_signatures ( ) . await {
61
50
Ok ( signatures) => {
62
51
for ( signature, signed_entity_type) in signatures {
@@ -77,11 +66,18 @@ impl SignatureProcessor for SequentialSignatureProcessor {
77
66
Ok ( ( ) )
78
67
}
79
68
80
- async fn stop ( & self ) -> StdResult < ( ) > {
81
- warn ! ( self . logger, "Stopping signature processor..." ) ;
82
- * self . stop . lock ( ) . await = true ;
69
+ async fn run ( & self ) -> StdResult < ( ) > {
70
+ loop {
71
+ let mut stop_rx = self . stop_rx . clone ( ) ;
72
+ select ! {
73
+ _ = stop_rx. changed( ) => {
74
+ warn!( self . logger, "Stopping signature processor..." ) ;
83
75
84
- Ok ( ( ) )
76
+ return Ok ( ( ) ) ;
77
+ }
78
+ _ = self . process_signatures( ) => { }
79
+ }
80
+ }
85
81
}
86
82
}
87
83
@@ -93,10 +89,16 @@ mod tests {
93
89
test_utils:: fake_data,
94
90
} ;
95
91
use mockall:: predicate:: eq;
96
- use tokio:: time:: { sleep, Duration } ;
92
+ use tokio:: {
93
+ sync:: watch:: channel,
94
+ time:: { sleep, Duration } ,
95
+ } ;
97
96
98
97
use crate :: {
99
- services:: { MockCertifierService , MockSignatureConsumer , SignatureRegistrationStatus } ,
98
+ services:: {
99
+ FakeSignatureConsumer , MockCertifierService , MockSignatureConsumer ,
100
+ SignatureRegistrationStatus ,
101
+ } ,
100
102
test_tools:: TestLogger ,
101
103
} ;
102
104
@@ -145,9 +147,11 @@ mod tests {
145
147
146
148
mock_certifier
147
149
} ;
150
+ let ( _stop_tx, stop_rx) = channel ( ( ) ) ;
148
151
let processor = SequentialSignatureProcessor :: new (
149
152
Arc :: new ( mock_consumer) ,
150
153
Arc :: new ( mock_certifier) ,
154
+ stop_rx,
151
155
logger,
152
156
) ;
153
157
@@ -160,26 +164,13 @@ mod tests {
160
164
#[ tokio:: test]
161
165
async fn processor_run_succeeds ( ) {
162
166
let logger = TestLogger :: stdout ( ) ;
163
- let mock_consumer = {
164
- let mut mock_consumer = MockSignatureConsumer :: new ( ) ;
165
- mock_consumer
166
- . expect_get_signatures ( )
167
- . returning ( || Err ( anyhow ! ( "Error consuming signatures" ) ) )
168
- . times ( 1 ) ;
169
- mock_consumer
170
- . expect_get_signatures ( )
171
- . returning ( || {
172
- Ok ( vec ! [ (
173
- fake_data:: single_signature( vec![ 1 , 2 , 3 ] ) ,
174
- SignedEntityType :: MithrilStakeDistribution ( Epoch ( 1 ) ) ,
175
- ) ] )
176
- } )
177
- . times ( 1 ) ;
178
- mock_consumer
179
- . expect_get_signatures ( )
180
- . returning ( || Ok ( vec ! [ ] ) ) ;
181
- mock_consumer
182
- } ;
167
+ let fake_consumer = FakeSignatureConsumer :: new ( vec ! [
168
+ Err ( anyhow!( "Error consuming signatures" ) ) ,
169
+ Ok ( vec![ (
170
+ fake_data:: single_signature( vec![ 1 , 2 , 3 ] ) ,
171
+ SignedEntityType :: MithrilStakeDistribution ( Epoch ( 1 ) ) ,
172
+ ) ] ) ,
173
+ ] ) ;
183
174
let mock_certifier = {
184
175
let mut mock_certifier = MockCertifierService :: new ( ) ;
185
176
mock_certifier
@@ -193,16 +184,19 @@ mod tests {
193
184
194
185
mock_certifier
195
186
} ;
187
+ let ( stop_tx, stop_rx) = channel ( ( ) ) ;
196
188
let processor = SequentialSignatureProcessor :: new (
197
- Arc :: new ( mock_consumer ) ,
189
+ Arc :: new ( fake_consumer ) ,
198
190
Arc :: new ( mock_certifier) ,
191
+ stop_rx,
199
192
logger,
200
193
) ;
201
194
202
195
tokio:: select!(
203
- _res = processor. run( ) => { } ,
196
+ _res = processor. run( ) => { } ,
204
197
_res = sleep( Duration :: from_millis( 10 ) ) => {
205
- processor. stop( ) . await . expect( "Failed to stop processor" ) ;
198
+ println!( "Stopping signature processor..." ) ;
199
+ stop_tx. send( ( ) ) . unwrap( ) ;
206
200
} ,
207
201
) ;
208
202
}
0 commit comments