提交 51373418 编写于 作者: N Nikita Koksharov

Feature - add method to update ttl and idleTime of entry by key. #3423

上级 43c90ef7
......@@ -1030,6 +1030,82 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
return future;
}
@Override
public boolean updateEntryExpiration(K key, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit) {
return get(updateEntryExpirationAsync(key, ttl, ttlUnit, maxIdleTime, maxIdleUnit));
}
@Override
public RFuture<Boolean> updateEntryExpirationAsync(K key, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit) {
checkKey(key);
long currentTime = System.currentTimeMillis();
long ttlTimeout = 0;
if (ttl > 0) {
ttlTimeout = currentTime + ttlUnit.toMillis(ttl);
}
long maxIdleTimeout = 0;
if (maxIdleTime > 0) {
long maxIdleDelta = maxIdleUnit.toMillis(maxIdleTime);
maxIdleTimeout = currentTime + maxIdleDelta;
}
String name = getRawName(key);
RFuture<Boolean> future = commandExecutor.evalWriteAsync(name, codec, RedisCommands.EVAL_BOOLEAN,
"local value = redis.call('hget', KEYS[1], ARGV[4]); "
+ "local t, val;"
+ "if value == false then "
+ "return 0; "
+ "else "
+ "t, val = struct.unpack('dLc0', value); "
+ "local expireDate = 92233720368547758; "
+ "local expireDateScore = redis.call('zscore', KEYS[2], ARGV[4]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if t ~= 0 then "
+ "local expireIdle = redis.call('zscore', KEYS[3], ARGV[4]); "
+ "if expireIdle ~= false then "
+ "expireDate = math.min(expireDate, tonumber(expireIdle)) "
+ "end; "
+ "end; "
+ "if expireDate <= tonumber(ARGV[1]) then "
+ "return 0; "
+ "end; "
+ "end; " +
"if tonumber(ARGV[2]) > 0 then "
+ "redis.call('zadd', KEYS[2], ARGV[2], ARGV[4]); "
+ "else "
+ "redis.call('zrem', KEYS[2], ARGV[4]); "
+ "end; "
+ "if tonumber(ARGV[3]) > 0 then "
+ "redis.call('zadd', KEYS[3], ARGV[3], ARGV[4]); "
+ "else "
+ "redis.call('zrem', KEYS[3], ARGV[4]); "
+ "end; " +
// last access time
"local maxSize = tonumber(redis.call('hget', KEYS[5], 'max-size')); " +
"local mode = redis.call('hget', KEYS[5], 'mode'); " +
"if maxSize ~= nil and maxSize ~= 0 then " +
"local currentTime = tonumber(ARGV[1]); " +
"if mode == false or mode == 'LRU' then " +
"redis.call('zadd', KEYS[4], currentTime, ARGV[4]); " +
"end; " +
"if mode == 'LFU' then " +
"redis.call('zincrby', KEYS[4], 1, ARGV[4]); " +
"end; " +
"end; " +
"return 1;",
Arrays.asList(name, getTimeoutSetName(name), getIdleSetName(name),
getLastAccessTimeSetName(name), getOptionsName(name)),
System.currentTimeMillis(), ttlTimeout, maxIdleTimeout, encodeMapKey(key));
return future;
}
@Override
public RFuture<V> putAsync(K key, V value, long ttl, TimeUnit ttlUnit) {
return putAsync(key, value, ttl, ttlUnit, 0, null);
......
......@@ -265,7 +265,30 @@ public interface RMapCache<K, V> extends RMap<K, V>, RMapCacheAsync<K, V>, RDest
* @param ttlUnit - time unit
*/
void putAll(java.util.Map<? extends K, ? extends V> map, long ttl, TimeUnit ttlUnit);
/**
* Updates time to live and max idle time of specified entry by key.
* Entry expires when specified time to live or max idle time was reached.
* <p>
* Returns <code>false</code> if entry already expired or doesn't exist,
* otherwise returns <code>true</code>.
*
* @param key - map key
* @param ttl - time to live for key\value entry.
* If <code>0</code> then time to live doesn't affect entry expiration.
* @param ttlUnit - time unit
* @param maxIdleTime - max idle time for key\value entry.
* If <code>0</code> then max idle time doesn't affect entry expiration.
* @param maxIdleUnit - time unit
* <p>
* if <code>maxIdleTime</code> and <code>ttl</code> params are equal to <code>0</code>
* then entry stores infinitely.
*
* @return returns <code>false</code> if entry already expired or doesn't exist,
* otherwise returns <code>true</code>.
*/
boolean updateEntryExpiration(K key, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit);
/**
* Returns the number of entries in cache.
* This number can reflects expired entries too
......
......@@ -249,6 +249,29 @@ public interface RMapCacheAsync<K, V> extends RMapAsync<K, V> {
*/
RFuture<Boolean> fastPutIfAbsentAsync(K key, V value, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit);
/**
* Updates time to live and max idle time of specified entry by key.
* Entry expires when specified time to live or max idle time was reached.
* <p>
* Returns <code>false</code> if entry already expired or doesn't exist,
* otherwise returns <code>true</code>.
*
* @param key - map key
* @param ttl - time to live for key\value entry.
* If <code>0</code> then time to live doesn't affect entry expiration.
* @param ttlUnit - time unit
* @param maxIdleTime - max idle time for key\value entry.
* If <code>0</code> then max idle time doesn't affect entry expiration.
* @param maxIdleUnit - time unit
* <p>
* if <code>maxIdleTime</code> and <code>ttl</code> params are equal to <code>0</code>
* then entry stores infinitely.
*
* @return returns <code>false</code> if entry already expired or doesn't exist,
* otherwise returns <code>true</code>.
*/
RFuture<Boolean> updateEntryExpirationAsync(K key, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit);
/**
* Returns the number of entries in cache.
* This number can reflects expired entries too
......
......@@ -40,11 +40,21 @@ import org.redisson.eviction.EvictionScheduler;
public class RedissonMapCacheTest extends BaseMapTest {
@Test
public void testUpdateEntryExpiration() throws InterruptedException {
RMapCache<Integer, Integer> cache = redisson.getMapCache("testUpdateEntryExpiration");
cache.put(1, 2, 3, TimeUnit.SECONDS);
Thread.sleep(2000);
long ttl = cache.remainTimeToLive(1);
assertThat(ttl).isBetween(900L, 1000L);
cache.updateEntryExpiration(1, 2, TimeUnit.SECONDS, -1, TimeUnit.SECONDS);
long ttl2 = cache.remainTimeToLive(1);
assertThat(ttl2).isBetween(1900L, 2000L);
}
@Test
public void testRemoveListener() {
RMapCache<Long, String> rMapCache = redisson.getMapCache("test",
LocalCachedMapOptions.<Long, String>defaults().evictionPolicy(LocalCachedMapOptions.EvictionPolicy.LRU)
.timeToLive(-1));
RMapCache<Long, String> rMapCache = redisson.getMapCache("test");
rMapCache.trySetMaxSize(5);
AtomicBoolean removed = new AtomicBoolean();
rMapCache.addListener(new EntryRemovedListener() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册