diff --git a/redisson-spring-data/redisson-spring-data-16/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java b/redisson-spring-data/redisson-spring-data-16/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java new file mode 100644 index 000000000..da9fc72a7 --- /dev/null +++ b/redisson-spring-data/redisson-spring-data-16/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java @@ -0,0 +1,46 @@ +/** + * Copyright 2018 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson.spring.data.connection; + +import java.util.Properties; + +import org.redisson.client.handler.State; +import org.redisson.client.protocol.Decoder; + +import io.netty.buffer.ByteBuf; +import io.netty.util.CharsetUtil; + +/** + * + * @author Nikita Koksharov + * + */ +public class PropertiesDecoder implements Decoder { + + @Override + public Properties decode(ByteBuf buf, State state) { + String value = buf.toString(CharsetUtil.UTF_8); + Properties result = new Properties(); + for (String entry : value.split("\r\n|\n")) { + String[] parts = entry.split(":"); + if (parts.length == 2) { + result.put(parts[0], parts[1]); + } + } + return result; + } + +} diff --git a/redisson-spring-data/redisson-spring-data-16/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java b/redisson-spring-data/redisson-spring-data-16/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java index 078584b76..b7a092960 100644 --- a/redisson-spring-data/redisson-spring-data-16/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java +++ b/redisson-spring-data/redisson-spring-data-16/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java @@ -1716,14 +1716,17 @@ public class RedissonConnection extends AbstractRedisConnection { sync(f); } + private static final RedisStrictCommand INFO_DEFAULT = new RedisStrictCommand("INFO", "DEFAULT", new PropertiesDecoder()); + private static final RedisStrictCommand INFO = new RedisStrictCommand("INFO", new PropertiesDecoder()); + @Override public Properties info() { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO_DEFAULT); } @Override public Properties info(String section) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO, section); } @Override @@ -1738,17 +1741,17 @@ public class RedissonConnection extends AbstractRedisConnection { @Override public List getConfig(String pattern) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, RedisCommands.CONFIG_GET, pattern); } @Override public void setConfig(String param, String value) { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_SET, param, value); } @Override public void resetConfigStats() { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_RESETSTAT); } private static final RedisStrictCommand TIME = new RedisStrictCommand("TIME", new TimeLongObjectDecoder()); diff --git a/redisson-spring-data/redisson-spring-data-17/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java b/redisson-spring-data/redisson-spring-data-17/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java new file mode 100644 index 000000000..da9fc72a7 --- /dev/null +++ b/redisson-spring-data/redisson-spring-data-17/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java @@ -0,0 +1,46 @@ +/** + * Copyright 2018 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson.spring.data.connection; + +import java.util.Properties; + +import org.redisson.client.handler.State; +import org.redisson.client.protocol.Decoder; + +import io.netty.buffer.ByteBuf; +import io.netty.util.CharsetUtil; + +/** + * + * @author Nikita Koksharov + * + */ +public class PropertiesDecoder implements Decoder { + + @Override + public Properties decode(ByteBuf buf, State state) { + String value = buf.toString(CharsetUtil.UTF_8); + Properties result = new Properties(); + for (String entry : value.split("\r\n|\n")) { + String[] parts = entry.split(":"); + if (parts.length == 2) { + result.put(parts[0], parts[1]); + } + } + return result; + } + +} diff --git a/redisson-spring-data/redisson-spring-data-17/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java b/redisson-spring-data/redisson-spring-data-17/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java index deb6af81e..b771e4cdb 100644 --- a/redisson-spring-data/redisson-spring-data-17/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java +++ b/redisson-spring-data/redisson-spring-data-17/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java @@ -1745,14 +1745,17 @@ public class RedissonConnection extends AbstractRedisConnection { sync(f); } + private static final RedisStrictCommand INFO_DEFAULT = new RedisStrictCommand("INFO", "DEFAULT", new PropertiesDecoder()); + private static final RedisStrictCommand INFO = new RedisStrictCommand("INFO", new PropertiesDecoder()); + @Override public Properties info() { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO_DEFAULT); } @Override public Properties info(String section) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO, section); } @Override @@ -1767,17 +1770,17 @@ public class RedissonConnection extends AbstractRedisConnection { @Override public List getConfig(String pattern) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, RedisCommands.CONFIG_GET, pattern); } @Override public void setConfig(String param, String value) { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_SET, param, value); } @Override public void resetConfigStats() { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_RESETSTAT); } private static final RedisStrictCommand TIME = new RedisStrictCommand("TIME", new TimeLongObjectDecoder()); diff --git a/redisson-spring-data/redisson-spring-data-18/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java b/redisson-spring-data/redisson-spring-data-18/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java new file mode 100644 index 000000000..da9fc72a7 --- /dev/null +++ b/redisson-spring-data/redisson-spring-data-18/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java @@ -0,0 +1,46 @@ +/** + * Copyright 2018 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson.spring.data.connection; + +import java.util.Properties; + +import org.redisson.client.handler.State; +import org.redisson.client.protocol.Decoder; + +import io.netty.buffer.ByteBuf; +import io.netty.util.CharsetUtil; + +/** + * + * @author Nikita Koksharov + * + */ +public class PropertiesDecoder implements Decoder { + + @Override + public Properties decode(ByteBuf buf, State state) { + String value = buf.toString(CharsetUtil.UTF_8); + Properties result = new Properties(); + for (String entry : value.split("\r\n|\n")) { + String[] parts = entry.split(":"); + if (parts.length == 2) { + result.put(parts[0], parts[1]); + } + } + return result; + } + +} diff --git a/redisson-spring-data/redisson-spring-data-18/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java b/redisson-spring-data/redisson-spring-data-18/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java index ee6ee3163..38cd42699 100644 --- a/redisson-spring-data/redisson-spring-data-18/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java +++ b/redisson-spring-data/redisson-spring-data-18/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java @@ -1764,14 +1764,17 @@ public class RedissonConnection extends AbstractRedisConnection { sync(f); } + private static final RedisStrictCommand INFO_DEFAULT = new RedisStrictCommand("INFO", "DEFAULT", new PropertiesDecoder()); + private static final RedisStrictCommand INFO = new RedisStrictCommand("INFO", new PropertiesDecoder()); + @Override public Properties info() { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO_DEFAULT); } @Override public Properties info(String section) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO, section); } @Override @@ -1786,17 +1789,17 @@ public class RedissonConnection extends AbstractRedisConnection { @Override public List getConfig(String pattern) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, RedisCommands.CONFIG_GET, pattern); } @Override public void setConfig(String param, String value) { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_SET, param, value); } @Override public void resetConfigStats() { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_RESETSTAT); } private static final RedisStrictCommand TIME = new RedisStrictCommand("TIME", new TimeLongObjectDecoder()); diff --git a/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java b/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java new file mode 100644 index 000000000..da9fc72a7 --- /dev/null +++ b/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/PropertiesDecoder.java @@ -0,0 +1,46 @@ +/** + * Copyright 2018 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.redisson.spring.data.connection; + +import java.util.Properties; + +import org.redisson.client.handler.State; +import org.redisson.client.protocol.Decoder; + +import io.netty.buffer.ByteBuf; +import io.netty.util.CharsetUtil; + +/** + * + * @author Nikita Koksharov + * + */ +public class PropertiesDecoder implements Decoder { + + @Override + public Properties decode(ByteBuf buf, State state) { + String value = buf.toString(CharsetUtil.UTF_8); + Properties result = new Properties(); + for (String entry : value.split("\r\n|\n")) { + String[] parts = entry.split(":"); + if (parts.length == 2) { + result.put(parts[0], parts[1]); + } + } + return result; + } + +} diff --git a/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java b/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java index bef616387..9a993a5a2 100644 --- a/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java +++ b/redisson-spring-data/redisson-spring-data-20/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java @@ -66,6 +66,7 @@ import org.redisson.client.protocol.decoder.MapScanResult; import org.redisson.client.protocol.decoder.MultiDecoder; import org.redisson.client.protocol.decoder.ObjectListReplayDecoder; import org.redisson.client.protocol.decoder.ObjectSetReplayDecoder; +import org.redisson.client.protocol.decoder.StringListReplayDecoder; import org.redisson.client.protocol.decoder.TimeLongObjectDecoder; import org.redisson.command.CommandAsyncService; import org.redisson.command.CommandBatchService; @@ -1778,14 +1779,17 @@ public class RedissonConnection extends AbstractRedisConnection { sync(f); } + private static final RedisStrictCommand INFO_DEFAULT = new RedisStrictCommand("INFO", "DEFAULT", new PropertiesDecoder()); + private static final RedisStrictCommand INFO = new RedisStrictCommand("INFO", new PropertiesDecoder()); + @Override public Properties info() { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO_DEFAULT); } @Override public Properties info(String section) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, INFO, section); } @Override @@ -1798,19 +1802,21 @@ public class RedissonConnection extends AbstractRedisConnection { throw new UnsupportedOperationException(); } + private static final RedisStrictCommand CONFIG_GET = new RedisStrictCommand("CONFIG", "GET", new PropertiesDecoder()); + @Override public Properties getConfig(String pattern) { - throw new UnsupportedOperationException(); + return read(null, StringCodec.INSTANCE, RedisCommands.CONFIG_GET, pattern); } @Override public void setConfig(String param, String value) { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_SET, param, value); } @Override public void resetConfigStats() { - throw new UnsupportedOperationException(); + write(null, StringCodec.INSTANCE, RedisCommands.CONFIG_RESETSTAT); } private static final RedisStrictCommand TIME = new RedisStrictCommand("TIME", new TimeLongObjectDecoder()); diff --git a/redisson/src/main/java/org/redisson/RedissonMapCache.java b/redisson/src/main/java/org/redisson/RedissonMapCache.java index 9c581081f..d029aac94 100644 --- a/redisson/src/main/java/org/redisson/RedissonMapCache.java +++ b/redisson/src/main/java/org/redisson/RedissonMapCache.java @@ -55,6 +55,7 @@ import org.redisson.codec.MapCacheEventCodec; import org.redisson.command.CommandAsyncExecutor; import org.redisson.connection.decoder.MapGetAllDecoder; import org.redisson.eviction.EvictionScheduler; +import org.redisson.misc.RedissonPromise; import io.netty.buffer.ByteBuf; import io.netty.util.concurrent.Future; @@ -619,6 +620,31 @@ public class RedissonMapCache extends RedissonMap implements RMapCac getLastAccessTimeSetNameByKey(key), getRemovedChannelNameByKey(key), getOptionsName(key)), System.currentTimeMillis(), encodeMapKey(key), encodeMapValue(value)); } + + @Override + public void putAll(Map map, long ttl, TimeUnit ttlUnit) { + get(putAllAsync(map, ttl, ttlUnit)); + } + + @Override + public RFuture putAllAsync(Map map, long ttl, TimeUnit ttlUnit) { + if (map.isEmpty()) { + return RedissonPromise.newSucceededFuture(null); + } + + RFuture future = putAllOperationAsync(map, ttl, ttlUnit); + if (hasNoWriter()) { + return future; + } + + MapWriterTask listener = new MapWriterTask() { + @Override + public void execute() { + options.getWriter().writeAll((Map) map); + } + }; + return mapWriterFuture(future, listener); + } @Override public V addAndGet(K key, Number value) { @@ -1772,6 +1798,105 @@ public class RedissonMapCache extends RedissonMap implements RMapCac getUpdatedChannelName(), getLastAccessTimeSetName(), getRemovedChannelName(), getOptionsName()), params.toArray()); } + + private RFuture putAllOperationAsync(Map map, long ttl, TimeUnit ttlUnit) { + List params = new ArrayList(map.size()*2 + 2); + params.add(System.currentTimeMillis()); + long ttlTimeout = 0; + if (ttl > 0) { + ttlTimeout = System.currentTimeMillis() + ttlUnit.toMillis(ttl); + } + params.add(ttlTimeout); + for (java.util.Map.Entry t : map.entrySet()) { + if (t.getKey() == null) { + throw new NullPointerException("map key can't be null"); + } + if (t.getValue() == null) { + throw new NullPointerException("map value can't be null"); + } + + params.add(encodeMapKey(t.getKey())); + params.add(encodeMapValue(t.getValue())); + } + + return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_VOID, + "local currentTime = tonumber(table.remove(ARGV, 1)); " + // index is the first parameter + "local ttl = table.remove(ARGV, 1); " + // ttl is the second parameter + "local ttlNumber = tonumber(ttl); " + + "local maxSize = tonumber(redis.call('hget', KEYS[8], 'max-size'));" + + "for i, value in ipairs(ARGV) do " + + "if i % 2 == 0 then " + + "local key = ARGV[i-1];" + + + "local v = redis.call('hget', KEYS[1], key);" + + "local exists = false;" + + "if v ~= false then" + + " local t, val = struct.unpack('dLc0', v);" + + " local expireDate = 92233720368547758;" + + " local expireDateScore = redis.call('zscore', KEYS[2], key);" + + " if expireDateScore ~= false then" + + " expireDate = tonumber(expireDateScore)" + + " end;" + + " if t ~= 0 then" + + " local expireIdle = redis.call('zscore', KEYS[3], key);" + + " if expireIdle ~= false then" + + " expireDate = math.min(expireDate, tonumber(expireIdle))" + + " end;" + + " end;" + + " if expireDate > tonumber(currentTime) then" + + " exists = true;" + + " end;" + + "end;" + + "" + + "if ttlNumber > 0 then " + + " redis.call('zadd', KEYS[2], ttl, key); " + + "else " + + " redis.call('zrem', KEYS[2], key); " + + "end; " + + "" + + "local newvalue = struct.pack('dLc0', 0, string.len(value), value);" + + "redis.call('hset', KEYS[1], key, newvalue);" + + + "local lastAccessTimeSetName = KEYS[6];" + + "if exists == false then" + + " if maxSize ~= nil and maxSize ~= 0 then" + + " redis.call('zadd', lastAccessTimeSetName, currentTime, key);" + + " local cacheSize = tonumber(redis.call('hlen', KEYS[1]));" + + " if cacheSize > maxSize then" + + " local lruItems = redis.call('zrange', lastAccessTimeSetName, 0, cacheSize - maxSize - 1);" + + " for index, lruItem in ipairs(lruItems) do" + + " if lruItem then" + + " local lruItemValue = redis.call('hget', KEYS[1], lruItem);" + + " redis.call('hdel', KEYS[1], lruItem);" + + " redis.call('zrem', KEYS[2], lruItem);" + + " redis.call('zrem', KEYS[3], lruItem);" + + " redis.call('zrem', lastAccessTimeSetName, lruItem);" + + " if lruItemValue ~= false then " + + " local removedChannelName = KEYS[7];" + + " local msg = struct.pack('Lc0Lc0', string.len(lruItem), lruItem, string.len(lruItemValue), lruItemValue);" + + " redis.call('publish', removedChannelName, msg);" + + "end; " + + " end;" + + " end" + + " end;" + + " end;" + + " local msg = struct.pack('Lc0Lc0', string.len(key), key, string.len(value), value);" + + " redis.call('publish', KEYS[4], msg);" + + "else " + + "local t, val = struct.unpack('dLc0', v);" + + "local msg = struct.pack('Lc0Lc0Lc0', string.len(key), key, string.len(value), value, string.len(val), val);" + + "redis.call('publish', KEYS[5], msg);" + + + " if maxSize ~= nil and maxSize ~= 0 then " + + " redis.call('zadd', lastAccessTimeSetName, currentTime, key);" + + " end;" + + "end;" + + "end;" + + "end;", + Arrays.asList(getName(), getTimeoutSetName(), getIdleSetName(), getCreatedChannelName(), + getUpdatedChannelName(), getLastAccessTimeSetName(), getRemovedChannelName(), getOptionsName()), + params.toArray()); + } private Boolean isWindows; diff --git a/redisson/src/main/java/org/redisson/api/RMapCache.java b/redisson/src/main/java/org/redisson/api/RMapCache.java index ddabab8ff..cc649aaa5 100644 --- a/redisson/src/main/java/org/redisson/api/RMapCache.java +++ b/redisson/src/main/java/org/redisson/api/RMapCache.java @@ -15,8 +15,10 @@ */ package org.redisson.api; +import java.util.Map; import java.util.concurrent.TimeUnit; +import org.redisson.api.map.MapWriter; import org.redisson.api.map.event.MapEntryListener; /** @@ -231,6 +233,33 @@ public interface RMapCache extends RMap, RMapCacheAsync, RDest * false if key already exists in the hash. */ boolean fastPutIfAbsent(K key, V value, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit); + + /** + * Associates the specified value with the specified key + * in batch. + *

+ * If {@link MapWriter} is defined then new map entries will be stored in write-through mode. + * + * @param map - mappings to be stored in this map + * @param ttl - time to live for all key\value entries. + * If 0 then stores infinitely. + * @param ttlUnit - time unit + */ + void putAll(java.util.Map map, long ttl, TimeUnit ttlUnit); + + /** + * Associates the specified value with the specified key + * in batch. + *

+ * If {@link MapWriter} is defined then new map entries are stored in write-through mode. + * + * @param map - mappings to be stored in this map + * @param ttl - time to live for all key\value entries. + * If 0 then stores infinitely. + * @param ttlUnit - time unit + * @return void + */ + RFuture putAllAsync(Map map, long ttl, TimeUnit ttlUnit); /** * Returns the number of entries in cache. diff --git a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java index c086dec21..189fb3ba1 100644 --- a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java +++ b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java @@ -649,6 +649,38 @@ public class RedissonMapCacheTest extends BaseMapTest { map.destroy(); } + @Test + public void testPutAllGetTTL() throws InterruptedException { + RMapCache map = redisson.getMapCache("simple06"); + Assert.assertNull(map.get(new SimpleKey("33"))); + Assert.assertNull(map.get(new SimpleKey("55"))); + + Map entries = new HashMap<>(); + entries.put(new SimpleKey("33"), new SimpleValue("44")); + entries.put(new SimpleKey("55"), new SimpleValue("66")); + map.putAll(entries, 2, TimeUnit.SECONDS); + + SimpleValue val1 = map.get(new SimpleKey("33")); + Assert.assertEquals("44", val1.getValue()); + SimpleValue val2 = map.get(new SimpleKey("55")); + Assert.assertEquals("66", val2.getValue()); + + Thread.sleep(1000); + + Assert.assertEquals(2, map.size()); + SimpleValue val3 = map.get(new SimpleKey("33")); + Assert.assertEquals("44", val3.getValue()); + SimpleValue val4 = map.get(new SimpleKey("55")); + Assert.assertEquals("66", val4.getValue()); + Assert.assertEquals(2, map.size()); + + Thread.sleep(1000); + + Assert.assertNull(map.get(new SimpleKey("33"))); + Assert.assertNull(map.get(new SimpleKey("55"))); + map.destroy(); + } + @Test public void testPutIfAbsentTTL() throws Exception { RMapCache map = redisson.getMapCache("simple");