@@ -44,30 +44,64 @@ 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 ;
5059 private final Timeout socketTimeout ;
5160 private final TimeValue validateAfterInactivity ;
5261 private final TimeValue timeToLive ;
5362
63+ /**
64+ * @since 5.6
65+ */
66+ private final boolean staggeredConnectEnabled ;
67+ /**
68+ * @since 5.6
69+ */
70+ private final TimeValue happyEyeballsAttemptDelay ;
71+ /**
72+ * @since 5.6
73+ */
74+ private final TimeValue happyEyeballsOtherFamilyDelay ;
75+ /**
76+ * @since 5.6
77+ */
78+ private final ProtocolFamilyPreference protocolFamilyPreference ;
79+
5480 /**
5581 * Intended for CDI compatibility
5682 */
5783 protected ConnectionConfig () {
58- this (DEFAULT_CONNECT_TIMEOUT , null , null , null );
84+ this (DEFAULT_CONNECT_TIMEOUT , null , null , null , false , DEFAULT_HE_ATTEMPT_DELAY , DEFAULT_HE_OTHER_FAMILY_DELAY , ProtocolFamilyPreference . INTERLEAVE );
5985 }
6086
6187 ConnectionConfig (
6288 final Timeout connectTimeout ,
6389 final Timeout socketTimeout ,
6490 final TimeValue validateAfterInactivity ,
65- final TimeValue timeToLive ) {
91+ final TimeValue timeToLive ,
92+ final boolean staggeredConnectEnabled ,
93+ final TimeValue happyEyeballsAttemptDelay ,
94+ final TimeValue happyEyeballsOtherFamilyDelay ,
95+ final ProtocolFamilyPreference protocolFamilyPreference ) {
6696 super ();
6797 this .connectTimeout = connectTimeout ;
6898 this .socketTimeout = socketTimeout ;
6999 this .validateAfterInactivity = validateAfterInactivity ;
70100 this .timeToLive = timeToLive ;
101+ this .staggeredConnectEnabled = staggeredConnectEnabled ;
102+ this .happyEyeballsAttemptDelay = happyEyeballsAttemptDelay != null ? happyEyeballsAttemptDelay : DEFAULT_HE_ATTEMPT_DELAY ;
103+ this .happyEyeballsOtherFamilyDelay = happyEyeballsOtherFamilyDelay != null ? happyEyeballsOtherFamilyDelay : DEFAULT_HE_OTHER_FAMILY_DELAY ;
104+ this .protocolFamilyPreference = protocolFamilyPreference != null ? protocolFamilyPreference : ProtocolFamilyPreference .INTERLEAVE ;
71105 }
72106
73107 /**
@@ -98,6 +132,46 @@ public TimeValue getTimeToLive() {
98132 return timeToLive ;
99133 }
100134
135+ /**
136+ * Whether staggered (Happy Eyeballs–style) connection attempts are enabled.
137+ *
138+ * @see Builder#setStaggeredConnectEnabled(boolean)
139+ * @since 5.6
140+ */
141+ public boolean isStaggeredConnectEnabled () {
142+ return staggeredConnectEnabled ;
143+ }
144+
145+ /**
146+ * Delay between subsequent staggered connection attempts.
147+ *
148+ * @see Builder#setHappyEyeballsAttemptDelay(TimeValue)
149+ * @since 5.6
150+ */
151+ public TimeValue getHappyEyeballsAttemptDelay () {
152+ return happyEyeballsAttemptDelay ;
153+ }
154+
155+ /**
156+ * Initial delay before launching the first address of the other protocol family.
157+ *
158+ * @see Builder#setHappyEyeballsOtherFamilyDelay(TimeValue)
159+ * @since 5.6
160+ */
161+ public TimeValue getHappyEyeballsOtherFamilyDelay () {
162+ return happyEyeballsOtherFamilyDelay ;
163+ }
164+
165+ /**
166+ * Protocol family preference controlling address selection and ordering.
167+ *
168+ * @see Builder#setProtocolFamilyPreference(ProtocolFamilyPreference)
169+ * @since 5.6
170+ */
171+ public ProtocolFamilyPreference getProtocolFamilyPreference () {
172+ return protocolFamilyPreference ;
173+ }
174+
101175 @ Override
102176 protected ConnectionConfig clone () throws CloneNotSupportedException {
103177 return (ConnectionConfig ) super .clone ();
@@ -111,6 +185,10 @@ public String toString() {
111185 builder .append (", socketTimeout=" ).append (socketTimeout );
112186 builder .append (", validateAfterInactivity=" ).append (validateAfterInactivity );
113187 builder .append (", timeToLive=" ).append (timeToLive );
188+ builder .append (", staggeredConnectEnabled=" ).append (staggeredConnectEnabled );
189+ builder .append (", happyEyeballsAttemptDelay=" ).append (happyEyeballsAttemptDelay );
190+ builder .append (", happyEyeballsOtherFamilyDelay=" ).append (happyEyeballsOtherFamilyDelay );
191+ builder .append (", protocolFamilyPreference=" ).append (protocolFamilyPreference );
114192 builder .append ("]" );
115193 return builder .toString ();
116194 }
@@ -124,7 +202,11 @@ public static ConnectionConfig.Builder copy(final ConnectionConfig config) {
124202 .setConnectTimeout (config .getConnectTimeout ())
125203 .setSocketTimeout (config .getSocketTimeout ())
126204 .setValidateAfterInactivity (config .getValidateAfterInactivity ())
127- .setTimeToLive (config .getTimeToLive ());
205+ .setTimeToLive (config .getTimeToLive ())
206+ .setStaggeredConnectEnabled (config .isStaggeredConnectEnabled ())
207+ .setHappyEyeballsAttemptDelay (config .getHappyEyeballsAttemptDelay ())
208+ .setHappyEyeballsOtherFamilyDelay (config .getHappyEyeballsOtherFamilyDelay ())
209+ .setProtocolFamilyPreference (config .getProtocolFamilyPreference ());
128210 }
129211
130212 public static class Builder {
@@ -134,6 +216,12 @@ public static class Builder {
134216 private TimeValue validateAfterInactivity ;
135217 private TimeValue timeToLive ;
136218
219+ // New fields (defaults)
220+ private boolean staggeredConnectEnabled = false ; // disabled by default
221+ private TimeValue happyEyeballsAttemptDelay = DEFAULT_HE_ATTEMPT_DELAY ;
222+ private TimeValue happyEyeballsOtherFamilyDelay = DEFAULT_HE_OTHER_FAMILY_DELAY ;
223+ private ProtocolFamilyPreference protocolFamilyPreference = ProtocolFamilyPreference .INTERLEAVE ;
224+
137225 Builder () {
138226 super ();
139227 this .connectTimeout = DEFAULT_CONNECT_TIMEOUT ;
@@ -232,12 +320,62 @@ public Builder setTimeToLive(final long timeToLive, final TimeUnit timeUnit) {
232320 return this ;
233321 }
234322
323+ /**
324+ * Enables or disables staggered (Happy Eyeballs–style) connection attempts.
325+ *
326+ * @since 5.6
327+ * @return this instance.
328+ */
329+ public Builder setStaggeredConnectEnabled (final boolean enabled ) {
330+ this .staggeredConnectEnabled = enabled ;
331+ return this ;
332+ }
333+
334+ /**
335+ * Sets the delay between staggered connection attempts.
336+ *
337+ * @since 5.6
338+ * @return this instance.
339+ */
340+ public Builder setHappyEyeballsAttemptDelay (final TimeValue delay ) {
341+ this .happyEyeballsAttemptDelay = delay ;
342+ return this ;
343+ }
344+
345+ /**
346+ * Sets the initial delay before launching the first address of the other
347+ * protocol family (IPv6 vs IPv4) when interleaving attempts.
348+ *
349+ * @since 5.6
350+ * @return this instance.
351+ */
352+ public Builder setHappyEyeballsOtherFamilyDelay (final TimeValue delay ) {
353+ this .happyEyeballsOtherFamilyDelay = delay ;
354+ return this ;
355+ }
356+
357+ /**
358+ * Sets the protocol family preference that guides address selection and ordering.
359+ *
360+ * @since 5.6
361+ * @return this instance.
362+ */
363+ public Builder setProtocolFamilyPreference (final ProtocolFamilyPreference preference ) {
364+ this .protocolFamilyPreference = preference ;
365+ return this ;
366+ }
367+
235368 public ConnectionConfig build () {
236369 return new ConnectionConfig (
237370 connectTimeout != null ? connectTimeout : DEFAULT_CONNECT_TIMEOUT ,
238371 socketTimeout ,
239372 validateAfterInactivity ,
240- timeToLive );
373+ timeToLive ,
374+ staggeredConnectEnabled ,
375+ happyEyeballsAttemptDelay != null ? happyEyeballsAttemptDelay : DEFAULT_HE_ATTEMPT_DELAY ,
376+ happyEyeballsOtherFamilyDelay != null ? happyEyeballsOtherFamilyDelay : DEFAULT_HE_OTHER_FAMILY_DELAY ,
377+ protocolFamilyPreference != null ? protocolFamilyPreference : ProtocolFamilyPreference .INTERLEAVE
378+ );
241379 }
242380
243381 }
0 commit comments