From d3b2cb3213f9d332e6697dc4ce9b7a2525e900dd Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 23 Dec 2015 16:27:59 +0300 Subject: [PATCH] TTL value checking --- .../java/org/redisson/RedissonSetCache.java | 38 ++++++------ .../reactive/RedissonMapCacheReactive.java | 14 +++++ .../reactive/RedissonSetCacheReactive.java | 58 +++++++++++++------ 3 files changed, 75 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/redisson/RedissonSetCache.java b/src/main/java/org/redisson/RedissonSetCache.java index 1df21dfcf..42d2180b5 100644 --- a/src/main/java/org/redisson/RedissonSetCache.java +++ b/src/main/java/org/redisson/RedissonSetCache.java @@ -69,7 +69,6 @@ import net.openhft.hashing.LongHashFunction; public class RedissonSetCache extends RedissonExpirable implements RSetCache { private static final RedisCommand ADD_ALL = new RedisCommand("HMSET", new VoidReplayConvertor()); - private static final RedisCommand EVAL_ADD = new RedisCommand("EVAL", new BooleanReplayConvertor(), 5); private static final RedisCommand> EVAL_CONTAINS_KEY = new RedisCommand>("EVAL", new ObjectListReplayDecoder()); private static final RedisStrictCommand HDEL = new RedisStrictCommand("HDEL", new BooleanReplayConvertor()); @@ -140,16 +139,16 @@ public class RedissonSetCache extends RedissonExpirable implements RSetCache< byte[] key = hash(o); Future> future = commandExecutor.evalReadAsync(getName(), codec, EVAL_CONTAINS_KEY, - "local value = redis.call('hexists', KEYS[1], KEYS[3]); " + + "local value = redis.call('hexists', KEYS[1], ARGV[1]); " + "local expireDate = 92233720368547758; " + "if value == 1 then " + - "local expireDateScore = redis.call('zscore', KEYS[2], KEYS[3]); " + "local expireDateScore = redis.call('zscore', KEYS[2], ARGV[1]); " + "if expireDateScore ~= false then " + "expireDate = tonumber(expireDateScore) " + "end; " + "end;" + "return {expireDate, value}; ", - Arrays.asList(getName(), getTimeoutSetName(), key)); + Arrays.asList(getName(), getTimeoutSetName()), key); addExpireListener(result, future, new BooleanReplayConvertor(), false); @@ -347,13 +346,13 @@ public class RedissonSetCache extends RedissonExpirable implements RSetCache< long timeoutDate = System.currentTimeMillis() + unit.toMillis(ttl); return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN, - "redis.call('zadd', KEYS[2], ARGV[1], KEYS[3]); " + - "if redis.call('hexists', KEYS[1], KEYS[3]) == 0 then " + - "redis.call('hset', KEYS[1], KEYS[3], ARGV[2]); " + + "redis.call('zadd', KEYS[2], ARGV[1], ARGV[3]); " + + "if redis.call('hexists', KEYS[1], ARGV[3]) == 0 then " + + "redis.call('hset', KEYS[1], ARGV[3], ARGV[2]); " + "return 1; " + "end;" + "return 0; ", - Arrays.asList(getName(), getTimeoutSetName(), key), timeoutDate, objectState); + Arrays.asList(getName(), getTimeoutSetName()), timeoutDate, objectState, key); } catch (IOException e) { throw new RuntimeException(e); } @@ -364,15 +363,20 @@ public class RedissonSetCache extends RedissonExpirable implements RSetCache< } @Override - public Future addAsync(V e) { - byte[] key = hash(e); - return commandExecutor.evalWriteAsync(getName(), codec, EVAL_ADD, - "if redis.call('hexists', KEYS[1], KEYS[2]) == 0 then " + - "redis.call('hset', KEYS[1], KEYS[2], ARGV[1]); " + - "return 1; " + - "end; " + - "return 0; ", - Arrays.asList(getName(), key), e); + public Future addAsync(V value) { + try { + byte[] objectState = encode(value); + byte[] key = hash(objectState); + return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN, + "if redis.call('hexists', KEYS[1], ARGV[1]) == 0 then " + + "redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); " + + "return 1; " + + "end; " + + "return 0; ", + Arrays.asList(getName()), key, objectState); + } catch (IOException e) { + throw new RuntimeException(e); + } } @Override diff --git a/src/main/java/org/redisson/reactive/RedissonMapCacheReactive.java b/src/main/java/org/redisson/reactive/RedissonMapCacheReactive.java index b9dd061c7..76c4bdd68 100644 --- a/src/main/java/org/redisson/reactive/RedissonMapCacheReactive.java +++ b/src/main/java/org/redisson/reactive/RedissonMapCacheReactive.java @@ -199,6 +199,13 @@ public class RedissonMapCacheReactive extends RedissonMapReactive im @Override public Publisher putIfAbsent(K key, V value, long ttl, TimeUnit unit) { + if (ttl < 0) { + throw new IllegalArgumentException("TTL can't be negative"); + } + if (ttl == 0) { + return putIfAbsent(key, value); + } + if (unit == null) { throw new NullPointerException("TimeUnit param can't be null"); } @@ -282,6 +289,13 @@ public class RedissonMapCacheReactive extends RedissonMapReactive im @Override public Publisher put(K key, V value, long ttl, TimeUnit unit) { + if (ttl < 0) { + throw new IllegalArgumentException("TTL can't be negative"); + } + if (ttl == 0) { + return put(key, value); + } + if (unit == null) { throw new NullPointerException("TimeUnit param can't be null"); } diff --git a/src/main/java/org/redisson/reactive/RedissonSetCacheReactive.java b/src/main/java/org/redisson/reactive/RedissonSetCacheReactive.java index 2d43fdbe3..2c313bc1d 100644 --- a/src/main/java/org/redisson/reactive/RedissonSetCacheReactive.java +++ b/src/main/java/org/redisson/reactive/RedissonSetCacheReactive.java @@ -36,7 +36,6 @@ import org.redisson.client.protocol.RedisCommands; import org.redisson.client.protocol.RedisStrictCommand; import org.redisson.client.protocol.convertor.BooleanReplayConvertor; import org.redisson.client.protocol.convertor.Convertor; -import org.redisson.client.protocol.convertor.LongReplayConvertor; import org.redisson.client.protocol.convertor.VoidReplayConvertor; import org.redisson.client.protocol.decoder.ListScanResult; import org.redisson.client.protocol.decoder.ObjectListReplayDecoder; @@ -71,7 +70,6 @@ import reactor.rx.action.support.DefaultSubscriber; public class RedissonSetCacheReactive extends RedissonExpirableReactive implements RSetCacheReactive { private static final RedisCommand ADD_ALL = new RedisCommand("HMSET", new VoidReplayConvertor()); - private static final RedisCommand EVAL_ADD = new RedisCommand("EVAL", new LongReplayConvertor(), 5); private static final RedisCommand> EVAL_CONTAINS_KEY = new RedisCommand>("EVAL", new ObjectListReplayDecoder()); private static final RedisStrictCommand HDEL = new RedisStrictCommand("HDEL", new BooleanReplayConvertor()); @@ -127,16 +125,16 @@ public class RedissonSetCacheReactive extends RedissonExpirableReactive imple byte[] key = hash(o); Publisher> future = commandExecutor.evalReadReactive(getName(), codec, EVAL_CONTAINS_KEY, - "local value = redis.call('hexists', KEYS[1], KEYS[3]); " + + "local value = redis.call('hexists', KEYS[1], ARGV[1]); " + "local expireDate = 92233720368547758; " + "if value == 1 then " + - "local expireDateScore = redis.call('zscore', KEYS[2], KEYS[3]); " + "local expireDateScore = redis.call('zscore', KEYS[2], ARGV[1]); " + "if expireDateScore ~= false then " + "expireDate = tonumber(expireDateScore) " + "end; " + "end;" + "return {expireDate, value}; ", - Arrays.asList(getName(), getTimeoutSetName(), key)); + Arrays.asList(getName(), getTimeoutSetName()), key); addExpireListener(result, future, new BooleanReplayConvertor(), false); @@ -206,6 +204,25 @@ public class RedissonSetCacheReactive extends RedissonExpirableReactive imple @Override public Publisher add(V value, long ttl, TimeUnit unit) { + if (ttl < 0) { + throw new IllegalArgumentException("TTL can't be negative"); + } + if (ttl == 0) { + try { + byte[] objectState = encode(value); + byte[] key = hash(objectState); + return commandExecutor.evalWriteReactive(getName(), codec, RedisCommands.EVAL_BOOLEAN, + "if redis.call('hexists', KEYS[1], ARGV[1]) == 0 then " + + "redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); " + + "return 1; " + + "end; " + + "return 0; ", + Arrays.asList(getName()), key, objectState); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + if (unit == null) { throw new NullPointerException("TimeUnit param can't be null"); } @@ -216,13 +233,13 @@ public class RedissonSetCacheReactive extends RedissonExpirableReactive imple long timeoutDate = System.currentTimeMillis() + unit.toMillis(ttl); return commandExecutor.evalWriteReactive(getName(), codec, RedisCommands.EVAL_BOOLEAN, - "redis.call('zadd', KEYS[2], ARGV[1], KEYS[3]); " + - "if redis.call('hexists', KEYS[1], KEYS[3]) == 0 then " + - "redis.call('hset', KEYS[1], KEYS[3], ARGV[2]); " + + "redis.call('zadd', KEYS[2], ARGV[1], ARGV[3]); " + + "if redis.call('hexists', KEYS[1], ARGV[3]) == 0 then " + + "redis.call('hset', KEYS[1], ARGV[3], ARGV[2]); " + "return 1; " + "end;" + "return 0; ", - Arrays.asList(getName(), getTimeoutSetName(), key), timeoutDate, objectState); + Arrays.asList(getName(), getTimeoutSetName()), timeoutDate, objectState, key); } catch (IOException e) { throw new RuntimeException(e); } @@ -233,15 +250,20 @@ public class RedissonSetCacheReactive extends RedissonExpirableReactive imple } @Override - public Publisher add(V e) { - byte[] key = hash(e); - return commandExecutor.evalWriteReactive(getName(), codec, EVAL_ADD, - "if redis.call('hexists', KEYS[1], KEYS[2]) == 0 then " + - "redis.call('hset', KEYS[1], KEYS[2], ARGV[1]); " + - "return 1; " + - "end; " + - "return 0; ", - Arrays.asList(getName(), key), e); + public Publisher add(V value) { + try { + byte[] objectState = encode(value); + byte[] key = hash(objectState); + return commandExecutor.evalWriteReactive(getName(), codec, RedisCommands.EVAL_LONG, + "if redis.call('hexists', KEYS[1], ARGV[1]) == 0 then " + + "redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); " + + "return 1; " + + "end; " + + "return 0; ", + Arrays.asList(getName()), key, objectState); + } catch (IOException e) { + throw new RuntimeException(e); + } } @Override