
org.apache.pulsar.io.elasticsearch.RandomExponentialRetry Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.pulsar.io.elasticsearch;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
/**
* Implements the jitter backoff retry.
* see https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
*/
@Slf4j
public class RandomExponentialRetry {
/**
* Singleton instance.
*/
public static final RandomExponentialRetry INSTANCE = new RandomExponentialRetry();
/**
* Maximum time in seconds between two retries.
*/
public final long maxRetryTimeInSec;
public RandomExponentialRetry() {
this(TimeUnit.HOURS.toSeconds(24));
}
public RandomExponentialRetry(long maxRetryTimeInSec) {
this.maxRetryTimeInSec = maxRetryTimeInSec;
}
public long waitInMs(int attempt, long backoffInMs) {
assert attempt >= 0;
assert backoffInMs >= 0;
return Math.min(maxRetryTimeInSec * 1000, backoffInMs << attempt);
}
public long randomWaitInMs(int attempt, long backoffInMs) {
return ThreadLocalRandom.current().nextLong(0, waitInMs(attempt, backoffInMs));
}
public T retry(Callable function, int maxAttempts, long initialBackoff, String source) throws Exception {
return retry(function, maxAttempts, initialBackoff, source, new Time());
}
protected T retry(Callable function, int maxAttempts, long initialBackoff, String source, Time clock)
throws Exception {
Exception lastException = null;
for (int i = 0; i < maxAttempts || maxAttempts == -1; i++) {
try {
return function.call();
} catch (Exception e) {
lastException = e;
long backoff = randomWaitInMs(i, initialBackoff);
log.info("Executing '{}', attempt {}/{}, next retry in {} ms, caused by: {}", source, i,
maxAttempts, backoff, e.getMessage());
clock.sleep(backoff);
}
}
throw lastException;
}
// mockable sleep
public static class Time {
void sleep(long millis) throws InterruptedException {
Thread.sleep(millis);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy