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.hc.client5.http.impl.cache;
28
29 import java.io.IOException;
30 import java.util.concurrent.Future;
31 import java.util.concurrent.RejectedExecutionException;
32 import java.util.concurrent.ScheduledExecutorService;
33 import java.util.concurrent.atomic.AtomicReference;
34
35 import org.apache.hc.client5.http.async.AsyncExecCallback;
36 import org.apache.hc.client5.http.impl.Operations;
37 import org.apache.hc.client5.http.schedule.SchedulingStrategy;
38 import org.apache.hc.core5.http.EntityDetails;
39 import org.apache.hc.core5.http.HttpException;
40 import org.apache.hc.core5.http.HttpResponse;
41 import org.apache.hc.core5.http.HttpStatus;
42 import org.apache.hc.core5.http.nio.AsyncDataConsumer;
43 import org.apache.hc.core5.util.TimeValue;
44 import org.apache.hc.core5.util.Timeout;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49
50
51
52 class DefaultAsyncCacheRevalidator extends CacheRevalidatorBase {
53
54 private static final Logger LOG = LoggerFactory.getLogger(DefaultAsyncCacheRevalidator.class);
55
56 interface RevalidationCall {
57
58 void execute(AsyncExecCallback asyncExecCallback);
59 }
60
61 static class InternalScheduledExecutor implements ScheduledExecutor {
62
63 private final ScheduledExecutor executor;
64
65 InternalScheduledExecutor(final ScheduledExecutor executor) {
66 this.executor = executor;
67 }
68
69 @Override
70 public Future<?> schedule(final Runnable command, final TimeValue timeValue) throws RejectedExecutionException {
71 if (timeValue.toMilliseconds() <= 0) {
72 command.run();
73 return new Operations.CompletedFuture<Void>(null);
74 }
75 return executor.schedule(command, timeValue);
76 }
77
78 @Override
79 public void shutdown() {
80 executor.shutdown();
81 }
82
83 @Override
84 public void awaitTermination(final Timeout timeout) throws InterruptedException {
85 executor.awaitTermination(timeout);
86 }
87
88 }
89
90 private final CacheKeyGenerator cacheKeyGenerator;
91
92
93
94
95
96 public DefaultAsyncCacheRevalidator(
97 final ScheduledExecutor scheduledExecutor,
98 final SchedulingStrategy schedulingStrategy) {
99 super(new InternalScheduledExecutor(scheduledExecutor), schedulingStrategy);
100 this.cacheKeyGenerator = CacheKeyGenerator.INSTANCE;
101
102 }
103
104
105
106
107
108 public DefaultAsyncCacheRevalidator(
109 final ScheduledExecutorService executorService,
110 final SchedulingStrategy schedulingStrategy) {
111 this(wrap(executorService), schedulingStrategy);
112 }
113
114
115
116
117 public void revalidateCacheEntry(
118 final String cacheKey ,
119 final AsyncExecCallback asyncExecCallback,
120 final RevalidationCall call) {
121 scheduleRevalidation(cacheKey, new Runnable() {
122
123 @Override
124 public void run() {
125 call.execute(new AsyncExecCallback() {
126
127 private final AtomicReference<HttpResponse> responseRef = new AtomicReference<>(null);
128
129 @Override
130 public AsyncDataConsumer handleResponse(
131 final HttpResponse response,
132 final EntityDetails entityDetails) throws HttpException, IOException {
133 responseRef.set(response);
134 return asyncExecCallback.handleResponse(response, entityDetails);
135 }
136
137 @Override
138 public void handleInformationResponse(
139 final HttpResponse response) throws HttpException, IOException {
140 asyncExecCallback.handleInformationResponse(response);
141 }
142
143 @Override
144 public void completed() {
145 final HttpResponse httpResponse = responseRef.getAndSet(null);
146 if (httpResponse != null && httpResponse.getCode() < HttpStatus.SC_SERVER_ERROR && !isStale(httpResponse)) {
147 jobSuccessful(cacheKey);
148 } else {
149 jobFailed(cacheKey);
150 }
151 asyncExecCallback.completed();
152 }
153
154 @Override
155 public void failed(final Exception cause) {
156 if (cause instanceof IOException) {
157 LOG.debug("Asynchronous revalidation failed due to I/O error", cause);
158 } else if (cause instanceof HttpException) {
159 LOG.error("HTTP protocol exception during asynchronous revalidation", cause);
160 } else {
161 LOG.error("Unexpected runtime exception thrown during asynchronous revalidation", cause);
162 }
163 try {
164 jobFailed(cacheKey);
165 } finally {
166 asyncExecCallback.failed(cause);
167 }
168 }
169
170 });
171 }
172
173 });
174 }
175
176 }