Skip to content

Commit 9dcb580

Browse files
feat(client): add connection pooling option
1 parent ac8f1c2 commit 9dcb580

File tree

4 files changed

+149
-0
lines changed

4 files changed

+149
-0
lines changed

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,25 @@ OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
335335
.build();
336336
```
337337

338+
### Connection pooling
339+
340+
To customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:
341+
342+
```java
343+
import java.time.Duration;
344+
import org.onebusaway.client.OnebusawaySdkClient;
345+
import org.onebusaway.client.okhttp.OnebusawaySdkOkHttpClient;
346+
347+
OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
348+
.fromEnv()
349+
// If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.
350+
.maxIdleConnections(10)
351+
.keepAliveDuration(Duration.ofMinutes(2))
352+
.build();
353+
```
354+
355+
If both options are unset, OkHttp's default connection pool settings are used.
356+
338357
### HTTPS
339358

340359
> [!NOTE]

onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import java.time.Duration
77
import java.util.concurrent.CancellationException
88
import java.util.concurrent.CompletableFuture
99
import java.util.concurrent.ExecutorService
10+
import java.util.concurrent.TimeUnit
1011
import javax.net.ssl.HostnameVerifier
1112
import javax.net.ssl.SSLSocketFactory
1213
import javax.net.ssl.X509TrustManager
1314
import okhttp3.Call
1415
import okhttp3.Callback
16+
import okhttp3.ConnectionPool
1517
import okhttp3.Dispatcher
1618
import okhttp3.HttpUrl.Companion.toHttpUrl
1719
import okhttp3.Interceptor
@@ -202,6 +204,8 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie
202204

203205
private var timeout: Timeout = Timeout.default()
204206
private var proxy: Proxy? = null
207+
private var maxIdleConnections: Int? = null
208+
private var keepAliveDuration: Duration? = null
205209
private var dispatcherExecutorService: ExecutorService? = null
206210
private var sslSocketFactory: SSLSocketFactory? = null
207211
private var trustManager: X509TrustManager? = null
@@ -213,6 +217,28 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie
213217

214218
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
215219

220+
/**
221+
* Sets the maximum number of idle connections kept by the underlying [ConnectionPool].
222+
*
223+
* If this is set, then [keepAliveDuration] must also be set.
224+
*
225+
* If unset, then OkHttp's default is used.
226+
*/
227+
fun maxIdleConnections(maxIdleConnections: Int?) = apply {
228+
this.maxIdleConnections = maxIdleConnections
229+
}
230+
231+
/**
232+
* Sets the keep-alive duration for idle connections in the underlying [ConnectionPool].
233+
*
234+
* If this is set, then [maxIdleConnections] must also be set.
235+
*
236+
* If unset, then OkHttp's default is used.
237+
*/
238+
fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
239+
this.keepAliveDuration = keepAliveDuration
240+
}
241+
216242
fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
217243
this.dispatcherExecutorService = dispatcherExecutorService
218244
}
@@ -242,6 +268,22 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie
242268
.apply {
243269
dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) }
244270

271+
val maxIdleConnections = maxIdleConnections
272+
val keepAliveDuration = keepAliveDuration
273+
if (maxIdleConnections != null && keepAliveDuration != null) {
274+
connectionPool(
275+
ConnectionPool(
276+
maxIdleConnections,
277+
keepAliveDuration.toNanos(),
278+
TimeUnit.NANOSECONDS,
279+
)
280+
)
281+
} else {
282+
check((maxIdleConnections != null) == (keepAliveDuration != null)) {
283+
"Both or none of `maxIdleConnections` and `keepAliveDuration` must be set, but only one was set"
284+
}
285+
}
286+
245287
val sslSocketFactory = sslSocketFactory
246288
val trustManager = trustManager
247289
if (sslSocketFactory != null && trustManager != null) {

onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
4747
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
4848
private var dispatcherExecutorService: ExecutorService? = null
4949
private var proxy: Proxy? = null
50+
private var maxIdleConnections: Int? = null
51+
private var keepAliveDuration: Duration? = null
5052
private var sslSocketFactory: SSLSocketFactory? = null
5153
private var trustManager: X509TrustManager? = null
5254
private var hostnameVerifier: HostnameVerifier? = null
@@ -75,6 +77,46 @@ class OnebusawaySdkOkHttpClient private constructor() {
7577
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
7678
fun proxy(proxy: Optional<Proxy>) = proxy(proxy.getOrNull())
7779

80+
/**
81+
* The maximum number of idle connections kept by the underlying OkHttp connection pool.
82+
*
83+
* If this is set, then [keepAliveDuration] must also be set.
84+
*
85+
* If unset, then OkHttp's default is used.
86+
*/
87+
fun maxIdleConnections(maxIdleConnections: Int?) = apply {
88+
this.maxIdleConnections = maxIdleConnections
89+
}
90+
91+
/**
92+
* Alias for [Builder.maxIdleConnections].
93+
*
94+
* This unboxed primitive overload exists for backwards compatibility.
95+
*/
96+
fun maxIdleConnections(maxIdleConnections: Int) =
97+
maxIdleConnections(maxIdleConnections as Int?)
98+
99+
/**
100+
* Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
101+
*/
102+
fun maxIdleConnections(maxIdleConnections: Optional<Int>) =
103+
maxIdleConnections(maxIdleConnections.getOrNull())
104+
105+
/**
106+
* The keep-alive duration for idle connections in the underlying OkHttp connection pool.
107+
*
108+
* If this is set, then [maxIdleConnections] must also be set.
109+
*
110+
* If unset, then OkHttp's default is used.
111+
*/
112+
fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
113+
this.keepAliveDuration = keepAliveDuration
114+
}
115+
116+
/** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
117+
fun keepAliveDuration(keepAliveDuration: Optional<Duration>) =
118+
keepAliveDuration(keepAliveDuration.getOrNull())
119+
78120
/**
79121
* The socket factory used to secure HTTPS connections.
80122
*
@@ -317,6 +359,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
317359
OkHttpClient.builder()
318360
.timeout(clientOptions.timeout())
319361
.proxy(proxy)
362+
.maxIdleConnections(maxIdleConnections)
363+
.keepAliveDuration(keepAliveDuration)
320364
.dispatcherExecutorService(dispatcherExecutorService)
321365
.sslSocketFactory(sslSocketFactory)
322366
.trustManager(trustManager)

onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
4747
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
4848
private var dispatcherExecutorService: ExecutorService? = null
4949
private var proxy: Proxy? = null
50+
private var maxIdleConnections: Int? = null
51+
private var keepAliveDuration: Duration? = null
5052
private var sslSocketFactory: SSLSocketFactory? = null
5153
private var trustManager: X509TrustManager? = null
5254
private var hostnameVerifier: HostnameVerifier? = null
@@ -75,6 +77,46 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
7577
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
7678
fun proxy(proxy: Optional<Proxy>) = proxy(proxy.getOrNull())
7779

80+
/**
81+
* The maximum number of idle connections kept by the underlying OkHttp connection pool.
82+
*
83+
* If this is set, then [keepAliveDuration] must also be set.
84+
*
85+
* If unset, then OkHttp's default is used.
86+
*/
87+
fun maxIdleConnections(maxIdleConnections: Int?) = apply {
88+
this.maxIdleConnections = maxIdleConnections
89+
}
90+
91+
/**
92+
* Alias for [Builder.maxIdleConnections].
93+
*
94+
* This unboxed primitive overload exists for backwards compatibility.
95+
*/
96+
fun maxIdleConnections(maxIdleConnections: Int) =
97+
maxIdleConnections(maxIdleConnections as Int?)
98+
99+
/**
100+
* Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
101+
*/
102+
fun maxIdleConnections(maxIdleConnections: Optional<Int>) =
103+
maxIdleConnections(maxIdleConnections.getOrNull())
104+
105+
/**
106+
* The keep-alive duration for idle connections in the underlying OkHttp connection pool.
107+
*
108+
* If this is set, then [maxIdleConnections] must also be set.
109+
*
110+
* If unset, then OkHttp's default is used.
111+
*/
112+
fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
113+
this.keepAliveDuration = keepAliveDuration
114+
}
115+
116+
/** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
117+
fun keepAliveDuration(keepAliveDuration: Optional<Duration>) =
118+
keepAliveDuration(keepAliveDuration.getOrNull())
119+
78120
/**
79121
* The socket factory used to secure HTTPS connections.
80122
*
@@ -317,6 +359,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
317359
OkHttpClient.builder()
318360
.timeout(clientOptions.timeout())
319361
.proxy(proxy)
362+
.maxIdleConnections(maxIdleConnections)
363+
.keepAliveDuration(keepAliveDuration)
320364
.dispatcherExecutorService(dispatcherExecutorService)
321365
.sslSocketFactory(sslSocketFactory)
322366
.trustManager(trustManager)

0 commit comments

Comments
 (0)