Skip to content

Commit 2cf5f3d

Browse files
authored
ClusterSettings does not compute ClusterConnectionMode consistently (#1273)
`ClusterSettings` does not compute `ClusterConnectionMode` consistently JAVA-5088
1 parent 75c00da commit 2cf5f3d

File tree

2 files changed

+97
-24
lines changed

2 files changed

+97
-24
lines changed

driver-core/src/main/com/mongodb/connection/ClusterSettings.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -337,16 +337,16 @@ public Builder applyConnectionString(final ConnectionString connectionString) {
337337
if (srvServiceName != null) {
338338
srvServiceName(srvServiceName);
339339
}
340-
} else if ((directConnection != null && directConnection)
341-
|| (directConnection == null && connectionString.getHosts().size() == 1
342-
&& connectionString.getRequiredReplicaSetName() == null)) {
343-
mode(ClusterConnectionMode.SINGLE)
344-
.hosts(singletonList(createServerAddress(connectionString.getHosts().get(0))));
340+
} else if (directConnection != null) {
341+
mode(directConnection ? ClusterConnectionMode.SINGLE : ClusterConnectionMode.MULTIPLE);
342+
List<String> hosts = directConnection ? singletonList(connectionString.getHosts().get(0)) : connectionString.getHosts();
343+
hosts(hosts.stream().map(ServerAddressHelper::createServerAddress).collect(Collectors.toList()));
345344
} else {
345+
mode = null;
346346
List<ServerAddress> seedList = connectionString.getHosts().stream()
347347
.map(ServerAddressHelper::createServerAddress)
348348
.collect(Collectors.toList());
349-
mode(ClusterConnectionMode.MULTIPLE).hosts(seedList);
349+
hosts(seedList);
350350
}
351351
requiredReplicaSetName(connectionString.getRequiredReplicaSetName());
352352

@@ -612,26 +612,39 @@ private ClusterSettings(final Builder builder) {
612612
}
613613
}
614614

615-
if (builder.mode == ClusterConnectionMode.LOAD_BALANCED && builder.srvHost == null && builder.hosts.size() != 1) {
616-
throw new IllegalArgumentException("Multiple hosts cannot be specified when in load balancing mode");
617-
}
618-
619615
srvHost = builder.srvHost;
620616
srvMaxHosts = builder.srvMaxHosts;
621617
srvServiceName = builder.srvServiceName;
622618
hosts = builder.hosts;
623-
if (srvHost != null) {
624-
if (builder.mode == ClusterConnectionMode.SINGLE) {
625-
throw new IllegalArgumentException("An SRV host name was provided but the connection mode is not MULTIPLE");
619+
requiredReplicaSetName = builder.requiredReplicaSetName;
620+
if (builder.mode != null) {
621+
switch (builder.mode) {
622+
case SINGLE: {
623+
if (srvHost != null) {
624+
throw new IllegalArgumentException("An SRV host name was provided but the connection mode is not MULTIPLE");
625+
} else if (builder.hosts.size() > 1) {
626+
throw new IllegalArgumentException("Can not directly connect to more than one server");
627+
}
628+
break;
629+
}
630+
case LOAD_BALANCED: {
631+
if (builder.srvHost == null && builder.hosts.size() != 1) {
632+
throw new IllegalArgumentException("Multiple hosts cannot be specified when in load balancing mode");
633+
}
634+
break;
635+
}
636+
default:
626637
}
627-
mode = builder.mode != null ? builder.mode : ClusterConnectionMode.MULTIPLE;
638+
mode = builder.mode;
628639
} else {
629-
if (builder.mode == ClusterConnectionMode.SINGLE && builder.hosts.size() > 1) {
630-
throw new IllegalArgumentException("Can not directly connect to more than one server");
640+
if (srvHost != null) {
641+
mode = ClusterConnectionMode.MULTIPLE;
642+
} else {
643+
mode = hosts.size() == 1 && requiredReplicaSetName == null
644+
? ClusterConnectionMode.SINGLE
645+
: ClusterConnectionMode.MULTIPLE;
631646
}
632-
mode = builder.mode != null ? builder.mode : hosts.size() == 1 ? ClusterConnectionMode.SINGLE : ClusterConnectionMode.MULTIPLE;
633647
}
634-
requiredReplicaSetName = builder.requiredReplicaSetName;
635648
requiredClusterType = builder.requiredClusterType;
636649
localThresholdMS = builder.localThresholdMS;
637650
serverSelector = builder.serverSelector;

driver-core/src/test/unit/com/mongodb/connection/ClusterSettingsSpecification.groovy

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ class ClusterSettingsSpecification extends Specification {
136136
thrown(IllegalArgumentException)
137137
}
138138

139+
def 'when srvHost is specified and mode is SINGLE, should throw'() {
140+
when:
141+
ClusterSettings.builder()
142+
.srvHost('foo.bar.com')
143+
.mode(ClusterConnectionMode.SINGLE)
144+
.build()
145+
146+
then:
147+
thrown(IllegalArgumentException)
148+
}
149+
139150
def 'when srvHost is specified, should set mode to MULTIPLE if mode is not configured'() {
140151
when:
141152
def builder = ClusterSettings.builder()
@@ -181,8 +192,10 @@ class ClusterSettingsSpecification extends Specification {
181192

182193
def 'when connection string is applied to builder, all properties should be set'() {
183194
when:
184-
def settings = ClusterSettings.builder().applyConnectionString(new ConnectionString('mongodb://example.com:27018'))
185-
.build()
195+
def settings = ClusterSettings.builder()
196+
.requiredReplicaSetName("test")
197+
.applyConnectionString(new ConnectionString('mongodb://example.com:27018'))
198+
.build()
186199

187200
then:
188201
settings.mode == ClusterConnectionMode.SINGLE
@@ -192,6 +205,20 @@ class ClusterSettingsSpecification extends Specification {
192205
settings.srvMaxHosts == null
193206
settings.srvServiceName == 'mongodb'
194207

208+
when:
209+
settings = ClusterSettings.builder()
210+
.applyConnectionString(new ConnectionString('mongodb://example.com:27018'))
211+
.requiredReplicaSetName("test")
212+
.build()
213+
214+
then:
215+
settings.mode == ClusterConnectionMode.MULTIPLE
216+
settings.hosts == [new ServerAddress('example.com:27018')]
217+
settings.requiredClusterType == ClusterType.REPLICA_SET
218+
settings.requiredReplicaSetName == 'test'
219+
settings.srvMaxHosts == null
220+
settings.srvServiceName == 'mongodb'
221+
195222
when:
196223
settings = ClusterSettings.builder().applyConnectionString(new ConnectionString('mongodb+srv://test5.test.build.10gen.cc/')).build()
197224

@@ -216,8 +243,10 @@ class ClusterSettingsSpecification extends Specification {
216243
settings.srvServiceName == 'customname'
217244

218245
when:
219-
settings = ClusterSettings.builder().applyConnectionString(new ConnectionString('mongodb://example.com:27018/?replicaSet=test'))
220-
.build()
246+
settings = ClusterSettings.builder()
247+
.mode(ClusterConnectionMode.SINGLE)
248+
.applyConnectionString(new ConnectionString('mongodb://example.com:27018/?replicaSet=test'))
249+
.build()
221250

222251
then:
223252
settings.mode == ClusterConnectionMode.MULTIPLE
@@ -240,6 +269,19 @@ class ClusterSettingsSpecification extends Specification {
240269
settings.srvMaxHosts == null
241270
settings.srvServiceName == 'mongodb'
242271

272+
when:
273+
settings = ClusterSettings.builder()
274+
.applyConnectionString(new ConnectionString('mongodb://example.com:27017,example.com:27018/?directConnection=false'))
275+
.build()
276+
277+
then:
278+
settings.mode == ClusterConnectionMode.MULTIPLE
279+
settings.hosts == [new ServerAddress('example.com:27017'), new ServerAddress('example.com:27018')]
280+
settings.requiredClusterType == ClusterType.UNKNOWN
281+
settings.requiredReplicaSetName == null
282+
settings.srvMaxHosts == null
283+
settings.srvServiceName == 'mongodb'
284+
243285
when:
244286
settings = ClusterSettings.builder()
245287
.applyConnectionString(new ConnectionString('mongodb://example.com:27018/?directConnection=true'))
@@ -288,15 +330,16 @@ class ClusterSettingsSpecification extends Specification {
288330
settings.hosts == [new ServerAddress('example.com:27018')]
289331
}
290332

291-
def 'when cluster type is unknown and replica set name is specified, should set cluster type to ReplicaSet'() {
333+
def 'when cluster type is UNKNOWN and replica set name is set, should set cluster type to REPLICA_SET and mode to MULTIPLE'() {
292334
when:
293335
def settings = ClusterSettings.builder().hosts([new ServerAddress()]).requiredReplicaSetName('yeah').build()
294336

295337
then:
296338
ClusterType.REPLICA_SET == settings.requiredClusterType
339+
ClusterConnectionMode.MULTIPLE == settings.mode
297340
}
298341

299-
def 'connection mode should default to single if one host or multiple if more'() {
342+
def 'connection mode should default to SINGLE if replica set name is not set and one host, or MULTIPLE if more'() {
300343
when:
301344
def settings = ClusterSettings.builder().hosts([new ServerAddress()]).build()
302345

@@ -310,11 +353,28 @@ class ClusterSettingsSpecification extends Specification {
310353
settings.mode == ClusterConnectionMode.MULTIPLE
311354
}
312355

356+
def 'when a valid mode is specified, should use it'() {
357+
when:
358+
def mode = ClusterConnectionMode.LOAD_BALANCED
359+
def settings = ClusterSettings.builder().mode(mode).build()
360+
361+
then:
362+
settings.mode == mode
363+
}
364+
313365
def 'when mode is Single and hosts size is greater than one, should throw'() {
314366
when:
315367
ClusterSettings.builder().hosts([new ServerAddress(), new ServerAddress('other')]).mode(ClusterConnectionMode.SINGLE).build()
316368
then:
317369
thrown(IllegalArgumentException)
370+
371+
when:
372+
ClusterSettings.builder()
373+
.applyConnectionString(new ConnectionString("mongodb://host1,host2/"))
374+
.mode(ClusterConnectionMode.SINGLE)
375+
.build()
376+
then:
377+
thrown(IllegalArgumentException)
318378
}
319379

320380
def 'when cluster type is Standalone and multiple hosts are specified, should throw'() {

0 commit comments

Comments
 (0)