/* * 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 } }