@@ -14,7 +14,17 @@ use crate::{
14
14
runtime,
15
15
sdam:: ServerInfo ,
16
16
selection_criteria:: SelectionCriteria ,
17
- test:: { log_uncaptured, EventClient , TestClient , CLIENT_OPTIONS , LOCK } ,
17
+ test:: {
18
+ log_uncaptured,
19
+ Event ,
20
+ EventClient ,
21
+ EventHandler ,
22
+ SdamEvent ,
23
+ TestClient ,
24
+ CLIENT_OPTIONS ,
25
+ LOCK ,
26
+ } ,
27
+ Client ,
18
28
Collection ,
19
29
} ;
20
30
@@ -238,19 +248,22 @@ async fn pool_is_lifo() {
238
248
async fn cluster_time_in_commands ( ) {
239
249
let _guard: RwLockReadGuard < ( ) > = LOCK . run_concurrently ( ) . await ;
240
250
241
- let client = TestClient :: new ( ) . await ;
242
- if client. is_standalone ( ) {
251
+ let test_client = TestClient :: new ( ) . await ;
252
+ if test_client. is_standalone ( ) {
253
+ log_uncaptured ( "skipping cluster_time_in_commands test due to standalone topology" ) ;
243
254
return ;
244
255
}
245
256
246
- async fn cluster_time_test < F , G , R > ( command_name : & str , operation : F )
247
- where
248
- F : Fn ( EventClient ) -> G ,
257
+ async fn cluster_time_test < F , G , R > (
258
+ command_name : & str ,
259
+ client : & Client ,
260
+ event_handler : & EventHandler ,
261
+ operation : F ,
262
+ ) where
263
+ F : Fn ( Client ) -> G ,
249
264
G : Future < Output = Result < R > > ,
250
265
{
251
- let mut options = CLIENT_OPTIONS . get ( ) . await . clone ( ) ;
252
- options. heartbeat_freq = Some ( Duration :: from_secs ( 1000 ) ) ;
253
- let client = EventClient :: with_options ( options) . await ;
266
+ let mut subscriber = event_handler. subscribe ( ) ;
254
267
255
268
operation ( client. clone ( ) )
256
269
. await
@@ -260,16 +273,31 @@ async fn cluster_time_in_commands() {
260
273
. await
261
274
. expect ( "operation should succeed" ) ;
262
275
263
- let ( first_command_started, first_command_succeeded) =
264
- client. get_successful_command_execution ( command_name) ;
276
+ let ( first_command_started, first_command_succeeded) = subscriber
277
+ . wait_for_successful_command_execution ( Duration :: from_secs ( 5 ) , command_name)
278
+ . await
279
+ . unwrap_or_else ( || {
280
+ panic ! (
281
+ "did not see command started and succeeded events for {}" ,
282
+ command_name
283
+ )
284
+ } ) ;
265
285
266
286
assert ! ( first_command_started. command. get( "$clusterTime" ) . is_some( ) ) ;
267
287
let response_cluster_time = first_command_succeeded
268
288
. reply
269
289
. get ( "$clusterTime" )
270
290
. expect ( "should get cluster time from command response" ) ;
271
291
272
- let ( second_command_started, _) = client. get_successful_command_execution ( command_name) ;
292
+ let ( second_command_started, _) = subscriber
293
+ . wait_for_successful_command_execution ( Duration :: from_secs ( 5 ) , command_name)
294
+ . await
295
+ . unwrap_or_else ( || {
296
+ panic ! (
297
+ "did not see command started and succeeded events for {}" ,
298
+ command_name
299
+ )
300
+ } ) ;
273
301
274
302
assert_eq ! (
275
303
response_cluster_time,
@@ -282,24 +310,73 @@ async fn cluster_time_in_commands() {
282
310
) ;
283
311
}
284
312
285
- cluster_time_test ( "ping" , |client| async move {
313
+ let handler = Arc :: new ( EventHandler :: new ( ) ) ;
314
+ let mut options = CLIENT_OPTIONS . get ( ) . await . clone ( ) ;
315
+ options. heartbeat_freq = Some ( Duration :: from_secs ( 1000 ) ) ;
316
+ options. command_event_handler = Some ( handler. clone ( ) ) ;
317
+ options. sdam_event_handler = Some ( handler. clone ( ) ) ;
318
+
319
+ // Ensure we only connect to one server so the monitor checks from other servers
320
+ // don't affect the TopologyDescription's clusterTime value between commands.
321
+ if options. load_balanced != Some ( true ) {
322
+ options. direct_connection = Some ( true ) ;
323
+
324
+ // Since we need to run an insert below, ensure the single host is a primary
325
+ // if we're connected to a replica set.
326
+ if let Some ( primary) = test_client. primary ( ) {
327
+ options. hosts = vec ! [ primary] ;
328
+ } else {
329
+ options. hosts . drain ( 1 ..) ;
330
+ }
331
+ }
332
+
333
+ let mut subscriber = handler. subscribe ( ) ;
334
+
335
+ let client = Client :: with_options ( options) . unwrap ( ) ;
336
+
337
+ // Wait for initial monitor check to complete and discover the server.
338
+ subscriber
339
+ . wait_for_event ( Duration :: from_secs ( 5 ) , |event| match event {
340
+ Event :: Sdam ( SdamEvent :: ServerDescriptionChanged ( e) ) => {
341
+ !e. previous_description . server_type ( ) . is_available ( )
342
+ && e. new_description . server_type ( ) . is_available ( )
343
+ }
344
+ _ => false ,
345
+ } )
346
+ . await
347
+ . expect ( "server should be discovered" ) ;
348
+
349
+ // LoadBalanced topologies don't have monitors, so the client needs to get a clusterTime from
350
+ // a command invocation.
351
+ client
352
+ . database ( "admin" )
353
+ . run_command ( doc ! { "ping" : 1 } , None )
354
+ . await
355
+ . unwrap ( ) ;
356
+
357
+ cluster_time_test ( "ping" , & client, handler. as_ref ( ) , |client| async move {
286
358
client
287
359
. database ( function_name ! ( ) )
288
360
. run_command ( doc ! { "ping" : 1 } , None )
289
361
. await
290
362
} )
291
363
. await ;
292
364
293
- cluster_time_test ( "aggregate" , |client| async move {
294
- client
295
- . database ( function_name ! ( ) )
296
- . collection :: < Document > ( function_name ! ( ) )
297
- . aggregate ( vec ! [ doc! { "$match" : { "x" : 1 } } ] , None )
298
- . await
299
- } )
365
+ cluster_time_test (
366
+ "aggregate" ,
367
+ & client,
368
+ handler. as_ref ( ) ,
369
+ |client| async move {
370
+ client
371
+ . database ( function_name ! ( ) )
372
+ . collection :: < Document > ( function_name ! ( ) )
373
+ . aggregate ( vec ! [ doc! { "$match" : { "x" : 1 } } ] , None )
374
+ . await
375
+ } ,
376
+ )
300
377
. await ;
301
378
302
- cluster_time_test ( "find" , |client| async move {
379
+ cluster_time_test ( "find" , & client , handler . as_ref ( ) , |client| async move {
303
380
client
304
381
. database ( function_name ! ( ) )
305
382
. collection :: < Document > ( function_name ! ( ) )
@@ -308,7 +385,7 @@ async fn cluster_time_in_commands() {
308
385
} )
309
386
. await ;
310
387
311
- cluster_time_test ( "insert" , |client| async move {
388
+ cluster_time_test ( "insert" , & client , handler . as_ref ( ) , |client| async move {
312
389
client
313
390
. database ( function_name ! ( ) )
314
391
. collection :: < Document > ( function_name ! ( ) )
0 commit comments