@@ -15,9 +15,9 @@ import aws.smithy.kotlin.runtime.net.TlsVersion
1515import aws.smithy.kotlin.runtime.operation.ExecutionContext
1616import aws.smithy.kotlin.runtime.time.Instant
1717import aws.smithy.kotlin.runtime.time.fromEpochMilliseconds
18- import kotlinx.coroutines.ExperimentalCoroutinesApi
1918import kotlinx.coroutines.job
2019import okhttp3.*
20+ import okhttp3.ConnectionPool
2121import okhttp3.coroutines.executeAsync
2222import java.util.concurrent.TimeUnit
2323import kotlin.time.toJavaDuration
@@ -44,15 +44,15 @@ public class OkHttpEngine(
4444 }
4545
4646 private val metrics = HttpClientMetrics (TELEMETRY_SCOPE , config.telemetryProvider)
47- private val client = config.buildClient(metrics)
47+ private val connectionIdleMonitor = config.connectionIdlePollingInterval?.let { ConnectionIdleMonitor (it) }
48+ private val client = config.buildClientWithConnectionListener(metrics, connectionIdleMonitor)
4849
4950 override suspend fun roundTrip (context : ExecutionContext , request : HttpRequest ): HttpCall {
5051 val callContext = callContext()
5152
5253 val engineRequest = request.toOkHttpRequest(context, callContext, metrics)
5354 val engineCall = client.newCall(engineRequest)
5455
55- @OptIn(ExperimentalCoroutinesApi ::class )
5656 val engineResponse = mapOkHttpExceptions { engineCall.executeAsync() }
5757
5858 val response = engineResponse.toSdkResponse()
@@ -71,17 +71,17 @@ public class OkHttpEngine(
7171 }
7272
7373 override fun shutdown () {
74+ connectionIdleMonitor?.close()
7475 client.connectionPool.evictAll()
7576 client.dispatcher.executorService.shutdown()
7677 metrics.close()
7778 }
7879}
7980
80- /* *
81- * Convert SDK version of HTTP configuration to OkHttp specific configuration and return the configured client
82- */
83- @InternalApi
84- public fun OkHttpEngineConfig.buildClient (metrics : HttpClientMetrics ): OkHttpClient {
81+ private fun OkHttpEngineConfig.buildClientFromConfig (
82+ metrics : HttpClientMetrics ,
83+ poolOverride : ConnectionPool ? = null,
84+ ): OkHttpClient {
8585 val config = this
8686
8787 return OkHttpClient .Builder ().apply {
@@ -99,20 +99,11 @@ public fun OkHttpEngineConfig.buildClient(metrics: HttpClientMetrics): OkHttpCli
9999 readTimeout(config.socketReadTimeout.toJavaDuration())
100100 writeTimeout(config.socketWriteTimeout.toJavaDuration())
101101
102- @OptIn(ExperimentalOkHttpApi ::class )
103- val connectionListener = if (config.connectionIdlePollingInterval == null ) {
104- ConnectionListener .NONE
105- } else {
106- ConnectionIdleMonitor (connectionIdlePollingInterval)
107- }
108-
109102 // use our own pool configured with the timeout settings taken from config
110- @OptIn(ExperimentalOkHttpApi ::class )
111- val pool = ConnectionPool (
103+ val pool = poolOverride ? : ConnectionPool (
112104 maxIdleConnections = 5 , // The default from the no-arg ConnectionPool() constructor
113105 keepAliveDuration = config.connectionIdleTimeout.inWholeMilliseconds,
114106 TimeUnit .MILLISECONDS ,
115- connectionListener = connectionListener,
116107 )
117108 connectionPool(pool)
118109
@@ -147,6 +138,34 @@ public fun OkHttpEngineConfig.buildClient(metrics: HttpClientMetrics): OkHttpCli
147138 }.build()
148139}
149140
141+ /* *
142+ * Convert SDK version of HTTP configuration to OkHttp specific configuration and return the configured client
143+ */
144+ // Used by OkHttp4Engine - OkHttp4 does NOT have `connectionListener`
145+ // TODO - Refactor in next minor version - Move this to OkHttp4Engine and make it private
146+ @InternalApi
147+ public fun OkHttpEngineConfig.buildClient (
148+ metrics : HttpClientMetrics ,
149+ ): OkHttpClient = this .buildClientFromConfig(metrics)
150+
151+ /* *
152+ * Convert SDK version of HTTP configuration to OkHttp specific configuration and return the configured client
153+ */
154+ // Used by OkHttpEngine - OkHttp5 does have `connectionListener`
155+ @OptIn(ExperimentalOkHttpApi ::class )
156+ private fun OkHttpEngineConfig.buildClientWithConnectionListener (
157+ metrics : HttpClientMetrics ,
158+ connectionListener : ConnectionIdleMonitor ? ,
159+ ): OkHttpClient = this .buildClientFromConfig(
160+ metrics,
161+ ConnectionPool (
162+ maxIdleConnections = 5 , // The default from the no-arg ConnectionPool() constructor
163+ keepAliveDuration = this .connectionIdleTimeout.inWholeMilliseconds,
164+ timeUnit = TimeUnit .MILLISECONDS ,
165+ connectionListener = connectionListener ? : ConnectionListener .NONE ,
166+ ),
167+ )
168+
150169private fun minTlsConnectionSpec (tlsContext : TlsContext ): ConnectionSpec {
151170 val minVersion = tlsContext.minVersion ? : TlsVersion .TLS_1_2
152171 val okHttpTlsVersions = SdkTlsVersion
0 commit comments