2828
2929import java .io .IOException ;
3030import java .net .InetSocketAddress ;
31+ import java .time .Duration ;
32+ import java .time .Instant ;
3133import java .util .Collection ;
3234import java .util .HashMap ;
3335import java .util .Map ;
3436import java .util .concurrent .CancellationException ;
37+ import java .util .function .BiFunction ;
3538
39+ import net .spy .memcached .CASResponse ;
40+ import net .spy .memcached .CASValue ;
41+ import net .spy .memcached .MemcachedClient ;
42+ import net .spy .memcached .MemcachedClientIF ;
43+ import net .spy .memcached .OperationTimeoutException ;
3644import org .apache .hc .client5 .http .cache .HttpCacheEntrySerializer ;
3745import org .apache .hc .client5 .http .cache .ResourceIOException ;
3846import org .apache .hc .client5 .http .impl .cache .AbstractBinaryCacheStorage ;
3947import org .apache .hc .client5 .http .impl .cache .CacheConfig ;
4048import org .apache .hc .client5 .http .impl .cache .HttpByteArrayCacheEntrySerializer ;
4149import org .apache .hc .core5 .util .Args ;
4250
43- import net .spy .memcached .CASResponse ;
44- import net .spy .memcached .CASValue ;
45- import net .spy .memcached .MemcachedClient ;
46- import net .spy .memcached .MemcachedClientIF ;
47- import net .spy .memcached .OperationTimeoutException ;
48-
4951/**
5052 * <p>
5153 * This class is a storage backend that uses an external <i>memcached</i>
@@ -88,6 +90,7 @@ public class MemcachedHttpCacheStorage extends AbstractBinaryCacheStorage<CASVal
8890
8991 private final MemcachedClientIF client ;
9092 private final KeyHashingScheme keyHashingScheme ;
93+ private final BiFunction <String , Instant , Duration > expiryResolver ;
9194
9295 /**
9396 * Create a storage backend talking to a <i>memcached</i> instance
@@ -119,7 +122,7 @@ public MemcachedHttpCacheStorage(final MemcachedClient cache) {
119122 * @since 5.2
120123 */
121124 public MemcachedHttpCacheStorage (final MemcachedClientIF cache ) {
122- this (cache , CacheConfig .DEFAULT , HttpByteArrayCacheEntrySerializer .INSTANCE , SHA256KeyHashingScheme .INSTANCE );
125+ this (cache , CacheConfig .DEFAULT , HttpByteArrayCacheEntrySerializer .INSTANCE , SHA256KeyHashingScheme .INSTANCE , null );
123126 }
124127
125128 /**
@@ -137,7 +140,18 @@ public MemcachedHttpCacheStorage(
137140 final CacheConfig config ,
138141 final HttpCacheEntrySerializer <byte []> serializer ,
139142 final KeyHashingScheme keyHashingScheme ) {
140- this ((MemcachedClientIF ) client , config , serializer , keyHashingScheme );
143+ this (client , config , serializer , keyHashingScheme , null );
144+ }
145+
146+ /**
147+ * @since 5.2
148+ */
149+ public MemcachedHttpCacheStorage (
150+ final MemcachedClientIF client ,
151+ final CacheConfig config ,
152+ final HttpCacheEntrySerializer <byte []> serializer ,
153+ final KeyHashingScheme keyHashingScheme ) {
154+ this (client , config , serializer , keyHashingScheme , null );
141155 }
142156
143157 /**
@@ -150,17 +164,20 @@ public MemcachedHttpCacheStorage(
150164 * @param serializer alternative serialization mechanism
151165 * @param keyHashingScheme how to map higher-level logical "storage keys"
152166 * onto "cache keys" suitable for use with memcached
153- * @since 5.2
167+ * @param expiryResolver resolver for cache entry expiry
168+ * @since 5.6
154169 */
155170 public MemcachedHttpCacheStorage (
156171 final MemcachedClientIF client ,
157172 final CacheConfig config ,
158173 final HttpCacheEntrySerializer <byte []> serializer ,
159- final KeyHashingScheme keyHashingScheme ) {
174+ final KeyHashingScheme keyHashingScheme ,
175+ final BiFunction <String , Instant , Duration > expiryResolver ) {
160176 super ((config != null ? config : CacheConfig .DEFAULT ).getMaxUpdateRetries (),
161177 serializer != null ? serializer : HttpByteArrayCacheEntrySerializer .INSTANCE );
162178 this .client = Args .notNull (client , "Memcached client" );
163179 this .keyHashingScheme = keyHashingScheme ;
180+ this .expiryResolver = expiryResolver ;
164181 }
165182
166183 @ Override
@@ -170,8 +187,21 @@ protected String digestToStorageKey(final String key) {
170187
171188 @ Override
172189 protected void store (final String storageKey , final byte [] storageObject ) throws ResourceIOException {
190+ store (storageKey , null , storageObject );
191+ }
192+
193+ @ Override
194+ protected void store (final String storageKey , final Instant expectedExpiry , final byte [] storageObject ) throws ResourceIOException {
195+ int exp = 0 ;
196+ final Duration validityduration = expiryResolver != null ? expiryResolver .apply (storageKey , expectedExpiry ) : null ;
197+ if (validityduration != null ) {
198+ final long expSeconds = validityduration .getSeconds ();
199+ if (expSeconds > 0 ) {
200+ exp = (int ) expSeconds ;
201+ }
202+ }
173203 try {
174- client .set (storageKey , 0 , storageObject );
204+ client .set (storageKey , exp , storageObject );
175205 } catch (final CancellationException ex ) {
176206 throw new MemcachedOperationCancellationException (ex );
177207 }
0 commit comments