1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.impl.client.cache;
28
29 import java.util.concurrent.ScheduledExecutorService;
30 import java.util.concurrent.ScheduledThreadPoolExecutor;
31 import java.util.concurrent.TimeUnit;
32
33 import org.apache.http.annotation.Contract;
34 import org.apache.http.annotation.ThreadingBehavior;
35 import org.apache.http.util.Args;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 @Contract(threading = ThreadingBehavior.SAFE)
61 public class ExponentialBackOffSchedulingStrategy implements SchedulingStrategy {
62
63 public static final long DEFAULT_BACK_OFF_RATE = 10;
64 public static final long DEFAULT_INITIAL_EXPIRY_IN_MILLIS = TimeUnit.SECONDS.toMillis(6);
65 public static final long DEFAULT_MAX_EXPIRY_IN_MILLIS = TimeUnit.SECONDS.toMillis(86400);
66
67 private final long backOffRate;
68 private final long initialExpiryInMillis;
69 private final long maxExpiryInMillis;
70
71 private final ScheduledExecutorService executor;
72
73
74
75
76
77
78
79
80
81 public ExponentialBackOffSchedulingStrategy(final CacheConfig cacheConfig) {
82 this(cacheConfig,
83 DEFAULT_BACK_OFF_RATE,
84 DEFAULT_INITIAL_EXPIRY_IN_MILLIS,
85 DEFAULT_MAX_EXPIRY_IN_MILLIS);
86 }
87
88
89
90
91
92
93
94
95
96
97
98
99 public ExponentialBackOffSchedulingStrategy(
100 final CacheConfig cacheConfig,
101 final long backOffRate,
102 final long initialExpiryInMillis,
103 final long maxExpiryInMillis) {
104 this(createThreadPoolFromCacheConfig(cacheConfig),
105 backOffRate,
106 initialExpiryInMillis,
107 maxExpiryInMillis);
108 }
109
110 private static ScheduledThreadPoolExecutor createThreadPoolFromCacheConfig(
111 final CacheConfig cacheConfig) {
112 final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(
113 cacheConfig.getAsynchronousWorkersMax());
114 scheduledThreadPoolExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
115 return scheduledThreadPoolExecutor;
116 }
117
118 ExponentialBackOffSchedulingStrategy(
119 final ScheduledExecutorService executor,
120 final long backOffRate,
121 final long initialExpiryInMillis,
122 final long maxExpiryInMillis) {
123 this.executor = Args.notNull(executor, "Executor");
124 this.backOffRate = Args.notNegative(backOffRate, "BackOffRate");
125 this.initialExpiryInMillis = Args.notNegative(initialExpiryInMillis, "InitialExpiryInMillis");
126 this.maxExpiryInMillis = Args.notNegative(maxExpiryInMillis, "MaxExpiryInMillis");
127 }
128
129 @Override
130 public void schedule(
131 final AsynchronousValidationRequest revalidationRequest) {
132 Args.notNull(revalidationRequest, "RevalidationRequest");
133 final int consecutiveFailedAttempts = revalidationRequest.getConsecutiveFailedAttempts();
134 final long delayInMillis = calculateDelayInMillis(consecutiveFailedAttempts);
135 executor.schedule(revalidationRequest, delayInMillis, TimeUnit.MILLISECONDS);
136 }
137
138 @Override
139 public void close() {
140 executor.shutdown();
141 }
142
143 public long getBackOffRate() {
144 return backOffRate;
145 }
146
147 public long getInitialExpiryInMillis() {
148 return initialExpiryInMillis;
149 }
150
151 public long getMaxExpiryInMillis() {
152 return maxExpiryInMillis;
153 }
154
155 protected long calculateDelayInMillis(final int consecutiveFailedAttempts) {
156 if (consecutiveFailedAttempts > 0) {
157 final long delayInSeconds = (long) (initialExpiryInMillis *
158 Math.pow(backOffRate, consecutiveFailedAttempts - 1));
159 return Math.min(delayInSeconds, maxExpiryInMillis);
160 }
161 else {
162 return 0;
163 }
164 }
165
166
167
168
169 @Deprecated
170 protected static <T> T checkNotNull(final String parameterName, final T value) {
171 if (value == null) {
172 throw new IllegalArgumentException(parameterName + " may not be null");
173 }
174 return value;
175 }
176
177
178
179
180 @Deprecated
181 protected static long checkNotNegative(final String parameterName, final long value) {
182 if (value < 0) {
183 throw new IllegalArgumentException(parameterName + " may not be negative");
184 }
185 return value;
186 }
187 }