From 640e40e4453a855f165548e9a8d4227adad3d376 Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Mon, 17 Dec 2018 13:28:03 +0300 Subject: [PATCH] Fixed - RMapCache element expiration doesn't work with map size = 1 #1808 --- .../java/org/redisson/RedissonMapCache.java | 51 ++++++++++--------- .../org/redisson/RedissonMapCacheTest.java | 14 +++++ 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/redisson/src/main/java/org/redisson/RedissonMapCache.java b/redisson/src/main/java/org/redisson/RedissonMapCache.java index ad31f1d0e..cac516bea 100644 --- a/redisson/src/main/java/org/redisson/RedissonMapCache.java +++ b/redisson/src/main/java/org/redisson/RedissonMapCache.java @@ -360,7 +360,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize >= maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[5] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -390,7 +390,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "return val; " + "end; ", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), ttlTimeout, maxIdleTimeout, maxIdleDelta, encodeMapKey(key), encodeMapValue(value)); if (hasNoWriter()) { return future; @@ -448,7 +448,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "return 0; " + "end", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getRemovedChannelNameByKey(key), - getLastAccessTimeSetNameByKey(key), getOptionsName(key)), + getLastAccessTimeSetNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), encodeMapKey(key), encodeMapValue(value)); } @@ -482,7 +482,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " redis.call('zadd', KEYS[4], tonumber(ARGV[1]), ARGV[2]); " + "end; " + "return val; ", - Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getLastAccessTimeSetNameByKey(key), getOptionsName(key)), + Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getLastAccessTimeSetNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), encodeMapKey(key)); } @@ -526,7 +526,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize > maxSize then" + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1);" + " for index, lruItem in ipairs(lruItems) do" + - " if lruItem then" + + " if lruItem and lruItem ~= ARGV[2] then" + " local lruItemValue = redis.call('hget', KEYS[1], lruItem);" + " redis.call('hdel', KEYS[1], lruItem);" + " redis.call('zrem', KEYS[2], lruItem);" + @@ -555,7 +555,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac "redis.call('publish', KEYS[5], msg);" + "return val;", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), encodeMapKey(key), encodeMapValue(value)); } @@ -597,7 +597,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize > maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[2] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -617,7 +617,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "redis.call('publish', KEYS[4], msg); " + "return nil;", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), encodeMapKey(key), encodeMapValue(value)); } @@ -700,7 +700,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize > maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[2] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -718,7 +718,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "return tostring(newValue); ", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), keyState, new BigDecimal(value.toString()).toPlainString()); } @@ -834,7 +834,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize >= maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[5] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -862,7 +862,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "return 0;" + "end;", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), ttlTimeout, maxIdleTimeout, maxIdleDelta, encodeMapKey(key), encodeMapValue(value)); return future; } @@ -972,7 +972,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize >= maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[5] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -1004,7 +1004,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "return val", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), ttlTimeout, maxIdleTimeout, maxIdleDelta, encodeMapKey(key), encodeMapValue(value)); return future; } @@ -1085,8 +1085,12 @@ public class RedissonMapCache extends RedissonMap implements RMapCac String getOptionsName() { return suffixName(getName(), "redisson_options"); } + + String getOptionsName(String name) { + return suffixName(name, "redisson_options"); + } - String getOptionsName(Object key) { + String getOptionsNameByKey(Object key) { return suffixName(getName(key), "redisson_options"); } @@ -1336,7 +1340,6 @@ public class RedissonMapCache extends RedissonMap implements RMapCac return (RFuture>)(Object)f; } - @Override protected RFuture fastPutOperationAsync(K key, V value) { return commandExecutor.evalWriteAsync(getName(key), codec, RedisCommands.EVAL_BOOLEAN, @@ -1375,7 +1378,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize > maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[2] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -1402,7 +1405,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "return 0;" + "end;", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getUpdatedChannelNameByKey(key), getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), encodeMapKey(key), encodeMapValue(value)); } @@ -1427,7 +1430,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize > maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[2] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -1477,7 +1480,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac + "redis.call('publish', KEYS[4], msg); " + "return 1; ", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), encodeMapKey(key), encodeMapValue(value)); } @@ -1573,7 +1576,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize >= maxSize then " + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize); " + " for index, lruItem in ipairs(lruItems) do " + - " if lruItem then " + + " if lruItem and lruItem ~= ARGV[5] then " + " local lruItemValue = redis.call('hget', KEYS[1], lruItem); " + " redis.call('hdel', KEYS[1], lruItem); " + " redis.call('zrem', KEYS[2], lruItem); " + @@ -1598,7 +1601,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " return 0; " + "end; ", Arrays.asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key), getCreatedChannelNameByKey(key), - getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), + getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsNameByKey(key)), System.currentTimeMillis(), ttlTimeout, maxIdleTimeout, maxIdleDelta, encodeMapKey(key), encodeMapValue(value)); if (hasNoWriter()) { return future; @@ -1766,7 +1769,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize > maxSize then" + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1);" + " for index, lruItem in ipairs(lruItems) do" + - " if lruItem then" + + " if lruItem and lruItem ~= key then" + " local lruItemValue = redis.call('hget', KEYS[1], lruItem);" + " redis.call('hdel', KEYS[1], lruItem);" + " redis.call('zrem', KEYS[2], lruItem);" + @@ -1865,7 +1868,7 @@ public class RedissonMapCache extends RedissonMap implements RMapCac " if cacheSize > maxSize then" + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1);" + " for index, lruItem in ipairs(lruItems) do" + - " if lruItem then" + + " if lruItem and lruItem ~= key then" + " local lruItemValue = redis.call('hget', KEYS[1], lruItem);" + " redis.call('hdel', KEYS[1], lruItem);" + " redis.call('zrem', KEYS[2], lruItem);" + diff --git a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java index 6df47372b..bed85d67c 100644 --- a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java +++ b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java @@ -94,6 +94,19 @@ public class RedissonMapCacheTest extends BaseMapTest { map.destroy(); } + @Test + public void testFastPutTTL() throws InterruptedException { + RMapCache map = redisson.getMapCache("getAll"); + map.trySetMaxSize(1); + map.fastPut(new SimpleKey("1"), new SimpleValue("3"), 5, TimeUnit.SECONDS, 0, TimeUnit.SECONDS); + Thread.sleep(5000); + assertThat(map.get(new SimpleKey("1"))).isNull(); + + map.fastPut(new SimpleKey("1"), new SimpleValue("4"), 5, TimeUnit.SECONDS, 0, TimeUnit.SECONDS); + Thread.sleep(10000); + assertThat(map.get(new SimpleKey("1"))).isNull(); + } + @Test public void testWriterPutIfAbsentTTL() { Map store = new HashMap<>(); @@ -179,6 +192,7 @@ public class RedissonMapCacheTest extends BaseMapTest { assertThat(map.put("03", "00")).isNull(); assertThat(map.fastPutIfAbsent("04", "00", 10, TimeUnit.SECONDS)).isTrue(); assertThat(map.fastPut("1", "11", 10, TimeUnit.SECONDS)).isTrue(); + assertThat(map.size()).isEqualTo(2); assertThat(map.fastPut("2", "22", 10, TimeUnit.SECONDS)).isTrue(); assertThat(map.fastPut("3", "33", 10, TimeUnit.SECONDS)).isTrue(); -- GitLab