3232import com .mongodb .event .ConnectionCheckedOutEvent ;
3333import com .mongodb .event .ConnectionPoolClearedEvent ;
3434import com .mongodb .internal .connection .ServerAddressHelper ;
35+ import com .mongodb .internal .connection .TestClusterListener ;
3536import com .mongodb .internal .connection .TestCommandListener ;
3637import com .mongodb .internal .connection .TestConnectionPoolListener ;
3738import com .mongodb .internal .event .ConfigureFailPointCommandListener ;
4243import org .junit .jupiter .api .Disabled ;
4344import org .junit .jupiter .api .Test ;
4445
46+ import java .time .Duration ;
4547import java .util .HashSet ;
4648import java .util .List ;
4749import java .util .Set ;
4850import java .util .concurrent .ExecutorService ;
4951import java .util .concurrent .Executors ;
5052import java .util .concurrent .Future ;
5153import java .util .concurrent .TimeUnit ;
54+ import java .util .concurrent .TimeoutException ;
5255import java .util .function .Predicate ;
5356import java .util .stream .Collectors ;
5457
@@ -224,15 +227,16 @@ public static void originalErrorMustBePropagatedIfNoWritesPerformed(
224227 * 4. Test that in a sharded cluster writes are retried on a different mongos when one is available</a>.
225228 */
226229 @ Test
227- void retriesOnDifferentMongosWhenAvailable () {
230+ void retriesOnDifferentMongosWhenAvailable () throws InterruptedException , TimeoutException {
228231 retriesOnDifferentMongosWhenAvailable (MongoClients ::create ,
229232 mongoCollection -> mongoCollection .insertOne (new Document ()), "insert" , true );
230233 }
231234
232235 @ SuppressWarnings ("try" )
233236 public static <R > void retriesOnDifferentMongosWhenAvailable (
234237 final Function <MongoClientSettings , MongoClient > clientCreator ,
235- final Function <MongoCollection <Document >, R > operation , final String expectedCommandName , final boolean write ) {
238+ final Function <MongoCollection <Document >, R > operation , final String expectedCommandName , final boolean write )
239+ throws InterruptedException , TimeoutException {
236240 if (write ) {
237241 assumeTrue (serverVersionAtLeast (4 , 4 ));
238242 }
@@ -253,15 +257,24 @@ public static <R> void retriesOnDifferentMongosWhenAvailable(
253257 + " }\n "
254258 + "}\n " );
255259 TestCommandListener commandListener = new TestCommandListener (singletonList ("commandFailedEvent" ), emptyList ());
260+ TestClusterListener clusterListener = new TestClusterListener ();
256261 try (FailPoint s0FailPoint = FailPoint .enable (configureFailPoint , s0Address );
257262 FailPoint s1FailPoint = FailPoint .enable (configureFailPoint , s1Address );
258263 MongoClient client = clientCreator .apply (getMultiMongosMongoClientSettingsBuilder ()
259264 .retryReads (true )
260265 .retryWrites (true )
261266 .addCommandListener (commandListener )
262267 // explicitly specify only s0 and s1, in case `getMultiMongosMongoClientSettingsBuilder` has more
263- .applyToClusterSettings (builder -> builder .hosts (asList (s0Address , s1Address )))
268+ .applyToClusterSettings (builder -> builder
269+ .hosts (asList (s0Address , s1Address ))
270+ .addClusterListener (clusterListener ))
264271 .build ())) {
272+ // We need both mongos servers to be discovered (not UNKNOWN) before running the deprioritization test.
273+ // When the first mongos is deprioritized on retry, the selector falls back to the second mongos.
274+ // If the second mongos is still UNKNOWN at that point, the non-deprioritized pass yields no selectable servers,
275+ // causing the deprioritized mongos to be selected again.
276+ clusterListener .waitForAllServersDiscovered (Duration .ofSeconds (10 ));
277+
265278 MongoCollection <Document > collection = dropAndGetCollection ("retriesOnDifferentMongosWhenAvailable" , client );
266279 commandListener .reset ();
267280 assertThrows (MongoServerException .class , () -> operation .apply (collection ));
0 commit comments