You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2018/01/02 11:46:58 UTC

httpcomponents-client git commit: HTTPCLIENT-1395: added config parameter to skip an extra cache entry freshness check upon cache update in case of a cache miss

Repository: httpcomponents-client
Updated Branches:
  refs/heads/master 194e4f528 -> c78032d63


HTTPCLIENT-1395: added config parameter to skip an extra cache entry freshness check upon cache update in case of a cache miss


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/c78032d6
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/c78032d6
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/c78032d6

Branch: refs/heads/master
Commit: c78032d638b19d0a44341e06561050401cc53aba
Parents: 194e4f5
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Mon Jan 1 18:31:23 2018 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Mon Jan 1 18:31:43 2018 +0100

----------------------------------------------------------------------
 .../http/impl/cache/AsyncCachingExec.java       | 117 ++++++++++---------
 .../hc/client5/http/impl/cache/CacheConfig.java |  41 +++++--
 .../hc/client5/http/impl/cache/CachingExec.java |  21 ++--
 3 files changed, 106 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/c78032d6/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AsyncCachingExec.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AsyncCachingExec.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AsyncCachingExec.java
index c812b12..59d6e07 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AsyncCachingExec.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AsyncCachingExec.java
@@ -486,72 +486,81 @@ public class AsyncCachingExec extends CachingExecBase implements AsyncExecChainH
             }
         }
 
-        @Override
-        public void completed() {
+        void triggerNewCacheEntryResponse(final HttpResponse backendResponse, final Date responseDate, final ByteArrayBuffer buffer) {
             final ComplexFuture<?> future = scope.future;
-            final CachingAsyncDataConsumer cachingDataConsumer = cachingConsumerRef.getAndSet(null);
-            if (cachingDataConsumer != null && !cachingDataConsumer.writtenThrough.get()) {
-                future.setDependency(responseCache.getCacheEntry(target, request, new FutureCallback<HttpCacheEntry>() {
+            future.setDependency(responseCache.createCacheEntry(
+                    target,
+                    request,
+                    backendResponse,
+                    buffer,
+                    requestDate,
+                    responseDate,
+                    new FutureCallback<HttpCacheEntry>() {
 
-                    @Override
-                    public void completed(final HttpCacheEntry existingEntry) {
-                        final HttpResponse backendResponse = cachingDataConsumer.backendResponse;
-                        if (DateUtils.isAfter(existingEntry, backendResponse, HttpHeaders.DATE)) {
+                        @Override
+                        public void completed(final HttpCacheEntry newEntry) {
+                            log.debug("Backend response successfully cached");
                             try {
-                                final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, existingEntry);
+                                final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, newEntry);
                                 triggerResponse(cacheResponse, scope, asyncExecCallback);
                             } catch (final ResourceIOException ex) {
                                 asyncExecCallback.failed(ex);
                             }
-                        } else {
-                            final Date responseDate = cachingDataConsumer.responseDate;
-                            final ByteArrayBuffer buffer = cachingDataConsumer.bufferRef.getAndSet(null);
-                            future.setDependency(responseCache.createCacheEntry(
-                                    target,
-                                    request,
-                                    backendResponse,
-                                    buffer,
-                                    requestDate,
-                                    responseDate,
-                                    new FutureCallback<HttpCacheEntry>() {
-
-                                        @Override
-                                        public void completed(final HttpCacheEntry newEntry) {
-                                            log.debug("Backend response successfully cached");
-                                            try {
-                                                final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, newEntry);
-                                                triggerResponse(cacheResponse, scope, asyncExecCallback);
-                                            } catch (final ResourceIOException ex) {
-                                                asyncExecCallback.failed(ex);
-                                            }
-                                        }
-
-                                        @Override
-                                        public void failed(final Exception ex) {
-                                            asyncExecCallback.failed(ex);
-                                        }
-
-                                        @Override
-                                        public void cancelled() {
-                                            asyncExecCallback.failed(new InterruptedIOException());
-                                        }
-
-                                    }));
+                        }
 
+                        @Override
+                        public void failed(final Exception ex) {
+                            asyncExecCallback.failed(ex);
                         }
-                    }
 
-                    @Override
-                    public void failed(final Exception cause) {
-                        asyncExecCallback.failed(cause);
-                    }
+                        @Override
+                        public void cancelled() {
+                            asyncExecCallback.failed(new InterruptedIOException());
+                        }
 
-                    @Override
-                    public void cancelled() {
-                        asyncExecCallback.failed(new InterruptedIOException());
-                    }
+                    }));
 
-                }));
+        }
+
+        @Override
+        public void completed() {
+            final CachingAsyncDataConsumer cachingDataConsumer = cachingConsumerRef.getAndSet(null);
+            if (cachingDataConsumer != null && !cachingDataConsumer.writtenThrough.get()) {
+                final ByteArrayBuffer buffer = cachingDataConsumer.bufferRef.getAndSet(null);
+                final HttpResponse backendResponse = cachingDataConsumer.backendResponse;
+                if (cacheConfig.isFreshnessCheckEnabled()) {
+                    final ComplexFuture<?> future = scope.future;
+                    future.setDependency(responseCache.getCacheEntry(target, request, new FutureCallback<HttpCacheEntry>() {
+
+                        @Override
+                        public void completed(final HttpCacheEntry existingEntry) {
+                            if (DateUtils.isAfter(existingEntry, backendResponse, HttpHeaders.DATE)) {
+                                log.debug("Backend already contains fresher cache entry");
+                                try {
+                                    final SimpleHttpResponse cacheResponse = responseGenerator.generateResponse(request, existingEntry);
+                                    triggerResponse(cacheResponse, scope, asyncExecCallback);
+                                } catch (final ResourceIOException ex) {
+                                    asyncExecCallback.failed(ex);
+                                }
+                            } else {
+                                triggerNewCacheEntryResponse(backendResponse, responseDate, buffer);
+                            }
+                        }
+
+                        @Override
+                        public void failed(final Exception cause) {
+                            asyncExecCallback.failed(cause);
+                        }
+
+                        @Override
+                        public void cancelled() {
+                            asyncExecCallback.failed(new InterruptedIOException());
+                        }
+
+                    }));
+                } else {
+                    triggerNewCacheEntryResponse(backendResponse, responseDate, buffer);
+                }
             } else {
                 asyncExecCallback.completed();
             }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/c78032d6/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheConfig.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheConfig.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheConfig.java
index 5994aa5..d63e623 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheConfig.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CacheConfig.java
@@ -168,7 +168,8 @@ public class CacheConfig implements Cloneable {
     private final boolean heuristicCachingEnabled;
     private final float heuristicCoefficient;
     private final long heuristicDefaultLifetime;
-    private final boolean isSharedCache;
+    private final boolean sharedCache;
+    private final boolean freshnessCheckEnabled;
     private final int asynchronousWorkersMax;
     private final int asynchronousWorkersCore;
     private final int asynchronousWorkerIdleLifetimeSecs;
@@ -184,7 +185,8 @@ public class CacheConfig implements Cloneable {
             final boolean heuristicCachingEnabled,
             final float heuristicCoefficient,
             final long heuristicDefaultLifetime,
-            final boolean isSharedCache,
+            final boolean sharedCache,
+            final boolean freshnessCheckEnabled,
             final int asynchronousWorkersMax,
             final int asynchronousWorkersCore,
             final int asynchronousWorkerIdleLifetimeSecs,
@@ -199,7 +201,8 @@ public class CacheConfig implements Cloneable {
         this.heuristicCachingEnabled = heuristicCachingEnabled;
         this.heuristicCoefficient = heuristicCoefficient;
         this.heuristicDefaultLifetime = heuristicDefaultLifetime;
-        this.isSharedCache = isSharedCache;
+        this.sharedCache = sharedCache;
+        this.freshnessCheckEnabled = freshnessCheckEnabled;
         this.asynchronousWorkersMax = asynchronousWorkersMax;
         this.asynchronousWorkersCore = asynchronousWorkersCore;
         this.asynchronousWorkerIdleLifetimeSecs = asynchronousWorkerIdleLifetimeSecs;
@@ -285,7 +288,17 @@ public class CacheConfig implements Cloneable {
      * shared (private) cache
      */
     public boolean isSharedCache() {
-        return isSharedCache;
+        return sharedCache;
+    }
+
+    /**
+     * Returns whether the cache will perform an extra cache entry freshness check
+     * upon cache update in case of a cache miss
+     *
+     * @since 5.0
+     */
+    public boolean isFreshnessCheckEnabled() {
+        return freshnessCheckEnabled;
     }
 
     /**
@@ -359,7 +372,8 @@ public class CacheConfig implements Cloneable {
         private boolean heuristicCachingEnabled;
         private float heuristicCoefficient;
         private long heuristicDefaultLifetime;
-        private boolean isSharedCache;
+        private boolean sharedCache;
+        private boolean freshnessCheckEnabled;
         private int asynchronousWorkersMax;
         private int asynchronousWorkersCore;
         private int asynchronousWorkerIdleLifetimeSecs;
@@ -372,10 +386,11 @@ public class CacheConfig implements Cloneable {
             this.maxUpdateRetries = DEFAULT_MAX_UPDATE_RETRIES;
             this.allow303Caching = DEFAULT_303_CACHING_ENABLED;
             this.weakETagOnPutDeleteAllowed = DEFAULT_WEAK_ETAG_ON_PUTDELETE_ALLOWED;
-            this.heuristicCachingEnabled = false;
+            this.heuristicCachingEnabled = DEFAULT_HEURISTIC_CACHING_ENABLED;
             this.heuristicCoefficient = DEFAULT_HEURISTIC_COEFFICIENT;
             this.heuristicDefaultLifetime = DEFAULT_HEURISTIC_LIFETIME;
-            this.isSharedCache = true;
+            this.sharedCache = true;
+            this.freshnessCheckEnabled = true;
             this.asynchronousWorkersMax = DEFAULT_ASYNCHRONOUS_WORKERS_MAX;
             this.asynchronousWorkersCore = DEFAULT_ASYNCHRONOUS_WORKERS_CORE;
             this.asynchronousWorkerIdleLifetimeSecs = DEFAULT_ASYNCHRONOUS_WORKER_IDLE_LIFETIME_SECS;
@@ -468,12 +483,12 @@ public class CacheConfig implements Cloneable {
 
         /**
          * Sets whether the cache should behave as a shared cache or not.
-         * @param isSharedCache true to behave as a shared cache, false to
+         * @param sharedCache true to behave as a shared cache, false to
          * behave as a non-shared (private) cache. To have the cache
          * behave like a browser cache, you want to set this to {@code false}.
          */
-        public Builder setSharedCache(final boolean isSharedCache) {
-            this.isSharedCache = isSharedCache;
+        public Builder setSharedCache(final boolean sharedCache) {
+            this.sharedCache = sharedCache;
             return this;
         }
 
@@ -542,7 +557,8 @@ public class CacheConfig implements Cloneable {
                     heuristicCachingEnabled,
                     heuristicCoefficient,
                     heuristicDefaultLifetime,
-                    isSharedCache,
+                    sharedCache,
+                    freshnessCheckEnabled,
                     asynchronousWorkersMax,
                     asynchronousWorkersCore,
                     asynchronousWorkerIdleLifetimeSecs,
@@ -563,7 +579,8 @@ public class CacheConfig implements Cloneable {
                 .append(", heuristicCachingEnabled=").append(this.heuristicCachingEnabled)
                 .append(", heuristicCoefficient=").append(this.heuristicCoefficient)
                 .append(", heuristicDefaultLifetime=").append(this.heuristicDefaultLifetime)
-                .append(", isSharedCache=").append(this.isSharedCache)
+                .append(", sharedCache=").append(this.sharedCache)
+                .append(", freshnessCheckEnabled=").append(this.freshnessCheckEnabled)
                 .append(", asynchronousWorkersMax=").append(this.asynchronousWorkersMax)
                 .append(", asynchronousWorkersCore=").append(this.asynchronousWorkersCore)
                 .append(", asynchronousWorkerIdleLifetimeSecs=").append(this.asynchronousWorkerIdleLifetimeSecs)

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/c78032d6/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
----------------------------------------------------------------------
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
index 7fb7e42..3b2491d 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingExec.java
@@ -380,15 +380,22 @@ public class CachingExec extends CachingExecBase implements ExecChainHandler {
             buf = null;
         }
         backendResponse.close();
-        final HttpCacheEntry existingEntry = responseCache.getCacheEntry(target, request);
-        if (DateUtils.isAfter(existingEntry, backendResponse, HttpHeaders.DATE)) {
-            return convert(responseGenerator.generateResponse(request, existingEntry));
+
+        final HttpCacheEntry cacheEntry;
+        if (cacheConfig.isFreshnessCheckEnabled()) {
+            final HttpCacheEntry existingEntry = responseCache.getCacheEntry(target, request);
+            if (DateUtils.isAfter(existingEntry, backendResponse, HttpHeaders.DATE)) {
+                log.debug("Backend already contains fresher cache entry");
+                cacheEntry = existingEntry;
+            } else {
+                cacheEntry = responseCache.createCacheEntry(target, request, backendResponse, buf, requestSent, responseReceived);
+                log.debug("Backend response successfully cached");
+            }
         } else {
-            final HttpCacheEntry newEntry = responseCache.createCacheEntry(
-                    target, request, backendResponse, buf, requestSent, responseReceived);
-            log.debug("Backend response successfully cached");
-            return convert(responseGenerator.generateResponse(request, newEntry));
+            cacheEntry = responseCache.createCacheEntry(target, request, backendResponse, buf, requestSent, responseReceived);
+            log.debug("Backend response successfully cached (freshness check skipped)");
         }
+        return convert(responseGenerator.generateResponse(request, cacheEntry));
     }
 
     private ClassicHttpResponse handleCacheMiss(