Skip to content

Commit 789fee7

Browse files
authored
Merge pull request #1536 from nats-io/HostnameResolveMode
HostnameResolveMode better organizes the 4 possible modes
2 parents 8be2da5 + bf1856e commit 789fee7

12 files changed

Lines changed: 521 additions & 217 deletions

src/main/java/io/nats/client/Options.java

Lines changed: 138 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,64 @@ public enum SubjectValidationType {
273273
Strict
274274
}
275275

276+
/**
277+
* The mode of hostname resolving
278+
*/
279+
public enum HostnameResolveMode {
280+
/**
281+
* Resolve host to all ip addresses allowing for connection attempts to try all ip addresses for a given hostname.
282+
* Default mode. Does not include IPV6 addresses.
283+
*/
284+
ResolveToAll(true, false, false),
285+
286+
/**
287+
* Resolve host to the first ip addresses allowing for connection attempts to try just that first ip addresses for a given hostname.
288+
* Does not include IPV6 addresses.
289+
*/
290+
ResolveToFirst(true, true, false),
291+
292+
/**
293+
* Resolve host to all ip addresses allowing for connection attempts to try all ip addresses for a given hostname.
294+
* Includes IPV6 addresses.
295+
*/
296+
ResolveToAllIncludeIPV6(true, false, true),
297+
298+
/**
299+
* Resolve host to the first ip addresses allowing for connection attempts to try just that first ip addresses for a given hostname.
300+
* Includes IPV6 addresses.
301+
*/
302+
ResolveToFirstIncludeIPV6(true, true, true),
303+
304+
/**
305+
* Do not resolve, instead use InetSocketAddress.createUnresolved while creating the socket.
306+
*/
307+
Unresolved(false, false, false),
308+
309+
/**
310+
* Attempt to connect to the fastest ip for a host via the Happy Eyeballs algorithm as described in RFC 6555/8305
311+
*/
312+
HappyEyeballs(false, false, false);
313+
314+
public final boolean resolve;
315+
public final boolean maxOneResult;
316+
public final boolean includeIPV6;
317+
318+
HostnameResolveMode(boolean resolve, boolean maxOneResult, boolean includeIPV6) {
319+
this.resolve = resolve;
320+
this.maxOneResult = maxOneResult;
321+
this.includeIPV6 = includeIPV6;
322+
}
323+
324+
public static HostnameResolveMode get(String value) {
325+
for (HostnameResolveMode mode : HostnameResolveMode.values()) {
326+
if (mode.name().equalsIgnoreCase(value)) {
327+
return mode;
328+
}
329+
}
330+
return null;
331+
}
332+
}
333+
276334
// ----------------------------------------------------------------------------------------------------
277335
// ENVIRONMENT PROPERTIES
278336
// ----------------------------------------------------------------------------------------------------
@@ -410,14 +468,23 @@ public enum SubjectValidationType {
410468
*/
411469
public static final String PROP_NORANDOMIZE = PFX + "norandomize";
412470
/**
471+
* @deprecated Prefer to use hostname resolve mode
413472
* Property used to configure a builder from a Properties object. {@value}, see {@link Builder#noResolveHostnames() noResolveHostnames}.
414473
*/
474+
@Deprecated
415475
public static final String PROP_NO_RESOLVE_HOSTNAMES = PFX + "noResolveHostnames";
416476
/**
417-
* Property used to enable InetSocketAddress.createUnresolved for proxied connections.
418-
* {@link Builder#enableInetAddressCreateUnresolved() enableInetAddressCreateUnresolved}.
477+
* @deprecated Prefer to use hostname resolve mode
478+
* Property used to enable fast fallback algorithm for socket connection.
479+
* {@link Builder#enableFastFallback() enableFastFallback}.
419480
*/
420-
public static final String PROP_ENABLE_INET_ADDRESS_CREATE_UNRESOLVED = PFX + "inet.address.create.unresolved";
481+
@Deprecated
482+
public static final String PROP_FAST_FALLBACK = PFX + "fast.fallback";
483+
/**
484+
* Property used to configure a builder from a Properties object. {@value}, see {@link Builder#hostnameResolveMode(HostnameResolveMode) hostnameResolveMode}.
485+
* Takes precedence over PROP_NO_RESOLVE_HOSTNAMES and PROP_FAST_FALLBACK
486+
*/
487+
public static final String PROP_HOSTNAME_RESOLVE_MODE = PFX + "hostnameResolveMode";
421488
/**
422489
* Property used to configure a builder from a Properties object. {@value}, see {@link Builder#noSubjectValidation() noSubjectValidation}.
423490
*/
@@ -613,12 +680,6 @@ public enum SubjectValidationType {
613680
*/
614681
public static final String PROP_READ_LISTENER_CLASS = "read.listener.class";
615682

616-
/**
617-
* Property used to enable fast fallback algorithm for socket connection.
618-
* {@link Builder#enableFastFallback() enableFastFallback}.
619-
*/
620-
public static final String PROP_FAST_FALLBACK = PFX + "fast.fallback";
621-
622683
// ----------------------------------------------------------------------------------------------------
623684
// PROTOCOL CONNECT OPTION CONSTANTS
624685
// ----------------------------------------------------------------------------------------------------
@@ -715,7 +776,7 @@ public enum SubjectValidationType {
715776
private final List<NatsUri> natsServerUris;
716777
private final List<String> unprocessedServers;
717778
private final boolean noRandomize;
718-
private final boolean noResolveHostnames;
779+
private final HostnameResolveMode hostnameResolveMode;
719780
private final SubjectValidationType subjectValidationType;
720781
private final boolean reportNoResponders;
721782
private final String connectionName;
@@ -791,8 +852,6 @@ public enum SubjectValidationType {
791852

792853
private final List<java.util.function.Consumer<HttpRequest>> httpRequestInterceptors;
793854
private final Proxy proxy;
794-
private final boolean enableFastFallback;
795-
private final boolean enableInetAddressCreateUnresolved;
796855

797856
// STATE VARIABLES
798857
private int executorUseCount = 0;
@@ -877,7 +936,7 @@ public static class Builder {
877936
private final List<NatsUri> natsServerUris = new ArrayList<>();
878937
private final List<String> unprocessedServers = new ArrayList<>();
879938
private boolean noRandomize = false;
880-
private boolean noResolveHostnames = false;
939+
private HostnameResolveMode hostnameResolveMode = HostnameResolveMode.ResolveToAll;
881940
private SubjectValidationType subjectValidationType = SubjectValidationType.Lenient;
882941
private boolean reportNoResponders = false;
883942
private String connectionName = null; // Useful for debugging -> "test: " + NatsTestServer.currentPort();
@@ -950,8 +1009,6 @@ public static class Builder {
9501009
private char[] truststorePassword;
9511010
private String tlsAlgorithm = DEFAULT_TLS_ALGORITHM;
9521011
private String credentialPath;
953-
private boolean enableFastFallback = false;
954-
private boolean enableInetAddressCreateUnresolved = false;
9551012

9561013
/**
9571014
* Constructs a new Builder with the default values.
@@ -1024,7 +1081,6 @@ public Builder properties(Properties props) {
10241081
stringProperty(props, PROP_CONNECTION_NAME, s -> this.connectionName = s);
10251082

10261083
booleanProperty(props, PROP_NORANDOMIZE, b -> this.noRandomize = b);
1027-
booleanProperty(props, PROP_NO_RESOLVE_HOSTNAMES, b -> this.noResolveHostnames = b);
10281084
booleanPropertyIfTrue(props, PROP_NO_SUBJECT_VALIDATION, b -> subjectValidationType = SubjectValidationType.None);
10291085
booleanPropertyIfTrue(props, PROP_STRICT_SUBJECT_VALIDATION, b -> subjectValidationType = SubjectValidationType.Strict);
10301086
booleanProperty(props, PROP_REPORT_NO_RESPONDERS, b -> this.reportNoResponders = b);
@@ -1073,8 +1129,23 @@ public Builder properties(Properties props) {
10731129
booleanProperty(props, PROP_USE_TIMEOUT_EXCEPTION, b -> this.useTimeoutException = b);
10741130
booleanProperty(props, PROP_USE_DISPATCHER_WITH_EXECUTOR, b -> this.useDispatcherWithExecutor = b);
10751131
booleanProperty(props, PROP_FORCE_FLUSH_ON_REQUEST, b -> this.forceFlushOnRequest = b);
1076-
booleanProperty(props, PROP_FAST_FALLBACK, b -> this.enableFastFallback = b);
1077-
booleanProperty(props, PROP_ENABLE_INET_ADDRESS_CREATE_UNRESOLVED, b -> this.enableInetAddressCreateUnresolved = b);
1132+
1133+
booleanProperty(props, PROP_NO_RESOLVE_HOSTNAMES, b -> {
1134+
if (b) {
1135+
hostnameResolveMode = HostnameResolveMode.ResolveToFirst;
1136+
}
1137+
});
1138+
booleanProperty(props, PROP_FAST_FALLBACK, b -> {
1139+
if (b) {
1140+
hostnameResolveMode = HostnameResolveMode.HappyEyeballs;
1141+
}
1142+
});
1143+
stringProperty(props, PROP_HOSTNAME_RESOLVE_MODE, s -> {
1144+
HostnameResolveMode mode = HostnameResolveMode.get(s);
1145+
if (mode != null) {
1146+
hostnameResolveMode = mode;
1147+
}
1148+
});
10781149

10791150
classnameProperty(props, PROP_SERVERS_POOL_IMPLEMENTATION_CLASS, o -> this.serverPool = (ServerPool) o);
10801151
classnameProperty(props, PROP_DISPATCHER_FACTORY_CLASS, o -> this.dispatcherFactory = (DispatcherFactory) o);
@@ -1148,11 +1219,34 @@ public Builder noRandomize() {
11481219
}
11491220

11501221
/**
1151-
* For the default server list provider, whether to resolve hostnames when building server list.
1222+
* @deprecated use hostnameResolveMode()
1223+
* If the connection should not resolve hostnames to ip addresses.
11521224
* @return the Builder for chaining
11531225
*/
1226+
@Deprecated
11541227
public Builder noResolveHostnames() {
1155-
this.noResolveHostnames = true;
1228+
this.hostnameResolveMode = HostnameResolveMode.ResolveToFirst;
1229+
return this;
1230+
}
1231+
1232+
/**
1233+
* @deprecated use hostnameResolveMode()
1234+
* Whether to enable Fast fallback algorithm for socket connect
1235+
* @return the Builder for chaining
1236+
*/
1237+
@Deprecated
1238+
public Builder enableFastFallback() {
1239+
this.hostnameResolveMode = HostnameResolveMode.HappyEyeballs;
1240+
return this;
1241+
}
1242+
1243+
/**
1244+
* Set the hostname resolve mode
1245+
* @param hostnameResolveMode the enum value
1246+
* @return the Builder for chaining
1247+
*/
1248+
public Builder hostnameResolveMode(HostnameResolveMode hostnameResolveMode) {
1249+
this.hostnameResolveMode = hostnameResolveMode == null ? HostnameResolveMode.ResolveToAll : hostnameResolveMode;
11561250
return this;
11571251
}
11581252

@@ -2044,26 +2138,6 @@ public Builder dispatcherFactory(DispatcherFactory dispatcherFactory) {
20442138
return this;
20452139
}
20462140

2047-
/**
2048-
* Whether to enable Fast fallback algorithm for socket connect
2049-
* @return the Builder for chaining
2050-
*/
2051-
public Builder enableFastFallback() {
2052-
this.enableFastFallback = true;
2053-
return this;
2054-
}
2055-
2056-
/**
2057-
* Whether to enable InetSocketAddress.createUnresolved for proxied connections.
2058-
* This is useful for backward compatibility and when hostname resolution should be deferred.
2059-
* @return the Builder for chaining
2060-
*/
2061-
public Builder enableInetAddressCreateUnresolved() {
2062-
this.enableInetAddressCreateUnresolved = true;
2063-
this.noResolveHostnames = true;
2064-
return this;
2065-
}
2066-
20672141
/**
20682142
* Build an Options object from this Builder.
20692143
*
@@ -2231,7 +2305,7 @@ public Builder(Options o) {
22312305
this.natsServerUris.addAll(o.natsServerUris);
22322306
this.unprocessedServers.addAll(o.unprocessedServers);
22332307
this.noRandomize = o.noRandomize;
2234-
this.noResolveHostnames = o.noResolveHostnames;
2308+
this.hostnameResolveMode = o.hostnameResolveMode;
22352309
this.subjectValidationType = o.subjectValidationType;
22362310
this.reportNoResponders = o.reportNoResponders;
22372311
this.connectionName = o.connectionName;
@@ -2298,8 +2372,6 @@ public Builder(Options o) {
22982372

22992373
this.serverPool = o.serverPool;
23002374
this.dispatcherFactory = o.dispatcherFactory;
2301-
this.enableFastFallback = o.enableFastFallback;
2302-
this.enableInetAddressCreateUnresolved = o.enableInetAddressCreateUnresolved;
23032375
}
23042376
}
23052377

@@ -2310,7 +2382,7 @@ private Options(Builder b) {
23102382
this.natsServerUris = Collections.unmodifiableList(b.natsServerUris);
23112383
this.unprocessedServers = Collections.unmodifiableList(b.unprocessedServers); // exactly how the user gave them
23122384
this.noRandomize = b.noRandomize;
2313-
this.noResolveHostnames = b.noResolveHostnames;
2385+
this.hostnameResolveMode = b.hostnameResolveMode;
23142386
this.subjectValidationType = b.subjectValidationType;
23152387
this.reportNoResponders = b.reportNoResponders;
23162388
this.connectionName = b.connectionName;
@@ -2378,8 +2450,6 @@ private Options(Builder b) {
23782450

23792451
this.serverPool = b.serverPool;
23802452
this.dispatcherFactory = b.dispatcherFactory;
2381-
this.enableFastFallback = b.enableFastFallback;
2382-
this.enableInetAddressCreateUnresolved = b.enableInetAddressCreateUnresolved;
23832453
}
23842454

23852455
// ----------------------------------------------------------------------------------------------------
@@ -2728,11 +2798,30 @@ public boolean isNoRandomize() {
27282798
}
27292799

27302800
/**
2731-
* should we skip resolving hostnames for server connection attempts, see {@link Builder#noResolveHostnames() noResolveHostnames()} in the builder doc
2732-
* @return true if we should resolve hostnames
2801+
* @deprecated use hostnameResolveMode instead
2802+
* @return true if HostnameResolveMode is HostnameResolveMode.ResolveToFirst since that mode replaces isNoResolveHostnames
27332803
*/
2804+
@Deprecated
27342805
public boolean isNoResolveHostnames() {
2735-
return noResolveHostnames;
2806+
return hostnameResolveMode == HostnameResolveMode.ResolveToFirst;
2807+
}
2808+
2809+
/**
2810+
* @deprecated use hostnameResolveMode instead
2811+
* Whether Fast fallback algorithm is enabled for socket connect
2812+
* @return true if HostnameResolveMode is HostnameResolveMode.HappyEyeballs since that mode replaces isEnableFastFallback
2813+
*/
2814+
@Deprecated
2815+
public boolean isEnableFastFallback() {
2816+
return hostnameResolveMode == HostnameResolveMode.HappyEyeballs;
2817+
}
2818+
2819+
/**
2820+
* Get the Hostname Resolve Mode
2821+
* @return the mode
2822+
*/
2823+
public HostnameResolveMode hostnameResolveMode() {
2824+
return hostnameResolveMode;
27362825
}
27372826

27382827
/**
@@ -3126,22 +3215,6 @@ public DispatcherFactory getDispatcherFactory() {
31263215
return dispatcherFactory;
31273216
}
31283217

3129-
/**
3130-
* Whether Fast fallback algorithm is enabled for socket connect
3131-
* @return the flag
3132-
*/
3133-
public boolean isEnableFastFallback() {
3134-
return enableFastFallback;
3135-
}
3136-
3137-
/**
3138-
* Whether InetSocketAddress.createUnresolved is enabled for proxied connections
3139-
* @return the flag
3140-
*/
3141-
public boolean isEnableInetAddressCreateUnresolved() {
3142-
return enableInetAddressCreateUnresolved;
3143-
}
3144-
31453218
/**
31463219
* create a URI from a server uri.
31473220
* @param serverURI the text uri

src/main/java/io/nats/client/ServerPool.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,28 @@ public interface ServerPool {
5353
NatsUri nextServer();
5454

5555
/**
56+
* @deprecated NatsConnection calls resolveHostToIps(String, resolveInstruction) now
5657
* Resolve a host name to an ip address
5758
* @param host the host to resolve
5859
* @return a list of resolved hosts. Can be null.
5960
*/
6061
@Nullable
62+
@Deprecated
6163
List<String> resolveHostToIps(@NonNull String host);
6264

65+
/**
66+
* Resolve a host name to an ip address based on the instructions. Replaces resolveHostToIps(String)
67+
*
68+
* @param host the host to resolve
69+
* @param maxOneResult flag to indicate to only return one result
70+
* @param includeIPV6 flag to indicate to include IPV6 ip addresses in the results.
71+
* @return a list of resolved hosts. Can be null if host does not resolve
72+
*/
73+
@Nullable
74+
default List<String> resolveHostToIps(@NonNull String host, boolean maxOneResult, boolean includeIPV6) {
75+
return resolveHostToIps(host);
76+
}
77+
6378
/**
6479
* Indicate that the connection to this NatsUri succeeded.
6580
* @param nuri should match the NatsUri given by nextServer

0 commit comments

Comments
 (0)