14
14
* See the License for the specific language governing permissions and
15
15
* limitations under the License.
16
16
*/
17
+ use std:: any:: Any ;
17
18
use std:: collections:: HashMap ;
19
+ use std:: collections:: HashSet ;
18
20
19
21
use crate :: latency:: latency_fault_tolerance:: LatencyFaultTolerance ;
20
22
use crate :: latency:: resolver:: Resolver ;
21
23
use crate :: latency:: service_detector:: ServiceDetector ;
22
24
23
- pub struct LatencyFaultToleranceImpl {
24
- fault_item_table : parking_lot :: Mutex < HashMap < String , FaultItem > > ,
25
- detect_timeout : i32 ,
26
- detect_interval : i32 ,
25
+ pub struct LatencyFaultToleranceImpl < R , S > {
26
+ fault_item_table : tokio :: sync :: Mutex < HashMap < String , FaultItem > > ,
27
+ detect_timeout : u32 ,
28
+ detect_interval : u32 ,
27
29
which_item_worst : ThreadLocalIndex ,
28
30
start_detector_enable : AtomicBool ,
29
- resolver : Option < Box < dyn Resolver > > ,
30
- service_detector : Option < Box < dyn ServiceDetector > > ,
31
+ resolver : Option < R > ,
32
+ service_detector : Option < S > ,
31
33
}
32
34
33
- impl LatencyFaultToleranceImpl {
35
+ impl < R , S > LatencyFaultToleranceImpl < R , S > {
34
36
pub fn new ( /*fetcher: impl Resolver, service_detector: impl ServiceDetector*/ ) -> Self {
35
37
Self {
36
38
resolver : None ,
@@ -44,15 +46,19 @@ impl LatencyFaultToleranceImpl {
44
46
}
45
47
}
46
48
47
- impl LatencyFaultTolerance < String > for LatencyFaultToleranceImpl {
48
- fn update_fault_item (
49
+ impl < R , S > LatencyFaultTolerance < String , R , S > for LatencyFaultToleranceImpl < R , S >
50
+ where
51
+ R : Resolver ,
52
+ S : ServiceDetector ,
53
+ {
54
+ async fn update_fault_item (
49
55
& mut self ,
50
56
name : String ,
51
57
current_latency : u64 ,
52
58
not_available_duration : u64 ,
53
59
reachable : bool ,
54
60
) {
55
- let mut table = self . fault_item_table . lock ( ) ;
61
+ let mut table = self . fault_item_table . lock ( ) . await ;
56
62
let fault_item = table
57
63
. entry ( name. clone ( ) )
58
64
. or_insert_with ( || FaultItem :: new ( name. clone ( ) ) ) ;
@@ -69,42 +75,120 @@ impl LatencyFaultTolerance<String> for LatencyFaultToleranceImpl {
69
75
}
70
76
}
71
77
72
- fn is_available ( & self , name : & String ) -> bool {
73
- let fault_item_table = self . fault_item_table . lock ( ) ;
78
+ async fn is_available ( & self , name : & String ) -> bool {
79
+ let fault_item_table = self . fault_item_table . lock ( ) . await ;
74
80
if let Some ( fault_item) = fault_item_table. get ( name) {
75
81
return fault_item. is_available ( ) ;
76
82
}
77
83
true
78
84
}
79
85
80
- fn is_reachable ( & self , name : & String ) -> bool {
81
- todo ! ( )
86
+ async fn is_reachable ( & self , name : & String ) -> bool {
87
+ let fault_item_table = self . fault_item_table . lock ( ) . await ;
88
+ if let Some ( fault_item) = fault_item_table. get ( name) {
89
+ return fault_item. is_reachable ( ) ;
90
+ }
91
+ true
82
92
}
83
93
84
- fn remove ( & mut self , name : & String ) {
85
- todo ! ( )
94
+ async fn remove ( & mut self , name : & String ) {
95
+ self . fault_item_table . lock ( ) . await . remove ( name ) ;
86
96
}
87
97
88
- fn pick_one_at_least ( & self ) -> String {
89
- todo ! ( )
98
+ async fn pick_one_at_least ( & self ) -> Option < String > {
99
+ let fault_item_table = self . fault_item_table . lock ( ) . await ;
100
+ let mut tmp_list: Vec < _ > = fault_item_table. values ( ) . collect ( ) ;
101
+
102
+ if !tmp_list. is_empty ( ) {
103
+ use rand:: seq:: SliceRandom ;
104
+ let mut rng = rand:: thread_rng ( ) ;
105
+ tmp_list. shuffle ( & mut rng) ;
106
+ for fault_item in tmp_list {
107
+ if fault_item
108
+ . reachable_flag
109
+ . load ( std:: sync:: atomic:: Ordering :: Acquire )
110
+ {
111
+ return Some ( fault_item. name . clone ( ) ) ;
112
+ }
113
+ }
114
+ }
115
+ None
90
116
}
91
117
92
- fn start_detector ( & self ) {
93
- todo ! ( )
118
+ fn start_detector ( this : ArcRefCellWrapper < Self > ) {
119
+ tokio:: spawn ( async move {
120
+ loop {
121
+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 3 ) ) . await ;
122
+ if !this
123
+ . start_detector_enable
124
+ . load ( std:: sync:: atomic:: Ordering :: Relaxed )
125
+ {
126
+ continue ;
127
+ }
128
+
129
+ this. detect_by_one_round ( ) . await ;
130
+ }
131
+ } ) ;
94
132
}
95
133
96
134
fn shutdown ( & self ) { }
97
135
98
- fn detect_by_one_round ( & self ) {
99
- todo ! ( )
136
+ async fn detect_by_one_round ( & self ) {
137
+ let mut fault_item_table = self . fault_item_table . lock ( ) . await ;
138
+ let mut remove_set = HashSet :: new ( ) ;
139
+ for ( name, fault_item) in fault_item_table. iter ( ) {
140
+ if get_current_millis ( ) as i64
141
+ - ( fault_item
142
+ . check_stamp
143
+ . load ( std:: sync:: atomic:: Ordering :: Relaxed ) as i64 )
144
+ < 0
145
+ {
146
+ continue ;
147
+ }
148
+ fault_item. check_stamp . store (
149
+ get_current_millis ( ) + self . detect_interval as u64 ,
150
+ std:: sync:: atomic:: Ordering :: Release ,
151
+ ) ;
152
+ let broker_addr = self
153
+ . resolver
154
+ . as_ref ( )
155
+ . unwrap ( )
156
+ . resolve ( fault_item. name . as_str ( ) )
157
+ . await ;
158
+ if broker_addr. is_none ( ) {
159
+ remove_set. insert ( name. clone ( ) ) ;
160
+ continue ;
161
+ }
162
+ if self . service_detector . is_none ( ) {
163
+ continue ;
164
+ }
165
+ let service_ok = self
166
+ . service_detector
167
+ . as_ref ( )
168
+ . unwrap ( )
169
+ . detect ( broker_addr. unwrap ( ) . as_str ( ) , self . detect_timeout as u64 ) ;
170
+ if service_ok
171
+ && fault_item
172
+ . reachable_flag
173
+ . load ( std:: sync:: atomic:: Ordering :: Acquire )
174
+ {
175
+ info ! ( "{} is reachable now, then it can be used." , name) ;
176
+ fault_item
177
+ . reachable_flag
178
+ . store ( true , std:: sync:: atomic:: Ordering :: Release ) ;
179
+ }
180
+ }
181
+ for name in remove_set {
182
+ fault_item_table. remove ( & name) ;
183
+ }
100
184
}
101
185
102
186
fn set_detect_timeout ( & mut self , detect_timeout : u32 ) {
103
- todo ! ( )
187
+ self . detect_timeout = detect_timeout ;
104
188
}
105
189
106
190
fn set_detect_interval ( & mut self , detect_interval : u32 ) {
107
- todo ! ( )
191
+ self . detect_interval = detect_interval ;
108
192
}
109
193
110
194
fn set_start_detector_enable ( & mut self , start_detector_enable : bool ) {
@@ -113,22 +197,32 @@ impl LatencyFaultTolerance<String> for LatencyFaultToleranceImpl {
113
197
}
114
198
115
199
fn is_start_detector_enable ( & self ) -> bool {
116
- todo ! ( )
200
+ self . start_detector_enable
201
+ . load ( std:: sync:: atomic:: Ordering :: Acquire )
117
202
}
118
203
119
- fn set_resolver ( & mut self , resolver : Box < dyn Resolver > ) {
204
+ fn set_resolver ( & mut self , resolver : R ) {
120
205
self . resolver = Some ( resolver) ;
121
206
}
122
207
123
- fn set_service_detector ( & mut self , service_detector : Box < dyn ServiceDetector > ) {
208
+ fn set_service_detector ( & mut self , service_detector : S ) {
124
209
self . service_detector = Some ( service_detector) ;
125
210
}
211
+
212
+ fn as_any ( & self ) -> & dyn Any {
213
+ self
214
+ }
215
+
216
+ fn as_any_mut ( & mut self ) -> & mut dyn Any {
217
+ self
218
+ }
126
219
}
127
220
128
221
use std:: cmp:: Ordering ;
129
222
use std:: hash:: Hash ;
130
223
use std:: sync:: atomic:: AtomicBool ;
131
224
225
+ use rocketmq_common:: ArcRefCellWrapper ;
132
226
use rocketmq_common:: TimeUtils :: get_current_millis;
133
227
use tracing:: info;
134
228
@@ -166,7 +260,7 @@ impl FaultItem {
166
260
now + not_available_duration,
167
261
std:: sync:: atomic:: Ordering :: Relaxed ,
168
262
) ;
169
- println ! (
263
+ info ! (
170
264
"{} will be isolated for {} ms." ,
171
265
self . name, not_available_duration
172
266
) ;
0 commit comments