001
002package io.vrap.rmf.base.client.http;
003
004import static io.vrap.rmf.base.client.http.HttpStatusCode.INTERNAL_SERVER_ERROR_500;
005import static io.vrap.rmf.base.client.http.HttpStatusCode.SERVICE_UNAVAILABLE_503;
006import static java.util.Arrays.asList;
007
008import java.util.List;
009import java.util.concurrent.ExecutorService;
010import java.util.concurrent.ScheduledExecutorService;
011
012import io.vrap.rmf.base.client.ApiHttpException;
013
014import dev.failsafe.spi.Scheduler;
015
016/**
017 * Middleware for retrying of a requests upon configured response status codes and/or exceptions
018 */
019public interface RetryRequestMiddleware extends Middleware {
020    int DEFAULT_MAX_DELAY = 60000;
021    int DEFAULT_INITIAL_DELAY = 200;
022    List<Integer> DEFAULT_RETRY_STATUS_CODES = asList(INTERNAL_SERVER_ERROR_500, SERVICE_UNAVAILABLE_503);
023
024    public static RetryRequestMiddleware of(final int maxRetries) {
025        return new RetryMiddleware(maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, DEFAULT_RETRY_STATUS_CODES,
026            null);
027    }
028
029    public static RetryRequestMiddleware of(final int maxRetries, final List<Integer> statusCodes) {
030        return new RetryMiddleware(maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes, null);
031    }
032
033    public static RetryRequestMiddleware of(final int maxRetries, final List<Integer> statusCodes,
034            final List<Class<? extends Throwable>> failures) {
035        return new RetryMiddleware(maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes, failures);
036    }
037
038    public static RetryRequestMiddleware of(final int maxRetries, final long delay, final long maxDelay) {
039        return new RetryMiddleware(maxRetries, delay, maxDelay, DEFAULT_RETRY_STATUS_CODES, null);
040    }
041
042    public static RetryRequestMiddleware of(final int maxRetries, final long delay, final long maxDelay,
043            final List<Integer> statusCodes) {
044        return new RetryMiddleware(maxRetries, delay, maxDelay, statusCodes, null);
045    }
046
047    public static RetryRequestMiddleware of(final int maxRetries, final long delay, final long maxDelay,
048            final List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
049        return new RetryMiddleware(maxRetries, delay, maxDelay,
050            handleFailures(failures).andThen(handleStatusCodes(statusCodes)));
051    }
052
053    public static RetryRequestMiddleware of(final int maxRetries, final long delay, final long maxDelay,
054            final FailsafeRetryPolicyBuilderOptions fn) {
055        return new RetryMiddleware(maxRetries, delay, maxDelay, fn);
056    }
057
058    public static RetryRequestMiddleware of(final Scheduler scheduler, final int maxRetries) {
059        return new RetryMiddleware(scheduler, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY,
060            DEFAULT_RETRY_STATUS_CODES, null);
061    }
062
063    public static RetryRequestMiddleware of(final Scheduler scheduler, final int maxRetries,
064            final List<Integer> statusCodes) {
065        return new RetryMiddleware(scheduler, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes, null);
066    }
067
068    public static RetryRequestMiddleware of(final Scheduler scheduler, final int maxRetries,
069            final List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
070        return new RetryMiddleware(scheduler, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes,
071            failures);
072    }
073
074    public static RetryRequestMiddleware of(final Scheduler scheduler, final int maxRetries, final long delay,
075            final long maxDelay) {
076        return new RetryMiddleware(scheduler, maxRetries, delay, maxDelay, DEFAULT_RETRY_STATUS_CODES, null);
077    }
078
079    public static RetryRequestMiddleware of(final Scheduler scheduler, final int maxRetries, final long delay,
080            final long maxDelay, final List<Integer> statusCodes) {
081        return new RetryMiddleware(scheduler, maxRetries, delay, maxDelay, statusCodes, null);
082    }
083
084    public static RetryRequestMiddleware of(final Scheduler scheduler, final int maxRetries, final long delay,
085            final long maxDelay, final List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
086        return new RetryMiddleware(scheduler, maxRetries, delay, maxDelay,
087            handleFailures(failures).andThen(handleStatusCodes(statusCodes)));
088    }
089
090    public static RetryRequestMiddleware of(final Scheduler scheduler, final int maxRetries, final long delay,
091            final long maxDelay, final FailsafeRetryPolicyBuilderOptions fn) {
092        return new RetryMiddleware(scheduler, maxRetries, delay, maxDelay, fn);
093    }
094
095    public static RetryRequestMiddleware of(final ScheduledExecutorService executorService, final int maxRetries) {
096        return new RetryMiddleware(executorService, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY,
097            DEFAULT_RETRY_STATUS_CODES, null);
098    }
099
100    public static RetryRequestMiddleware of(final ScheduledExecutorService executorService, final int maxRetries,
101            final List<Integer> statusCodes) {
102        return new RetryMiddleware(executorService, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes,
103            null);
104    }
105
106    public static RetryRequestMiddleware of(final ScheduledExecutorService executorService, final int maxRetries,
107            final List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
108        return new RetryMiddleware(executorService, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes,
109            failures);
110    }
111
112    public static RetryRequestMiddleware of(final ScheduledExecutorService executorService, final int maxRetries,
113            final long delay, final long maxDelay) {
114        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay, DEFAULT_RETRY_STATUS_CODES, null);
115    }
116
117    public static RetryRequestMiddleware of(final ScheduledExecutorService executorService, final int maxRetries,
118            final long delay, final long maxDelay, final List<Integer> statusCodes) {
119        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay, statusCodes, null);
120    }
121
122    public static RetryRequestMiddleware of(final ScheduledExecutorService executorService, final int maxRetries,
123            final long delay, final long maxDelay, final List<Integer> statusCodes,
124            final List<Class<? extends Throwable>> failures) {
125        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay,
126            handleFailures(failures).andThen(handleStatusCodes(statusCodes)));
127    }
128
129    public static RetryRequestMiddleware of(final ScheduledExecutorService executorService, final int maxRetries,
130            final long delay, final long maxDelay, final FailsafeRetryPolicyBuilderOptions fn) {
131        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay, fn);
132    }
133
134    public static RetryRequestMiddleware of(final ExecutorService executorService, final int maxRetries) {
135        return new RetryMiddleware(executorService, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY,
136            DEFAULT_RETRY_STATUS_CODES, null);
137    }
138
139    public static RetryRequestMiddleware of(final ExecutorService executorService, final int maxRetries,
140            final List<Integer> statusCodes) {
141        return new RetryMiddleware(executorService, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes,
142            null);
143    }
144
145    public static RetryRequestMiddleware of(final ExecutorService executorService, final int maxRetries,
146            final List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
147        return new RetryMiddleware(executorService, maxRetries, DEFAULT_INITIAL_DELAY, DEFAULT_MAX_DELAY, statusCodes,
148            failures);
149    }
150
151    public static RetryRequestMiddleware of(final ExecutorService executorService, final int maxRetries,
152            final long delay, final long maxDelay) {
153        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay, DEFAULT_RETRY_STATUS_CODES, null);
154    }
155
156    public static RetryRequestMiddleware of(final ExecutorService executorService, final int maxRetries,
157            final long delay, final long maxDelay, final List<Integer> statusCodes) {
158        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay, statusCodes, null);
159    }
160
161    public static RetryRequestMiddleware of(final ExecutorService executorService, final int maxRetries,
162            final long delay, final long maxDelay, final List<Integer> statusCodes,
163            final List<Class<? extends Throwable>> failures) {
164        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay,
165            handleFailures(failures).andThen(handleStatusCodes(statusCodes)));
166    }
167
168    public static RetryRequestMiddleware of(final ExecutorService executorService, final int maxRetries,
169            final long delay, final long maxDelay, final FailsafeRetryPolicyBuilderOptions fn) {
170        return new RetryMiddleware(executorService, maxRetries, delay, maxDelay, fn);
171    }
172
173    public static FailsafeRetryPolicyBuilderOptions handleFailures(final List<Class<? extends Throwable>> failures) {
174        return builder -> {
175            if (failures != null) {
176                builder.handle(failures);
177            }
178            return builder;
179        };
180    }
181
182    public static FailsafeRetryPolicyBuilderOptions handleStatusCodes(final List<Integer> statusCodes) {
183        return builder -> builder.handleIf((response, throwable) -> {
184            if (throwable instanceof ApiHttpException) {
185                return statusCodes.contains(((ApiHttpException) throwable).getStatusCode());
186            }
187            return statusCodes.contains(response.getStatusCode());
188        });
189    }
190}