View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.client5.http.impl.cache;
28  
29  
30  import static org.junit.jupiter.api.Assertions.assertEquals;
31  import static org.junit.jupiter.api.Assertions.assertFalse;
32  import static org.junit.jupiter.api.Assertions.assertSame;
33  import static org.junit.jupiter.api.Assertions.assertTrue;
34  
35  import java.time.Instant;
36  
37  import org.apache.hc.client5.http.cache.HttpCacheEntry;
38  import org.apache.hc.client5.http.utils.DateUtils;
39  import org.apache.hc.core5.http.Header;
40  import org.apache.hc.core5.http.HttpHeaders;
41  import org.apache.hc.core5.http.HttpRequest;
42  import org.apache.hc.core5.http.message.BasicHeader;
43  import org.apache.hc.core5.http.message.BasicHttpRequest;
44  import org.apache.hc.core5.util.TimeValue;
45  import org.junit.jupiter.api.BeforeEach;
46  import org.junit.jupiter.api.Test;
47  
48  public class TestCacheValidityPolicy {
49  
50      private CacheValidityPolicy impl;
51      private Instant now;
52      private Instant oneSecondAgo;
53      private Instant sixSecondsAgo;
54      private Instant tenSecondsAgo;
55      private Instant elevenSecondsAgo;
56  
57      @BeforeEach
58      public void setUp() {
59          impl = new CacheValidityPolicy();
60          now = Instant.now();
61          oneSecondAgo = now.minusSeconds(1);
62          sixSecondsAgo = now.minusSeconds(6);
63          tenSecondsAgo = now.minusSeconds(10);
64          elevenSecondsAgo = now.minusSeconds(11);
65      }
66  
67      @Test
68      public void testApparentAgeIsMaxIntIfDateHeaderNotPresent() {
69          final Header[] headers = {
70                  new BasicHeader("Server", "MockServer/1.0")
71          };
72          final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
73          assertEquals(CacheValidityPolicy.MAX_AGE, impl.getApparentAge(entry));
74      }
75  
76      @Test
77      public void testApparentAgeIsResponseReceivedTimeLessDateHeader() {
78          final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)) };
79  
80          final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo, headers);
81          assertEquals(TimeValue.ofSeconds(4), impl.getApparentAge(entry));
82      }
83  
84      @Test
85      public void testNegativeApparentAgeIsBroughtUpToZero() {
86          final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils.formatStandardDate(sixSecondsAgo)) };
87          final HttpCacheEntry entry  = HttpTestUtils.makeCacheEntry(now, tenSecondsAgo, headers);
88          assertEquals(TimeValue.ofSeconds(0), impl.getApparentAge(entry));
89      }
90  
91      @Test
92      public void testCorrectedReceivedAgeIsAgeHeaderIfLarger() {
93          final Header[] headers = new Header[] { new BasicHeader("Age", "10"), };
94          final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
95          impl = new CacheValidityPolicy() {
96              @Override
97              protected TimeValue getApparentAge(final HttpCacheEntry ent) {
98                  return TimeValue.ofSeconds(6);
99              }
100         };
101         assertEquals(TimeValue.ofSeconds(10), impl.getCorrectedReceivedAge(entry));
102     }
103 
104     @Test
105     public void testCorrectedReceivedAgeIsApparentAgeIfLarger() {
106         final Header[] headers = new Header[] { new BasicHeader("Age", "6"), };
107         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
108         impl = new CacheValidityPolicy() {
109             @Override
110             protected TimeValue getApparentAge(final HttpCacheEntry ent) {
111                 return TimeValue.ofSeconds(10);
112             }
113         };
114         assertEquals(TimeValue.ofSeconds(10), impl.getCorrectedReceivedAge(entry));
115     }
116 
117     @Test
118     public void testResponseDelayIsDifferenceBetweenResponseAndRequestTimes() {
119         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, sixSecondsAgo);
120         assertEquals(TimeValue.ofSeconds(4), impl.getResponseDelay(entry));
121     }
122 
123     @Test
124     public void testCorrectedInitialAgeIsCorrectedReceivedAgePlusResponseDelay() {
125         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
126         impl = new CacheValidityPolicy() {
127             @Override
128             protected TimeValue getCorrectedReceivedAge(final HttpCacheEntry ent) {
129                 return TimeValue.ofSeconds(7);
130             }
131 
132             @Override
133             protected TimeValue getResponseDelay(final HttpCacheEntry ent) {
134                 return TimeValue.ofSeconds(13);
135             }
136         };
137         assertEquals(TimeValue.ofSeconds(20), impl.getCorrectedInitialAge(entry));
138     }
139 
140     @Test
141     public void testResidentTimeSecondsIsTimeSinceResponseTime() {
142         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, sixSecondsAgo);
143         assertEquals(TimeValue.ofSeconds(6), impl.getResidentTime(entry, now));
144     }
145 
146     @Test
147     public void testCurrentAgeIsCorrectedInitialAgePlusResidentTime() {
148         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
149         impl = new CacheValidityPolicy() {
150             @Override
151             protected TimeValue getCorrectedInitialAge(final HttpCacheEntry ent) {
152                 return TimeValue.ofSeconds(11);
153             }
154             @Override
155             protected TimeValue getResidentTime(final HttpCacheEntry ent, final Instant d) {
156                 return TimeValue.ofSeconds(17);
157             }
158         };
159         assertEquals(TimeValue.ofSeconds(28), impl.getCurrentAge(entry, Instant.now()));
160     }
161 
162     @Test
163     public void testFreshnessLifetimeIsSMaxAgeIfPresent() {
164         final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10") };
165         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
166         assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
167     }
168 
169     @Test
170     public void testFreshnessLifetimeIsMaxAgeIfPresent() {
171         final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10") };
172         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
173         assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
174     }
175 
176     @Test
177     public void testFreshnessLifetimeIsMostRestrictiveOfMaxAgeAndSMaxAge() {
178         Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
179                 new BasicHeader("Cache-Control", "s-maxage=20") };
180         HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
181         assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
182 
183         headers = new Header[] { new BasicHeader("Cache-Control", "max-age=20"),
184                 new BasicHeader("Cache-Control", "s-maxage=10") };
185         entry = HttpTestUtils.makeCacheEntry(headers);
186         assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
187     }
188 
189     @Test
190     public void testFreshnessLifetimeIsMaxAgeEvenIfExpiresIsPresent() {
191         final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
192                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
193                 new BasicHeader("Expires", DateUtils.formatStandardDate(sixSecondsAgo)) };
194 
195         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
196         assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
197     }
198 
199     @Test
200     public void testFreshnessLifetimeIsSMaxAgeEvenIfExpiresIsPresent() {
201         final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10"),
202                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
203                 new BasicHeader("Expires", DateUtils.formatStandardDate(sixSecondsAgo)) };
204 
205         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
206         assertEquals(TimeValue.ofSeconds(10), impl.getFreshnessLifetime(entry));
207     }
208 
209     @Test
210     public void testFreshnessLifetimeIsFromExpiresHeaderIfNoMaxAge() {
211         final Header[] headers = new Header[] {
212                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
213                 new BasicHeader("Expires", DateUtils.formatStandardDate(sixSecondsAgo)) };
214 
215         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
216         assertEquals(TimeValue.ofSeconds(4), impl.getFreshnessLifetime(entry));
217     }
218 
219     @Test
220     public void testHeuristicFreshnessLifetime() {
221         final Header[] headers = new Header[] {
222                 new BasicHeader("Date", DateUtils.formatStandardDate(oneSecondAgo)),
223                 new BasicHeader("Last-Modified", DateUtils.formatStandardDate(elevenSecondsAgo))
224         };
225         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
226         assertEquals(TimeValue.ofSeconds(1), impl.getHeuristicFreshnessLifetime(entry, 0.1f, TimeValue.ZERO_MILLISECONDS));
227     }
228 
229     @Test
230     public void testHeuristicFreshnessLifetimeDefaultsProperly() {
231         final TimeValue defaultFreshness = TimeValue.ofSeconds(10);
232         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
233         assertEquals(defaultFreshness, impl.getHeuristicFreshnessLifetime(entry, 0.1f, defaultFreshness));
234     }
235 
236     @Test
237     public void testHeuristicFreshnessLifetimeIsNonNegative() {
238         final Header[] headers = new Header[] {
239                 new BasicHeader("Date", DateUtils.formatStandardDate(elevenSecondsAgo)),
240                 new BasicHeader("Last-Modified", DateUtils.formatStandardDate(oneSecondAgo))
241         };
242 
243         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
244         assertTrue(TimeValue.isNonNegative(impl.getHeuristicFreshnessLifetime(entry, 0.1f, TimeValue.ofSeconds(10))));
245     }
246 
247     @Test
248     public void testResponseIsFreshIfFreshnessLifetimeExceedsCurrentAge() {
249         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
250         impl = new CacheValidityPolicy() {
251             @Override
252             public TimeValue getCurrentAge(final HttpCacheEntry e, final Instant d) {
253                 assertSame(entry, e);
254                 assertEquals(now, d);
255                 return TimeValue.ofSeconds(6);
256             }
257             @Override
258             public TimeValue getFreshnessLifetime(final HttpCacheEntry e) {
259                 assertSame(entry, e);
260                 return TimeValue.ofSeconds(10);
261             }
262         };
263         assertTrue(impl.isResponseFresh(entry, now));
264     }
265 
266     @Test
267     public void testResponseIsNotFreshIfFreshnessLifetimeEqualsCurrentAge() {
268         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
269         impl = new CacheValidityPolicy() {
270             @Override
271             public TimeValue getCurrentAge(final HttpCacheEntry e, final Instant d) {
272                 assertEquals(now, d);
273                 assertSame(entry, e);
274                 return TimeValue.ofSeconds(6);
275             }
276             @Override
277             public TimeValue getFreshnessLifetime(final HttpCacheEntry e) {
278                 assertSame(entry, e);
279                 return TimeValue.ofSeconds(6);
280             }
281         };
282         assertFalse(impl.isResponseFresh(entry, now));
283     }
284 
285     @Test
286     public void testResponseIsNotFreshIfCurrentAgeExceedsFreshnessLifetime() {
287         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry();
288         impl = new CacheValidityPolicy() {
289             @Override
290             public TimeValue getCurrentAge(final HttpCacheEntry e, final Instant d) {
291                 assertEquals(now, d);
292                 assertSame(entry, e);
293                 return TimeValue.ofSeconds(10);
294             }
295             @Override
296             public TimeValue getFreshnessLifetime(final HttpCacheEntry e) {
297                 assertSame(entry, e);
298                 return TimeValue.ofSeconds(6);
299             }
300         };
301         assertFalse(impl.isResponseFresh(entry, now));
302     }
303 
304     @Test
305     public void testCacheEntryIsRevalidatableIfHeadersIncludeETag() {
306         final Header[] headers = {
307                 new BasicHeader("Expires", DateUtils.formatStandardDate(Instant.now())),
308                 new BasicHeader("ETag", "somevalue")};
309         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
310         assertTrue(impl.isRevalidatable(entry));
311     }
312 
313     @Test
314     public void testCacheEntryIsRevalidatableIfHeadersIncludeLastModifiedDate() {
315         final Header[] headers = {
316                 new BasicHeader("Expires", DateUtils.formatStandardDate(Instant.now())),
317                 new BasicHeader("Last-Modified", DateUtils.formatStandardDate(Instant.now())) };
318         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
319         assertTrue(impl.isRevalidatable(entry));
320     }
321 
322     @Test
323     public void testCacheEntryIsNotRevalidatableIfNoAppropriateHeaders() {
324         final Header[] headers =  {
325                 new BasicHeader("Expires", DateUtils.formatStandardDate(Instant.now())),
326                 new BasicHeader("Cache-Control", "public") };
327         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
328         assertFalse(impl.isRevalidatable(entry));
329     }
330 
331     @Test
332     public void testMissingContentLengthDoesntInvalidateEntry() {
333         final int contentLength = 128;
334         final Header[] headers = {}; // no Content-Length header
335         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers, HttpTestUtils.getRandomBytes(contentLength));
336         assertTrue(impl.contentLengthHeaderMatchesActualLength(entry));
337     }
338 
339     @Test
340     public void testCorrectContentLengthDoesntInvalidateEntry() {
341         final int contentLength = 128;
342         final Header[] headers = { new BasicHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(contentLength)) };
343         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers, HttpTestUtils.getRandomBytes(contentLength));
344         assertTrue(impl.contentLengthHeaderMatchesActualLength(entry));
345     }
346 
347     @Test
348     public void testWrongContentLengthInvalidatesEntry() {
349         final int contentLength = 128;
350         final Header[] headers = {new BasicHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(contentLength+1))};
351         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers, HttpTestUtils.getRandomBytes(contentLength));
352         assertFalse(impl.contentLengthHeaderMatchesActualLength(entry));
353     }
354 
355     @Test
356     public void testNullResourceInvalidatesEntry() {
357         final int contentLength = 128;
358         final Header[] headers = {new BasicHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(contentLength))};
359         final HttpCacheEntry entry = HttpTestUtils.makeHeadCacheEntry(headers);
360         assertFalse(impl.contentLengthHeaderMatchesActualLength(entry));
361     }
362 
363     @Test
364     public void testNegativeAgeHeaderValueReturnsMaxAge() {
365         final Header[] headers = new Header[] { new BasicHeader("Age", "-100") };
366         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
367         // in seconds
368         assertEquals(CacheValidityPolicy.MAX_AGE.toSeconds(), impl.getAgeValue(entry));
369     }
370 
371     @Test
372     public void testMalformedAgeHeaderValueReturnsMaxAge() {
373         final Header[] headers = new Header[] { new BasicHeader("Age", "asdf") };
374         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
375         // in seconds
376         assertEquals(CacheValidityPolicy.MAX_AGE.toSeconds(), impl.getAgeValue(entry));
377     }
378 
379     @Test
380     public void testMalformedCacheControlMaxAgeHeaderReturnsZero() {
381         final Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=asdf") };
382         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
383         // in seconds
384         assertEquals(0L, impl.getMaxAge(entry));
385     }
386 
387     @Test
388     public void testMustRevalidateIsFalseIfDirectiveNotPresent() {
389         final Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
390         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
391         assertFalse(impl.mustRevalidate(entry));
392     }
393 
394     @Test
395     public void testMustRevalidateIsTrueWhenDirectiveIsPresent() {
396         final Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, must-revalidate") };
397         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
398         assertTrue(impl.mustRevalidate(entry));
399     }
400 
401     @Test
402     public void testProxyRevalidateIsFalseIfDirectiveNotPresent() {
403         final Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
404         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
405         assertFalse(impl.proxyRevalidate(entry));
406     }
407 
408     @Test
409     public void testProxyRevalidateIsTrueWhenDirectiveIsPresent() {
410         final Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, proxy-revalidate") };
411         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
412         assertTrue(impl.proxyRevalidate(entry));
413     }
414 
415     @Test
416     public void testMayReturnStaleIfErrorInResponseIsTrueWithinStaleness(){
417         final Header[] headers = new Header[] {
418                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
419                 new BasicHeader("Cache-Control", "max-age=5, stale-if-error=15")
420         };
421         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
422         final HttpRequest req = new BasicHttpRequest("GET","/");
423         assertTrue(impl.mayReturnStaleIfError(req, entry, now));
424     }
425 
426     @Test
427     public void testMayReturnStaleIfErrorInRequestIsTrueWithinStaleness(){
428         final Header[] headers = new Header[] {
429                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
430                 new BasicHeader("Cache-Control", "max-age=5")
431         };
432         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
433         final HttpRequest req = new BasicHttpRequest("GET","/");
434         req.setHeader("Cache-Control","stale-if-error=15");
435         assertTrue(impl.mayReturnStaleIfError(req, entry, now));
436     }
437 
438     @Test
439     public void testMayNotReturnStaleIfErrorInResponseAndAfterResponseWindow(){
440         final Header[] headers = new Header[] {
441                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
442                 new BasicHeader("Cache-Control", "max-age=5, stale-if-error=1")
443         };
444         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
445         final HttpRequest req = new BasicHttpRequest("GET","/");
446         assertFalse(impl.mayReturnStaleIfError(req, entry, now));
447     }
448 
449     @Test
450     public void testMayNotReturnStaleIfErrorInResponseAndAfterRequestWindow(){
451         final Header[] headers = new Header[] {
452                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
453                 new BasicHeader("Cache-Control", "max-age=5")
454         };
455         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
456         final HttpRequest req = new BasicHttpRequest("GET","/");
457         req.setHeader("Cache-Control","stale-if-error=1");
458         assertFalse(impl.mayReturnStaleIfError(req, entry, now));
459     }
460 
461     @Test
462     public void testMayReturnStaleWhileRevalidatingIsFalseWhenDirectiveIsAbsent() {
463         final Header[] headers = new Header[] { new BasicHeader("Cache-control", "public") };
464         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers);
465 
466         assertFalse(impl.mayReturnStaleWhileRevalidating(entry, now));
467     }
468 
469     @Test
470     public void testMayReturnStaleWhileRevalidatingIsTrueWhenWithinStaleness() {
471         final Header[] headers = new Header[] {
472                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
473                 new BasicHeader("Cache-Control", "max-age=5, stale-while-revalidate=15")
474         };
475         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
476 
477         assertTrue(impl.mayReturnStaleWhileRevalidating(entry, now));
478     }
479 
480     @Test
481     public void testMayReturnStaleWhileRevalidatingIsFalseWhenPastStaleness() {
482         final Instant twentyFiveSecondsAgo = now.minusSeconds(25);
483         final Header[] headers = new Header[] {
484                 new BasicHeader("Date", DateUtils.formatStandardDate(twentyFiveSecondsAgo)),
485                 new BasicHeader("Cache-Control", "max-age=5, stale-while-revalidate=15")
486         };
487         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
488 
489         assertFalse(impl.mayReturnStaleWhileRevalidating(entry, now));
490     }
491 
492     @Test
493     public void testMayReturnStaleWhileRevalidatingIsFalseWhenDirectiveEmpty() {
494         final Header[] headers = new Header[] {
495                 new BasicHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo)),
496                 new BasicHeader("Cache-Control", "max-age=5, stale-while-revalidate=")
497         };
498         final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(now, now, headers);
499 
500         assertFalse(impl.mayReturnStaleWhileRevalidating(entry, now));
501     }
502 }