PR Review Lab · Give Every Service a Shared HTTP Client

35:00left of 35:00

Give Every Service a Shared HTTP Client

Every team configures HTTP clients differently, and two incidents last quarter came from calls with no timeout. This adds platform-http, a shared OkHttp client with a 30 second timeout, retries with exponential backoff on IOExceptions and 5xx responses, and a metrics interceptor. platform-core 5.0 registers it as the default client, so the BOM bump moves all 41 services onto it at their next build with no code changes.

Aplatform-http/src/main/java/com/acme/platform/http/PlatformHttpClient.java1 of 3

Files Changed

platform-http/src/main/java/com/acme/platform/http/

platform-bom/

platform-http/src/main/java/com/acme/platform/http/PlatformHttpClient.java

Java · Click a line number to comment · Tap a line to comment
@@ -0,0 +1,46 @@
Added: package com.acme.platform.http;
Added:
Added: import java.io.IOException;
Added: import java.time.Duration;
Added: import okhttp3.Interceptor;
Added: import okhttp3.OkHttpClient;
Added: import okhttp3.Response;
Added:
Added: /** The HTTP client every service gets from the platform BOM. */
Added: public final class PlatformHttpClient {
Added: static final int MAX_RETRIES = 5;
Added: static final Duration TIMEOUT = Duration.ofSeconds(30);
Added:
Added: public static OkHttpClient create() {
Added: return new OkHttpClient.Builder()
Added: .callTimeout(TIMEOUT)
Added: .addInterceptor(PlatformHttpClient::retry)
Added: .addInterceptor(new MetricsInterceptor())
Added: .build();
Added: }
Added:
Added: static Response retry(Interceptor.Chain chain) throws IOException {
Added: IOException last = null;
Added: for (int attempt = 0; attempt <= MAX_RETRIES; attempt++) {
Added: try {
Added: Response response = chain.proceed(chain.request());
Added: if (response.code() < 500) {
Added: return response;
Added: }
Added: response.close();
Added: } catch (IOException e) {
Added: last = e;
Added: }
Added: sleep(100L << attempt);
Added: }
Added: throw last != null ? last : new IOException("retries exhausted");
Added: }
Added:
Added: private static void sleep(long millis) {
Added: try {
Added: Thread.sleep(millis);
Added: } catch (InterruptedException e) {
Added: Thread.currentThread().interrupt();
Added: }
Added: }
Added: }