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 2025/11/24 16:50:26 UTC

(httpcomponents-client) branch master updated: HTTPCLIENT-2406: MemcachedHttpCacheStorage to support per entry expiry setting

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git


The following commit(s) were added to refs/heads/master by this push:
     new 79992d832 HTTPCLIENT-2406: MemcachedHttpCacheStorage to support per entry expiry setting
79992d832 is described below

commit 79992d832cc5d9fb4ce8307200dae844085b9d3d
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Sat Nov 22 12:15:24 2025 +0100

    HTTPCLIENT-2406: MemcachedHttpCacheStorage to support per entry expiry setting
---
 .../cache/AbstractSerializingCacheStorage.java     | 11 ++++-
 .../cache/memcached/MemcachedHttpCacheStorage.java | 52 +++++++++++++++++-----
 2 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AbstractSerializingCacheStorage.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AbstractSerializingCacheStorage.java
index 108f9a621..b0a24d328 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AbstractSerializingCacheStorage.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/AbstractSerializingCacheStorage.java
@@ -26,6 +26,7 @@
  */
 package org.apache.hc.client5.http.impl.cache;
 
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -60,6 +61,13 @@ public AbstractSerializingCacheStorage(final int maxUpdateRetries, final HttpCac
 
     protected abstract void store(String storageKey, T storageObject) throws ResourceIOException;
 
+    /**
+     * @since 5.6
+     */
+    protected void store(final String storageKey, final Instant expectedExpiry, final T storageObject) throws ResourceIOException {
+        store(storageKey, storageObject);
+    }
+
     protected abstract T restore(String storageKey) throws ResourceIOException;
 
     protected abstract CAS getForUpdateCAS(String storageKey) throws ResourceIOException;
@@ -76,7 +84,8 @@ public AbstractSerializingCacheStorage(final int maxUpdateRetries, final HttpCac
     public final void putEntry(final String key, final HttpCacheEntry entry) throws ResourceIOException {
         final String storageKey = digestToStorageKey(key);
         final T storageObject = serializer.serialize(new HttpCacheStorageEntry(key, entry));
-        store(storageKey, storageObject);
+        final Instant expires = entry.getExpires();
+        store(storageKey, expires, storageObject);
     }
 
     @Override
diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/memcached/MemcachedHttpCacheStorage.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/memcached/MemcachedHttpCacheStorage.java
index 84ec2aa37..3b62d2282 100644
--- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/memcached/MemcachedHttpCacheStorage.java
+++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/memcached/MemcachedHttpCacheStorage.java
@@ -28,11 +28,19 @@
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.time.Duration;
+import java.time.Instant;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.CancellationException;
+import java.util.function.BiFunction;
 
+import net.spy.memcached.CASResponse;
+import net.spy.memcached.CASValue;
+import net.spy.memcached.MemcachedClient;
+import net.spy.memcached.MemcachedClientIF;
+import net.spy.memcached.OperationTimeoutException;
 import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
 import org.apache.hc.client5.http.cache.ResourceIOException;
 import org.apache.hc.client5.http.impl.cache.AbstractBinaryCacheStorage;
@@ -40,12 +48,6 @@
 import org.apache.hc.client5.http.impl.cache.HttpByteArrayCacheEntrySerializer;
 import org.apache.hc.core5.util.Args;
 
-import net.spy.memcached.CASResponse;
-import net.spy.memcached.CASValue;
-import net.spy.memcached.MemcachedClient;
-import net.spy.memcached.MemcachedClientIF;
-import net.spy.memcached.OperationTimeoutException;
-
 /**
  * <p>
  * This class is a storage backend that uses an external <i>memcached</i>
@@ -88,6 +90,7 @@ public class MemcachedHttpCacheStorage extends AbstractBinaryCacheStorage<CASVal
 
     private final MemcachedClientIF client;
     private final KeyHashingScheme keyHashingScheme;
+    private final BiFunction<String, Instant, Duration> expiryResolver;
 
     /**
      * Create a storage backend talking to a <i>memcached</i> instance
@@ -119,7 +122,7 @@ public MemcachedHttpCacheStorage(final MemcachedClient cache) {
      * @since 5.2
      */
     public MemcachedHttpCacheStorage(final MemcachedClientIF cache) {
-        this(cache, CacheConfig.DEFAULT, HttpByteArrayCacheEntrySerializer.INSTANCE, SHA256KeyHashingScheme.INSTANCE);
+        this(cache, CacheConfig.DEFAULT, HttpByteArrayCacheEntrySerializer.INSTANCE, SHA256KeyHashingScheme.INSTANCE, null);
     }
 
     /**
@@ -137,7 +140,18 @@ public MemcachedHttpCacheStorage(
             final CacheConfig config,
             final HttpCacheEntrySerializer<byte[]> serializer,
             final KeyHashingScheme keyHashingScheme) {
-        this((MemcachedClientIF) client, config, serializer, keyHashingScheme);
+        this(client, config, serializer, keyHashingScheme, null);
+    }
+
+    /**
+     * @since 5.2
+     */
+    public MemcachedHttpCacheStorage(
+            final MemcachedClientIF client,
+            final CacheConfig config,
+            final HttpCacheEntrySerializer<byte[]> serializer,
+            final KeyHashingScheme keyHashingScheme) {
+        this(client, config, serializer, keyHashingScheme, null);
     }
 
     /**
@@ -150,17 +164,20 @@ public MemcachedHttpCacheStorage(
      * @param serializer       alternative serialization mechanism
      * @param keyHashingScheme how to map higher-level logical "storage keys"
      *                         onto "cache keys" suitable for use with memcached
-     * @since 5.2
+     * @param expiryResolver   resolver for cache entry expiry
+     * @since 5.6
      */
     public MemcachedHttpCacheStorage(
             final MemcachedClientIF client,
             final CacheConfig config,
             final HttpCacheEntrySerializer<byte[]> serializer,
-            final KeyHashingScheme keyHashingScheme) {
+            final KeyHashingScheme keyHashingScheme,
+            final BiFunction<String, Instant, Duration> expiryResolver) {
         super((config != null ? config : CacheConfig.DEFAULT).getMaxUpdateRetries(),
                 serializer != null ? serializer : HttpByteArrayCacheEntrySerializer.INSTANCE);
         this.client = Args.notNull(client, "Memcached client");
         this.keyHashingScheme = keyHashingScheme;
+        this.expiryResolver = expiryResolver;
     }
 
     @Override
@@ -170,8 +187,21 @@ protected String digestToStorageKey(final String key) {
 
     @Override
     protected void store(final String storageKey, final byte[] storageObject) throws ResourceIOException {
+        store(storageKey, null, storageObject);
+    }
+
+    @Override
+    protected void store(final String storageKey, final Instant expectedExpiry, final byte[] storageObject) throws ResourceIOException {
+        int exp = 0;
+        final Duration validityduration = expiryResolver != null ? expiryResolver.apply(storageKey, expectedExpiry) : null;
+        if (validityduration != null) {
+            final long expSeconds = validityduration.getSeconds();
+            if (expSeconds > 0) {
+                exp = (int) expSeconds;
+            }
+        }
         try {
-            client.set(storageKey, 0, storageObject);
+            client.set(storageKey, exp, storageObject);
         } catch (final CancellationException ex) {
             throw new MemcachedOperationCancellationException(ex);
         }