@@ -31,6 +31,7 @@ import (
31
31
var (
32
32
emptyDoc = []byte {5 , 0 , 0 , 0 , 0 }
33
33
errorCommandNotFound int32 = 59
34
+ errorLockTimeout int32 = 24
34
35
killAllSessionsErrorCodes = map [int32 ]struct {}{
35
36
errorInterrupted : {},
36
37
errorCommandNotFound : {}, // the killAllSessions command does not exist on server versions < 3.6
@@ -1406,12 +1407,38 @@ func executeAdminCommand(mt *mtest.T, op *operation) {
1406
1407
_ = client .Disconnect (mtest .Background )
1407
1408
}()
1408
1409
1409
- db := client .Database ("admin" )
1410
1410
cmd := op .Arguments .Lookup ("command" ).Document ()
1411
+ if op .CommandName == "replSetStepDown" {
1412
+ // replSetStepDown can fail with transient errors, so we use executeAdminCommandWithRetry to handle them and
1413
+ // retry until a timeout is hit.
1414
+ executeAdminCommandWithRetry (mt , client , cmd )
1415
+ return
1416
+ }
1417
+
1418
+ db := client .Database ("admin" )
1411
1419
err = db .RunCommand (mtest .Background , cmd ).Err ()
1412
1420
assert .Nil (mt , err , "RunCommand error for command %q: %v" , op .CommandName , err )
1413
1421
}
1414
1422
1423
+ func executeAdminCommandWithRetry (mt * mtest.T , client * mongo.Client , cmd interface {}, opts ... * options.RunCmdOptions ) {
1424
+ mt .Helper ()
1425
+
1426
+ ctx , cancel := context .WithTimeout (mtest .Background , 10 * time .Second )
1427
+ defer cancel ()
1428
+
1429
+ for {
1430
+ err := client .Database ("admin" ).RunCommand (ctx , cmd , opts ... ).Err ()
1431
+ if err == nil {
1432
+ return
1433
+ }
1434
+
1435
+ if ce , ok := err .(mongo.CommandError ); ok && ce .Code == errorLockTimeout {
1436
+ continue
1437
+ }
1438
+ mt .Fatalf ("error executing command: %v" , err )
1439
+ }
1440
+ }
1441
+
1415
1442
// verification function to use for all count operations
1416
1443
func verifyCountResult (mt * mtest.T , actualResult int64 , expectedResult interface {}) {
1417
1444
mt .Helper ()
0 commit comments