Skip to content

Commit 0922a24

Browse files
authored
Improve selection criteria for srvMaxHosts (#1590)
Improve selection criteria for srvMaxHosts This PR improves the selection criteria for srvMaxHosts. The net result is that it will keep existing nodes, discard deleted nodes, and fill up to srvMaxHosts from a random shuffle of newly discovered nodes from the SRV response. It also updates the prose test to match the spec. JAVA-4400
1 parent 3cea0ab commit 0922a24

File tree

2 files changed

+29
-11
lines changed

2 files changed

+29
-11
lines changed

Diff for: driver-core/src/main/com/mongodb/internal/connection/DnsMultiServerCluster.java

+27-10
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
import com.mongodb.connection.ClusterId;
2222
import com.mongodb.connection.ClusterSettings;
2323
import com.mongodb.connection.ClusterType;
24+
import com.mongodb.connection.ServerDescription;
2425
import com.mongodb.lang.Nullable;
2526

2627
import java.util.ArrayList;
2728
import java.util.Collection;
2829
import java.util.Collections;
2930
import java.util.List;
3031
import java.util.concurrent.ThreadLocalRandom;
32+
import java.util.stream.Collectors;
3133

3234
import static com.mongodb.assertions.Assertions.assertNotNull;
3335

@@ -38,7 +40,6 @@ public final class DnsMultiServerCluster extends AbstractMultiServerCluster {
3840
private final DnsSrvRecordMonitor dnsSrvRecordMonitor;
3941
private volatile MongoException srvResolutionException;
4042

41-
4243
public DnsMultiServerCluster(final ClusterId clusterId, final ClusterSettings settings, final ClusterableServerFactory serverFactory,
4344
final DnsSrvRecordMonitorFactory dnsSrvRecordMonitorFactory) {
4445
super(clusterId, settings, serverFactory);
@@ -57,17 +58,33 @@ public void initialize(final Collection<ServerAddress> hosts) {
5758
}
5859
}
5960

60-
private Collection<ServerAddress> applySrvMaxHosts(final Collection<ServerAddress> hosts) {
61-
Collection<ServerAddress> newHosts = hosts;
61+
private Collection<ServerAddress> applySrvMaxHosts(final Collection<ServerAddress> latestSrvHosts) {
6262
Integer srvMaxHosts = getSettings().getSrvMaxHosts();
63-
if (srvMaxHosts != null && srvMaxHosts > 0) {
64-
if (srvMaxHosts < hosts.size()) {
65-
List<ServerAddress> newHostsList = new ArrayList<>(hosts);
66-
Collections.shuffle(newHostsList, ThreadLocalRandom.current());
67-
newHosts = newHostsList.subList(0, srvMaxHosts);
68-
}
63+
if (srvMaxHosts == null || srvMaxHosts <= 0 || latestSrvHosts.size() <= srvMaxHosts) {
64+
return new ArrayList<>(latestSrvHosts);
6965
}
70-
return newHosts;
66+
List<ServerAddress> activeHosts = getActivePriorHosts(latestSrvHosts);
67+
int numNewHostsToAdd = srvMaxHosts - activeHosts.size();
68+
activeHosts.addAll(addShuffledHosts(latestSrvHosts, activeHosts, numNewHostsToAdd));
69+
70+
return activeHosts;
71+
}
72+
73+
private List<ServerAddress> getActivePriorHosts(final Collection<ServerAddress> latestSrvHosts) {
74+
List<ServerAddress> priorHosts = DnsMultiServerCluster.this.getCurrentDescription().getServerDescriptions().stream()
75+
.map(ServerDescription::getAddress).collect(Collectors.toList());
76+
priorHosts.removeIf(host -> !latestSrvHosts.contains(host));
77+
78+
return priorHosts;
79+
}
80+
81+
private List<ServerAddress> addShuffledHosts(final Collection<ServerAddress> latestSrvHosts,
82+
final List<ServerAddress> activePriorHosts, final int numNewHostsToAdd) {
83+
List<ServerAddress> addedHosts = new ArrayList<>(latestSrvHosts);
84+
addedHosts.removeAll(activePriorHosts);
85+
Collections.shuffle(addedHosts, ThreadLocalRandom.current());
86+
87+
return addedHosts.subList(0, numNewHostsToAdd);
7188
}
7289

7390
@Override

Diff for: driver-core/src/test/unit/com/mongodb/internal/connection/SrvPollingProseTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,10 @@ public void shouldUseAllRecordsWhenSrvMaxHostsIsGreaterThanOrEqualToNumSrvRecord
160160
public void shouldUseSrvMaxHostsWhenSrvMaxHostsIsLessThanNumSrvRecords() {
161161
int srvMaxHosts = 2;
162162
List<String> updatedHosts = asList(firstHost, thirdHost, fourthHost);
163-
164163
initCluster(updatedHosts, srvMaxHosts);
164+
165165
assertEquals(srvMaxHosts, clusterHostsSet().size());
166+
assertTrue(updatedHosts.contains(firstHost));
166167
assertTrue(updatedHosts.containsAll(clusterHostsSet()));
167168
}
168169

0 commit comments

Comments
 (0)