Skip to content

Instantly share code, notes, and snippets.

@yschimke
Last active May 28, 2022 09:53
Show Gist options
  • Save yschimke/02c3964023e6df860d6719dd8de707bf to your computer and use it in GitHub Desktop.
Save yschimke/02c3964023e6df860d6719dd8de707bf to your computer and use it in GitHub Desktop.
/*
* Copyright (C) 2020 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.compare
import java.io.IOException
import java.time.Duration
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy
import java.util.concurrent.TimeUnit
import mockwebserver3.MockWebServer
import okhttp3.Call
import okhttp3.Callback
import okhttp3.ConnectionPool
import okhttp3.Dispatcher
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import org.junit.jupiter.api.Test
/**
* OkHttp.
*
* https://square.github.io/okhttp/
*/
class OkHttpClientTest {
@Test fun get(server: MockWebServer) {
val connectionPool = ConnectionPool(8, 5, TimeUnit.MINUTES)
val dispatcher = Dispatcher(
ThreadPoolExecutor(
8,
8,
1, TimeUnit.MINUTES,
LinkedBlockingQueue(16),
Executors.defaultThreadFactory(),
CallerRunsPolicy()
)
)
dispatcher.maxRequestsPerHost = 8
dispatcher.maxRequests = 8
val builder = OkHttpClient().newBuilder()
.retryOnConnectionFailure(false)
.callTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(3))
.writeTimeout(Duration.ofSeconds(3))
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.addInterceptor(OkHttpRetryInterceptor(3))
val client = builder
.protocols(listOf(Protocol.HTTP_1_1))
.build()
val request = Request.Builder()
.url("https://nghttp2.org/httpbin/status/500")
.build()
val requests = 10
val latch = CountDownLatch(requests)
val responseCallback = object : Callback {
override fun onFailure(call: Call, e: okio.IOException) {
println(e)
latch.countDown()
}
override fun onResponse(call: Call, response: Response) {
println(response.code)
// response.close()
latch.countDown()
}
}
repeat(10) {
client.newCall(request).enqueue(responseCallback)
}
latch.await()
}
}
class OkHttpRetryInterceptor(var maxRetryTimes: Int) : Interceptor {
val retryInterval = 200L
@Throws(IOException::class) override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
var response = chain.proceed(request)
var retryCount = 1
while (!response.isSuccessful && retryCount <= maxRetryTimes) {
val wait = retryInterval * retryCount
println(
"okhttp retry: retry count = $retryCount, wait = $wait ms, response = $response"
)
response.close()
try {
TimeUnit.MILLISECONDS.sleep(wait)
} catch (ignored1: InterruptedException) {
}
retryCount++
response = chain.proceed(request)
}
return response
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment