1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.gbif.ws.client;
15
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18
19 import feign.RetryableException;
20 import feign.Retryer;
21
22 @SuppressWarnings("unused")
23 public class ClientRetryer implements Retryer {
24
25 private static final Logger LOG = LoggerFactory.getLogger(ClientRetryer.class);
26
27 private final int maxAttempts;
28 private final long period;
29 private final double multiplier;
30 int attempt;
31 long sleptForMillis;
32
33 public ClientRetryer() {
34 this(1000, 3, 1.5);
35 }
36
37 public ClientRetryer(long period, int maxAttempts, double multiplier) {
38 this.period = period;
39 this.maxAttempts = maxAttempts;
40 this.multiplier = multiplier;
41 this.attempt = 1;
42 }
43
44 protected long currentTimeMillis() {
45 return System.currentTimeMillis();
46 }
47
48 @Override
49 public void continueOrPropagate(RetryableException e) {
50 if (attempt++ >= maxAttempts) {
51 LOG.error(
52 "All {} retry attempts failed. Giving up. Last execution was: '{}: {}'",
53 maxAttempts,
54 e.getClass().getSimpleName(),
55 e.getMessage());
56 throw e;
57 }
58
59 long interval;
60 if (e.retryAfter() != null) {
61 interval = e.retryAfter().getTime() - currentTimeMillis();
62 if (interval < 0) {
63 return;
64 }
65 } else {
66 interval = nextMaxInterval();
67 }
68 try {
69 Thread.sleep(interval);
70 } catch (InterruptedException ignored) {
71 Thread.currentThread().interrupt();
72 throw e;
73 }
74 sleptForMillis += interval;
75 }
76
77
78
79
80
81
82
83
84 long nextMaxInterval() {
85 return (long) (period * Math.pow(multiplier, attempt - 1));
86 }
87
88 @Override
89 public Retryer clone() {
90 return new ClientRetryer(period, maxAttempts, multiplier);
91 }
92 }