@@ -2,6 +2,7 @@ use glide_core::connection_request::{ConnectionRequest, NodeAddress, TlsMode};
22use glide_core:: errors:: RequestErrorType ;
33use glide_core:: request_type:: RequestType ;
44use glide_ffi:: * ;
5+ use lazy_static:: lazy_static;
56use protobuf:: Message ;
67use rstest:: rstest;
78use std:: collections:: HashMap ;
@@ -10,26 +11,35 @@ use std::net::TcpListener;
1011use std:: process:: { Child , Command } ;
1112use std:: sync:: {
1213 atomic:: { AtomicUsize , Ordering } ,
13- Arc ,
14+ Arc , RwLock ,
1415} ;
15- use std:: sync:: { LazyLock , Mutex } ;
1616use tokio:: runtime:: Runtime ;
1717use tokio:: time:: { sleep, Duration } ;
1818
19- static ASYNC_SUCCESS_COUNTER : LazyLock < Arc < AtomicUsize > > =
20- LazyLock :: new ( || Arc :: new ( AtomicUsize :: new ( 0 ) ) ) ;
21- static ASYNC_FAILURE_COUNTER : LazyLock < Arc < AtomicUsize > > =
22- LazyLock :: new ( || Arc :: new ( AtomicUsize :: new ( 0 ) ) ) ;
23- type StringResultMap = LazyLock < Mutex < HashMap < usize , Result < String , ( String , RequestErrorType ) > > > > ;
24- static ASYNC_RESULTS_MAP : StringResultMap = LazyLock :: new ( || Mutex :: new ( HashMap :: new ( ) ) ) ;
19+ pub ( crate ) struct AsyncMetrics {
20+ pub success_count : AtomicUsize ,
21+ pub failure_count : AtomicUsize ,
22+ pub results : HashMap < usize , Result < String , ( String , RequestErrorType ) > > ,
23+ }
24+
25+ lazy_static ! {
26+ static ref ASYNC_METRICS : Arc <RwLock <AsyncMetrics >> = Arc :: new( RwLock :: new( AsyncMetrics {
27+ success_count: AtomicUsize :: new( 0 ) ,
28+ failure_count: AtomicUsize :: new( 0 ) ,
29+ results: HashMap :: new( ) ,
30+ } ) ) ;
31+ }
32+
33+ const ASYNC_WRITE_LOCK_ERR : & str = "Failed to aquire ASYNC_METRICS the write lock" ;
34+ const ASYNC_READ_LOCK_ERR : & str = "Failed to aquire ASYNC_METRICS the write lock" ;
2535
2636/// Success callback function for String responses for the async client
2737extern "C" fn string_success_callback ( index : usize , response_ptr : * const CommandResponse ) {
28- let mut map = ASYNC_RESULTS_MAP
29- . lock ( )
30- . expect ( "Failed to aquire the results' lock" ) ;
31- map . insert ( index, Ok ( parse_string_res ( response_ptr) ) ) ;
32- ASYNC_SUCCESS_COUNTER . fetch_add ( 1 , Ordering :: SeqCst ) ;
38+ let mut metrics = ASYNC_METRICS . write ( ) . expect ( ASYNC_WRITE_LOCK_ERR ) ;
39+ metrics
40+ . results
41+ . insert ( index, Ok ( parse_string_res ( response_ptr) ) ) ;
42+ metrics . success_count . fetch_add ( 1 , Ordering :: SeqCst ) ;
3343}
3444
3545/// Failure callback function for the async client
@@ -38,11 +48,11 @@ extern "C" fn failure_callback(
3848 err_msg_ptr : * const c_char ,
3949 error_type : RequestErrorType ,
4050) {
41- let mut map = ASYNC_RESULTS_MAP
42- . lock ( )
43- . expect ( "Failed to aquire the results' lock" ) ;
44- map . insert ( index, Err ( ( parse_error_msg ( err_msg_ptr) , error_type) ) ) ;
45- ASYNC_FAILURE_COUNTER . fetch_add ( 1 , Ordering :: SeqCst ) ;
51+ let mut metrics = ASYNC_METRICS . write ( ) . expect ( ASYNC_WRITE_LOCK_ERR ) ;
52+ metrics
53+ . results
54+ . insert ( index, Err ( ( parse_error_msg ( err_msg_ptr) , error_type) ) ) ;
55+ metrics . failure_count . fetch_add ( 1 , Ordering :: SeqCst ) ;
4656}
4757
4858fn parse_string_res ( response_ptr : * const CommandResponse ) -> String {
@@ -169,7 +179,8 @@ fn execute_command(
169179 )
170180 } ;
171181 if command_res_ptr. is_null ( ) {
172- // Async client is being used, let the async callback to be called
182+ // If the returned CommandResult pointer is a null it means that the Async client is being used.
183+ // We shall let the async callback to be called.
173184 let rt = Runtime :: new ( ) . unwrap ( ) ;
174185 rt. block_on ( async {
175186 sleep ( Duration :: from_millis ( 1 ) ) . await ;
@@ -186,8 +197,9 @@ fn get_sync_response(cmd_resp: *mut CommandResponse) -> String {
186197}
187198
188199fn get_async_response ( index : usize ) -> String {
189- let map = ASYNC_RESULTS_MAP . lock ( ) . unwrap ( ) ;
190- let result = map
200+ let metrics = ASYNC_METRICS . read ( ) . expect ( ASYNC_READ_LOCK_ERR ) ;
201+ let result = metrics
202+ . results
191203 . get ( & index)
192204 . expect ( "Couldn't find the relevant idx in the map" ) ;
193205 assert ! ( result. is_ok( ) ) ;
@@ -204,8 +216,9 @@ fn get_sync_error(command_error: *mut CommandError) -> (String, RequestErrorType
204216}
205217
206218fn get_async_error ( index : usize ) -> ( String , RequestErrorType ) {
207- let map = ASYNC_RESULTS_MAP . lock ( ) . unwrap ( ) ;
208- let result = map
219+ let metrics = ASYNC_METRICS . read ( ) . expect ( ASYNC_READ_LOCK_ERR ) ;
220+ let result = metrics
221+ . results
209222 . get ( & index)
210223 . expect ( "Couldn't find the relevant idx in the map" ) ;
211224 assert ! ( result. is_err( ) ) ;
@@ -214,7 +227,6 @@ fn get_async_error(index: usize) -> (String, RequestErrorType) {
214227}
215228
216229#[ rstest]
217- #[ serial_test:: serial]
218230fn test_ffi_client_command_execution ( #[ values( false , true ) ] async_client : bool ) {
219231 let server = Server :: new ( ) ;
220232 let connection_request_bytes = create_connection_request ( server. port ) ;
@@ -252,7 +264,8 @@ fn test_ffi_client_command_execution(#[values(false, true)] async_client: bool)
252264 ) ;
253265 let ping_res = if async_client {
254266 assert ! ( good_res. is_none( ) ) ; // result should be returned through callback
255- assert_eq ! ( ASYNC_SUCCESS_COUNTER . load( Ordering :: SeqCst ) , 1 ) ;
267+ let metrics = ASYNC_METRICS . read ( ) . expect ( ASYNC_READ_LOCK_ERR ) ;
268+ assert_eq ! ( metrics. success_count. load( Ordering :: SeqCst ) , 1 ) ;
256269 get_async_response ( good_cmd_idx)
257270 } else {
258271 assert ! ( good_res. is_some( ) ) ;
@@ -270,7 +283,8 @@ fn test_ffi_client_command_execution(#[values(false, true)] async_client: bool)
270283 ) ;
271284 let ( err_msg, err_type) = if async_client {
272285 assert ! ( bad_res. is_none( ) ) ; // result should be returned through callback
273- assert_eq ! ( ASYNC_FAILURE_COUNTER . load( Ordering :: SeqCst ) , 1 ) ;
286+ let metrics = ASYNC_METRICS . read ( ) . expect ( ASYNC_READ_LOCK_ERR ) ;
287+ assert_eq ! ( metrics. failure_count. load( Ordering :: SeqCst ) , 1 ) ;
274288 get_async_error ( bad_cmd_idx)
275289 } else {
276290 assert ! ( bad_res. is_some( ) ) ;
0 commit comments