From 27fb531c0c4cb771ef580be2c48ac0ae99f78b5c Mon Sep 17 00:00:00 2001 From: Nikita Date: Mon, 19 Feb 2018 06:16:47 +0300 Subject: [PATCH] RMapCache.remainTimeToLive(key) method added. #1210 --- .../java/org/redisson/RedissonMapCache.java | 41 +++++++++++++++++++ .../main/java/org/redisson/api/RMapCache.java | 9 ++++ .../java/org/redisson/api/RMapCacheAsync.java | 10 +++++ .../org/redisson/RedissonMapCacheTest.java | 13 ++++++ 4 files changed, 73 insertions(+) diff --git a/redisson/src/main/java/org/redisson/RedissonMapCache.java b/redisson/src/main/java/org/redisson/RedissonMapCache.java index 5a31c6b10..77086fac0 100644 --- a/redisson/src/main/java/org/redisson/RedissonMapCache.java +++ b/redisson/src/main/java/org/redisson/RedissonMapCache.java @@ -970,6 +970,47 @@ public class RedissonMapCache extends RedissonMap implements RMapCac System.currentTimeMillis(), ttlTimeout, maxIdleTimeout, maxIdleDelta, encodeMapKey(key), encodeMapValue(value)); return future; } + + @Override + public long remainTimeToLive(K key) { + return get(remainTimeToLiveAsync(key)); + } + + @Override + public RFuture remainTimeToLiveAsync(K key) { + checkKey(key); + + return commandExecutor.evalWriteAsync(getName(key), codec, RedisCommands.EVAL_LONG, + "local value = redis.call('hget', KEYS[1], ARGV[2]); " + + "if value == false then " + + "return -2; " + + "end; " + + "local t, val = struct.unpack('dLc0', value); " + + "local expireDate = 92233720368547758; " + + "local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); " + + "if expireDateScore ~= false then " + + "expireDate = tonumber(expireDateScore) " + + "end; " + + "if t ~= 0 then " + + "local expireIdle = redis.call('zscore', KEYS[3], ARGV[2]); " + + "if expireIdle ~= false then " + + "expireDate = math.min(expireDate, tonumber(expireIdle)) " + + "end; " + + "end; " + + + "if expireDate == 92233720368547758 then " + + "return -1; " + + "end;" + + "if expireDate > tonumber(ARGV[1]) then " + + "return ARGV[1] - expireDate; " + + "else " + + "return -2; " + + "end; " + + "return val; ", + Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key)), + System.currentTimeMillis(), encodeMapKey(key)); + + } String getTimeoutSetNameByKey(Object key) { return prefixName("redisson__timeout__set", getName(key)); diff --git a/redisson/src/main/java/org/redisson/api/RMapCache.java b/redisson/src/main/java/org/redisson/api/RMapCache.java index 7ccdc490f..28c7f95f3 100644 --- a/redisson/src/main/java/org/redisson/api/RMapCache.java +++ b/redisson/src/main/java/org/redisson/api/RMapCache.java @@ -260,5 +260,14 @@ public interface RMapCache extends RMap, RMapCacheAsync { * @param listenerId - listener id */ void removeListener(int listenerId); + + /** + * Remaining time to live of map entry associated with a key. + * + * @return time in milliseconds + * -2 if the key does not exist. + * -1 if the key exists but has no associated expire. + */ + long remainTimeToLive(K key); } diff --git a/redisson/src/main/java/org/redisson/api/RMapCacheAsync.java b/redisson/src/main/java/org/redisson/api/RMapCacheAsync.java index cc4a716bf..623b6b1a1 100644 --- a/redisson/src/main/java/org/redisson/api/RMapCacheAsync.java +++ b/redisson/src/main/java/org/redisson/api/RMapCacheAsync.java @@ -220,4 +220,14 @@ public interface RMapCacheAsync extends RMapAsync { */ @Override RFuture sizeAsync(); + + /** + * Remaining time to live of map entry associated with a key. + * + * @return time in milliseconds + * -2 if the key does not exist. + * -1 if the key exists but has no associated expire. + */ + RFuture remainTimeToLiveAsync(K key); + } diff --git a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java index c6cb7204b..2017085e9 100644 --- a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java +++ b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java @@ -57,6 +57,19 @@ public class RedissonMapCacheTest extends BaseMapTest { return redisson.getMapCache("test", options); } + @Test + public void testRemainTimeToLive() { + RMapCache map = redisson.getMapCache("test"); + map.put("1", "2", 2, TimeUnit.SECONDS); + assertThat(map.remainTimeToLive("1")).isLessThan(1900); + map.put("3", "4"); + assertThat(map.remainTimeToLive("3")).isEqualTo(-1); + assertThat(map.remainTimeToLive("0")).isEqualTo(-2); + + map.put("5", "6", 20, TimeUnit.SECONDS, 10, TimeUnit.SECONDS); + assertThat(map.remainTimeToLive("1")).isLessThan(9900); + } + @Test public void testWriterPutIfAbsentTTL() { Map store = new HashMap<>();