@@ -44,6 +44,15 @@ public class ConnectionConfig implements Cloneable {
4444
4545 private static final Timeout DEFAULT_CONNECT_TIMEOUT = Timeout .ofMinutes (3 );
4646
47+ /**
48+ * @since 5.6
49+ */
50+ private static final TimeValue DEFAULT_HE_ATTEMPT_DELAY = TimeValue .ofMilliseconds (250 );
51+ /**
52+ * @since 5.6
53+ */
54+ private static final TimeValue DEFAULT_HE_OTHER_FAMILY_DELAY = TimeValue .ofMilliseconds (50 );
55+
4756 public static final ConnectionConfig DEFAULT = new Builder ().build ();
4857
4958 private final Timeout connectTimeout ;
@@ -52,25 +61,50 @@ public class ConnectionConfig implements Cloneable {
5261 private final TimeValue validateAfterInactivity ;
5362 private final TimeValue timeToLive ;
5463
64+ /**
65+ * @since 5.6
66+ */
67+ private final boolean staggeredConnectEnabled ;
68+ /**
69+ * @since 5.6
70+ */
71+ private final TimeValue happyEyeballsAttemptDelay ;
72+ /**
73+ * @since 5.6
74+ */
75+ private final TimeValue happyEyeballsOtherFamilyDelay ;
76+ /**
77+ * @since 5.6
78+ */
79+ private final ProtocolFamilyPreference protocolFamilyPreference ;
80+
5581 /**
5682 * Intended for CDI compatibility
5783 */
5884 protected ConnectionConfig () {
59- this (DEFAULT_CONNECT_TIMEOUT , null , null , null , null );
85+ this (DEFAULT_CONNECT_TIMEOUT , null , null , null , null , false , DEFAULT_HE_ATTEMPT_DELAY , DEFAULT_HE_OTHER_FAMILY_DELAY , ProtocolFamilyPreference . INTERLEAVE );
6086 }
6187
6288 ConnectionConfig (
6389 final Timeout connectTimeout ,
6490 final Timeout socketTimeout ,
6591 final Timeout idleTimeout ,
6692 final TimeValue validateAfterInactivity ,
67- final TimeValue timeToLive ) {
93+ final TimeValue timeToLive ,
94+ final boolean staggeredConnectEnabled ,
95+ final TimeValue happyEyeballsAttemptDelay ,
96+ final TimeValue happyEyeballsOtherFamilyDelay ,
97+ final ProtocolFamilyPreference protocolFamilyPreference ) {
6898 super ();
6999 this .connectTimeout = connectTimeout ;
70100 this .socketTimeout = socketTimeout ;
71101 this .idleTimeout = idleTimeout ;
72102 this .validateAfterInactivity = validateAfterInactivity ;
73103 this .timeToLive = timeToLive ;
104+ this .staggeredConnectEnabled = staggeredConnectEnabled ;
105+ this .happyEyeballsAttemptDelay = happyEyeballsAttemptDelay != null ? happyEyeballsAttemptDelay : DEFAULT_HE_ATTEMPT_DELAY ;
106+ this .happyEyeballsOtherFamilyDelay = happyEyeballsOtherFamilyDelay != null ? happyEyeballsOtherFamilyDelay : DEFAULT_HE_OTHER_FAMILY_DELAY ;
107+ this .protocolFamilyPreference = protocolFamilyPreference != null ? protocolFamilyPreference : ProtocolFamilyPreference .INTERLEAVE ;
74108 }
75109
76110 /**
@@ -108,6 +142,46 @@ public TimeValue getTimeToLive() {
108142 return timeToLive ;
109143 }
110144
145+ /**
146+ * Whether staggered (Happy Eyeballs–style) connection attempts are enabled.
147+ *
148+ * @see Builder#setStaggeredConnectEnabled(boolean)
149+ * @since 5.6
150+ */
151+ public boolean isStaggeredConnectEnabled () {
152+ return staggeredConnectEnabled ;
153+ }
154+
155+ /**
156+ * Delay between subsequent staggered connection attempts.
157+ *
158+ * @see Builder#setHappyEyeballsAttemptDelay(TimeValue)
159+ * @since 5.6
160+ */
161+ public TimeValue getHappyEyeballsAttemptDelay () {
162+ return happyEyeballsAttemptDelay ;
163+ }
164+
165+ /**
166+ * Initial delay before launching the first address of the other protocol family.
167+ *
168+ * @see Builder#setHappyEyeballsOtherFamilyDelay(TimeValue)
169+ * @since 5.6
170+ */
171+ public TimeValue getHappyEyeballsOtherFamilyDelay () {
172+ return happyEyeballsOtherFamilyDelay ;
173+ }
174+
175+ /**
176+ * Protocol family preference controlling address selection and ordering.
177+ *
178+ * @see Builder#setProtocolFamilyPreference(ProtocolFamilyPreference)
179+ * @since 5.6
180+ */
181+ public ProtocolFamilyPreference getProtocolFamilyPreference () {
182+ return protocolFamilyPreference ;
183+ }
184+
111185 @ Override
112186 protected ConnectionConfig clone () throws CloneNotSupportedException {
113187 return (ConnectionConfig ) super .clone ();
@@ -122,6 +196,10 @@ public String toString() {
122196 builder .append (", idleTimeout=" ).append (idleTimeout );
123197 builder .append (", validateAfterInactivity=" ).append (validateAfterInactivity );
124198 builder .append (", timeToLive=" ).append (timeToLive );
199+ builder .append (", staggeredConnectEnabled=" ).append (staggeredConnectEnabled );
200+ builder .append (", happyEyeballsAttemptDelay=" ).append (happyEyeballsAttemptDelay );
201+ builder .append (", happyEyeballsOtherFamilyDelay=" ).append (happyEyeballsOtherFamilyDelay );
202+ builder .append (", protocolFamilyPreference=" ).append (protocolFamilyPreference );
125203 builder .append ("]" );
126204 return builder .toString ();
127205 }
@@ -135,7 +213,11 @@ public static ConnectionConfig.Builder copy(final ConnectionConfig config) {
135213 .setConnectTimeout (config .getConnectTimeout ())
136214 .setSocketTimeout (config .getSocketTimeout ())
137215 .setValidateAfterInactivity (config .getValidateAfterInactivity ())
138- .setTimeToLive (config .getTimeToLive ());
216+ .setTimeToLive (config .getTimeToLive ())
217+ .setStaggeredConnectEnabled (config .isStaggeredConnectEnabled ())
218+ .setHappyEyeballsAttemptDelay (config .getHappyEyeballsAttemptDelay ())
219+ .setHappyEyeballsOtherFamilyDelay (config .getHappyEyeballsOtherFamilyDelay ())
220+ .setProtocolFamilyPreference (config .getProtocolFamilyPreference ());
139221 }
140222
141223 public static class Builder {
@@ -146,6 +228,12 @@ public static class Builder {
146228 private TimeValue validateAfterInactivity ;
147229 private TimeValue timeToLive ;
148230
231+ // New fields (defaults)
232+ private boolean staggeredConnectEnabled = false ; // disabled by default
233+ private TimeValue happyEyeballsAttemptDelay = DEFAULT_HE_ATTEMPT_DELAY ;
234+ private TimeValue happyEyeballsOtherFamilyDelay = DEFAULT_HE_OTHER_FAMILY_DELAY ;
235+ private ProtocolFamilyPreference protocolFamilyPreference = ProtocolFamilyPreference .INTERLEAVE ;
236+
149237 Builder () {
150238 super ();
151239 this .connectTimeout = DEFAULT_CONNECT_TIMEOUT ;
@@ -281,13 +369,63 @@ public Builder setTimeToLive(final long timeToLive, final TimeUnit timeUnit) {
281369 return this ;
282370 }
283371
372+ /**
373+ * Enables or disables staggered (Happy Eyeballs–style) connection attempts.
374+ *
375+ * @since 5.6
376+ * @return this instance.
377+ */
378+ public Builder setStaggeredConnectEnabled (final boolean enabled ) {
379+ this .staggeredConnectEnabled = enabled ;
380+ return this ;
381+ }
382+
383+ /**
384+ * Sets the delay between staggered connection attempts.
385+ *
386+ * @since 5.6
387+ * @return this instance.
388+ */
389+ public Builder setHappyEyeballsAttemptDelay (final TimeValue delay ) {
390+ this .happyEyeballsAttemptDelay = delay ;
391+ return this ;
392+ }
393+
394+ /**
395+ * Sets the initial delay before launching the first address of the other
396+ * protocol family (IPv6 vs IPv4) when interleaving attempts.
397+ *
398+ * @since 5.6
399+ * @return this instance.
400+ */
401+ public Builder setHappyEyeballsOtherFamilyDelay (final TimeValue delay ) {
402+ this .happyEyeballsOtherFamilyDelay = delay ;
403+ return this ;
404+ }
405+
406+ /**
407+ * Sets the protocol family preference that guides address selection and ordering.
408+ *
409+ * @since 5.6
410+ * @return this instance.
411+ */
412+ public Builder setProtocolFamilyPreference (final ProtocolFamilyPreference preference ) {
413+ this .protocolFamilyPreference = preference ;
414+ return this ;
415+ }
416+
284417 public ConnectionConfig build () {
285418 return new ConnectionConfig (
286419 connectTimeout != null ? connectTimeout : DEFAULT_CONNECT_TIMEOUT ,
287420 socketTimeout ,
288421 idleTimeout ,
289422 validateAfterInactivity ,
290- timeToLive );
423+ timeToLive ,
424+ staggeredConnectEnabled ,
425+ happyEyeballsAttemptDelay != null ? happyEyeballsAttemptDelay : DEFAULT_HE_ATTEMPT_DELAY ,
426+ happyEyeballsOtherFamilyDelay != null ? happyEyeballsOtherFamilyDelay : DEFAULT_HE_OTHER_FAMILY_DELAY ,
427+ protocolFamilyPreference != null ? protocolFamilyPreference : ProtocolFamilyPreference .INTERLEAVE
428+ );
291429 }
292430
293431 }
0 commit comments