All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.rocketmq.shaded.io.opentelemetry.exporter.internal.retry.RetryInterceptor Maven / Gradle / Ivy

There is a newer version: 5.0.7
Show newest version
/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package org.apache.rocketmq.shaded.io.opentelemetry.exporter.internal.retry;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import okhttp3.Interceptor;
import okhttp3.Response;

/**
 * Retrier of OkHttp requests.
 *
 * 

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ public final class RetryInterceptor implements Interceptor { private final RetryPolicy retryPolicy; private final Function isRetryable; private final Function isRetryableException; private final Sleeper sleeper; private final BoundedLongGenerator randomLong; /** Constructs a new retrier. */ public RetryInterceptor(RetryPolicy retryPolicy, Function isRetryable) { this( retryPolicy, isRetryable, RetryInterceptor::isRetryableException, TimeUnit.NANOSECONDS::sleep, bound -> ThreadLocalRandom.current().nextLong(bound)); } // Visible for testing RetryInterceptor( RetryPolicy retryPolicy, Function isRetryable, Function isRetryableException, Sleeper sleeper, BoundedLongGenerator randomLong) { this.retryPolicy = retryPolicy; this.isRetryable = isRetryable; this.isRetryableException = isRetryableException; this.sleeper = sleeper; this.randomLong = randomLong; } @Override public Response intercept(Chain chain) throws IOException { Response response = null; IOException exception = null; int attempt = 0; long nextBackoffNanos = retryPolicy.getInitialBackoff().toNanos(); do { if (attempt > 0) { // Compute and sleep for backoff // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#exponential-backoff long upperBoundNanos = Math.min(nextBackoffNanos, retryPolicy.getMaxBackoff().toNanos()); long backoffNanos = randomLong.get(upperBoundNanos); nextBackoffNanos = (long) (nextBackoffNanos * retryPolicy.getBackoffMultiplier()); try { sleeper.sleep(backoffNanos); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; // Break out and return response or throw } // Close response from previous attempt if (response != null) { response.close(); } } attempt++; try { response = chain.proceed(chain.request()); } catch (IOException e) { exception = e; } if (response != null && !Boolean.TRUE.equals(isRetryable.apply(response))) { return response; } if (exception != null && !Boolean.TRUE.equals(isRetryableException.apply(exception))) { throw exception; } } while (attempt < retryPolicy.getMaxAttempts()); if (response != null) { return response; } throw exception; } // Visible for testing static boolean isRetryableException(IOException e) { if (!(e instanceof SocketTimeoutException)) { return false; } String message = e.getMessage(); return message != null && message.toLowerCase().contains("connect timed out"); } // Visible for testing interface BoundedLongGenerator { long get(long bound); } // Visible for testing interface Sleeper { void sleep(long delayNanos) throws InterruptedException; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy