
org.apache.flink.streaming.util.retryable.AsyncRetryStrategies 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.flink.streaming.util.retryable;
import org.apache.flink.streaming.api.functions.async.AsyncRetryPredicate;
import org.apache.flink.streaming.api.functions.async.AsyncRetryStrategy;
import org.apache.flink.util.Preconditions;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Predicate;
/**
* Utility class to create concrete {@link AsyncRetryStrategy}.
*
* NOTICE: For performance reasons, this utility's {@link AsyncRetryStrategy}
* implementation assumes the attempt always start from 1 and will only increase by 1 each time.
*/
public class AsyncRetryStrategies {
public static final NoRetryStrategy NO_RETRY_STRATEGY = new NoRetryStrategy();
/** NoRetryStrategy. */
private static class NoRetryStrategy implements AsyncRetryStrategy {
private static final long serialVersionUID = 1L;
private NoRetryStrategy() {}
@Override
public boolean canRetry(int currentAttempts) {
return false;
}
@Override
public long getBackoffTimeMillis(int currentAttempts) {
return -1;
}
@Override
public AsyncRetryPredicate getRetryPredicate() {
return new RetryPredicate(null, null);
}
}
private static class RetryPredicate implements AsyncRetryPredicate {
final Predicate> resultPredicate;
final Predicate exceptionPredicate;
public RetryPredicate(
Predicate> resultPredicate,
Predicate exceptionPredicate) {
this.resultPredicate = resultPredicate;
this.exceptionPredicate = exceptionPredicate;
}
@Override
public Optional>> resultPredicate() {
return Optional.ofNullable(resultPredicate);
}
@Override
public Optional> exceptionPredicate() {
return Optional.ofNullable(exceptionPredicate);
}
}
/** FixedDelayRetryStrategy. */
public static class FixedDelayRetryStrategy implements AsyncRetryStrategy {
private static final long serialVersionUID = 1L;
private final int maxAttempts;
private final long backoffTimeMillis;
private final Predicate> resultPredicate;
private final Predicate exceptionPredicate;
private FixedDelayRetryStrategy(
int maxAttempts,
long backoffTimeMillis,
Predicate> resultPredicate,
Predicate exceptionPredicate) {
this.maxAttempts = maxAttempts;
this.backoffTimeMillis = backoffTimeMillis;
this.resultPredicate = resultPredicate;
this.exceptionPredicate = exceptionPredicate;
}
@Override
public boolean canRetry(int currentAttempts) {
return currentAttempts <= maxAttempts;
}
@Override
public AsyncRetryPredicate getRetryPredicate() {
return new RetryPredicate(resultPredicate, exceptionPredicate);
}
@Override
public long getBackoffTimeMillis(int currentAttempts) {
return backoffTimeMillis;
}
}
/** FixedDelayRetryStrategyBuilder for building a FixedDelayRetryStrategy. */
public static class FixedDelayRetryStrategyBuilder {
private int maxAttempts;
private long backoffTimeMillis;
private Predicate> resultPredicate;
private Predicate exceptionPredicate;
public FixedDelayRetryStrategyBuilder(int maxAttempts, long backoffTimeMillis) {
Preconditions.checkArgument(
maxAttempts > 0, "maxAttempts should be greater than zero.");
Preconditions.checkArgument(
backoffTimeMillis > 0, "backoffTimeMillis should be greater than zero.");
this.maxAttempts = maxAttempts;
this.backoffTimeMillis = backoffTimeMillis;
}
public FixedDelayRetryStrategyBuilder ifResult(
@Nonnull Predicate> resultRetryPredicate) {
this.resultPredicate = resultRetryPredicate;
return this;
}
public FixedDelayRetryStrategyBuilder ifException(
@Nonnull Predicate exceptionRetryPredicate) {
this.exceptionPredicate = exceptionRetryPredicate;
return this;
}
public FixedDelayRetryStrategy build() {
return new FixedDelayRetryStrategy(
maxAttempts, backoffTimeMillis, resultPredicate, exceptionPredicate);
}
}
/** ExponentialBackoffDelayRetryStrategy. */
public static class ExponentialBackoffDelayRetryStrategy
implements AsyncRetryStrategy {
private static final long serialVersionUID = 1L;
private final int maxAttempts;
private final long maxRetryDelay;
private final long initialDelay;
private final double multiplier;
private final Predicate> resultPredicate;
private final Predicate exceptionPredicate;
private long lastRetryDelay;
public ExponentialBackoffDelayRetryStrategy(
int maxAttempts,
long initialDelay,
long maxRetryDelay,
double multiplier,
Predicate> resultPredicate,
Predicate exceptionPredicate) {
this.maxAttempts = maxAttempts;
this.maxRetryDelay = maxRetryDelay;
this.multiplier = multiplier;
this.resultPredicate = resultPredicate;
this.exceptionPredicate = exceptionPredicate;
this.initialDelay = initialDelay;
this.lastRetryDelay = initialDelay;
}
@Override
public boolean canRetry(int currentAttempts) {
return currentAttempts <= maxAttempts;
}
@Override
public long getBackoffTimeMillis(int currentAttempts) {
if (currentAttempts <= 1) {
// reset to initialDelay
this.lastRetryDelay = initialDelay;
return lastRetryDelay;
}
long backoff = Math.min((long) (lastRetryDelay * multiplier), maxRetryDelay);
this.lastRetryDelay = backoff;
return backoff;
}
@Override
public AsyncRetryPredicate getRetryPredicate() {
return new RetryPredicate(resultPredicate, exceptionPredicate);
}
}
/**
* ExponentialBackoffDelayRetryStrategyBuilder for building a
* ExponentialBackoffDelayRetryStrategy.
*/
public static class ExponentialBackoffDelayRetryStrategyBuilder {
private final int maxAttempts;
private final long initialDelay;
private final long maxRetryDelay;
private final double multiplier;
private Predicate> resultPredicate;
private Predicate exceptionPredicate;
public ExponentialBackoffDelayRetryStrategyBuilder(
int maxAttempts, long initialDelay, long maxRetryDelay, double multiplier) {
this.maxAttempts = maxAttempts;
this.initialDelay = initialDelay;
this.maxRetryDelay = maxRetryDelay;
this.multiplier = multiplier;
}
public ExponentialBackoffDelayRetryStrategyBuilder ifResult(
@Nonnull Predicate> resultRetryPredicate) {
this.resultPredicate = resultRetryPredicate;
return this;
}
public ExponentialBackoffDelayRetryStrategyBuilder ifException(
@Nonnull Predicate exceptionRetryPredicate) {
this.exceptionPredicate = exceptionRetryPredicate;
return this;
}
public ExponentialBackoffDelayRetryStrategy build() {
return new ExponentialBackoffDelayRetryStrategy(
maxAttempts,
initialDelay,
maxRetryDelay,
multiplier,
resultPredicate,
exceptionPredicate);
}
}
}