Feature - RMapCache.getAllWithTTLOnly() method added. #3907

pull/5038/head
Nikita Koksharov 2 years ago
parent 888d46abed
commit 32511e67c3

@ -1294,6 +1294,72 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
return new CompletableFutureWrapper<>(f);
}
@Override
public Map<K, V> getAllWithTTLOnly(Set<K> keys) {
return get(getAllWithTTLOnlyAsync(keys));
}
@Override
public RFuture<Map<K, V>> getAllWithTTLOnlyAsync(Set<K> keys) {
if (keys.isEmpty()) {
return new CompletableFutureWrapper<>(Collections.emptyMap());
}
RFuture<Map<K, V>> future = getAllWithTTLOnlyOperationAsync(keys);
if (hasNoLoader()) {
return future;
}
CompletionStage<Map<K, V>> f = future.thenCompose(res -> {
if (!res.keySet().containsAll(keys)) {
Set<K> newKeys = new HashSet<K>(keys);
newKeys.removeAll(res.keySet());
CompletionStage<Map<K, V>> ff = loadAllMapAsync(newKeys.spliterator(), false, 1);
return ff.thenApply(map -> {
res.putAll(map);
return res;
});
}
return CompletableFuture.completedFuture(res);
});
return new CompletableFutureWrapper<>(f);
}
protected RFuture<Map<K, V>> getAllWithTTLOnlyOperationAsync(Set<K> keys) {
List<Object> args = new ArrayList<>(keys.size() + 1);
List<Object> plainKeys = new ArrayList<>(keys);
args.add(System.currentTimeMillis());
encodeMapKeys(args, keys);
return commandExecutor.evalReadAsync(getRawName(), codec, new RedisCommand<Map<Object, Object>>("EVAL",
new MapValueDecoder(new MapGetAllDecoder(plainKeys, 0))),
"local expireHead = redis.call('zrange', KEYS[2], 0, 0, 'withscores'); " +
"local currentTime = tonumber(table.remove(ARGV, 1)); " + // index is the first parameter
"local hasExpire = #expireHead == 2 and tonumber(expireHead[2]) <= currentTime; " +
"local map = {}; " +
"for i = 1, #ARGV, 1 do " +
" local value = redis.call('hget', KEYS[1], ARGV[i]); " +
" map[i] = false;" +
" if value ~= false then " +
" local key = ARGV[i]; " +
" local t, val = struct.unpack('dLc0', value); " +
" map[i] = val; " +
" if hasExpire then " +
" local expireDate = redis.call('zscore', KEYS[2], key); " +
" if expireDate ~= false and tonumber(expireDate) <= currentTime then " +
" map[i] = false; " +
" end; " +
" end; " +
" end; " +
"end; " +
"return map;",
Arrays.asList(getRawName(), getTimeoutSetName()),
args.toArray());
}
@Override
public long remainTimeToLive(K key) {
return get(remainTimeToLiveAsync(key));

@ -303,7 +303,7 @@ public interface RMap<K, V> extends ConcurrentMap<K, V>, RExpirable, RMapAsync<K
* <p>
* The returned map is <b>NOT</b> backed by the original map.
*
* @param keys - map keys
* @param keys map keys
* @return Map slice
*/
Map<K, V> getAll(Set<K> keys);

@ -19,6 +19,8 @@ import org.redisson.api.map.MapLoader;
import org.redisson.api.map.MapWriter;
import org.redisson.api.map.event.MapEntryListener;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
@ -303,6 +305,20 @@ public interface RMapCache<K, V> extends RMap<K, V>, RMapCacheAsync<K, V> {
*/
V getWithTTLOnly(K key);
/**
* Returns map slice contained the mappings with defined <code>keys</code>.
* <p>
* If map doesn't contain value/values for specified key/keys and {@link MapLoader} is defined
* then value/values will be loaded in read-through mode.
* <p>
* NOTE: Idle time of entry is not taken into account.
* Entry last access time isn't modified if map limited by size.
*
* @param keys map keys
* @return Map slice
*/
Map<K, V> getAllWithTTLOnly(Set<K> keys);
/**
* Returns the number of entries in cache.
* This number can reflects expired entries too

@ -20,6 +20,7 @@ import org.redisson.api.map.MapWriter;
import org.redisson.api.map.event.MapEntryListener;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
@ -288,6 +289,20 @@ public interface RMapCacheAsync<K, V> extends RMapAsync<K, V> {
*/
RFuture<V> getWithTTLOnlyAsync(K key);
/**
* Returns map slice contained the mappings with defined <code>keys</code>.
* <p>
* If map doesn't contain value/values for specified key/keys and {@link MapLoader} is defined
* then value/values will be loaded in read-through mode.
* <p>
* NOTE: Idle time of entry is not taken into account.
* Entry last access time isn't modified if map limited by size.
*
* @param keys map keys
* @return Map slice
*/
RFuture<Map<K, V>> getAllWithTTLOnlyAsync(Set<K> keys);
/**
* Returns the number of entries in cache.
* This number can reflects expired entries too

@ -19,6 +19,8 @@ import org.redisson.api.map.MapLoader;
import org.redisson.api.map.event.MapEntryListener;
import reactor.core.publisher.Mono;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
@ -273,6 +275,20 @@ public interface RMapCacheReactive<K, V> extends RMapReactive<K, V>, RDestroyabl
*/
Mono<V> getWithTTLOnly(K key);
/**
* Returns map slice contained the mappings with defined <code>keys</code>.
* <p>
* If map doesn't contain value/values for specified key/keys and {@link MapLoader} is defined
* then value/values will be loaded in read-through mode.
* <p>
* NOTE: Idle time of entry is not taken into account.
* Entry last access time isn't modified if map limited by size.
*
* @param keys map keys
* @return Map slice
*/
Mono<Map<K, V>> getAllWithTTLOnly(Set<K> keys);
/**
* Returns the number of entries in cache.
* This number can reflects expired entries too

@ -21,6 +21,8 @@ import io.reactivex.rxjava3.core.Single;
import org.redisson.api.map.MapLoader;
import org.redisson.api.map.event.MapEntryListener;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
@ -275,6 +277,20 @@ public interface RMapCacheRx<K, V> extends RMapRx<K, V>, RDestroyable {
*/
Maybe<V> getWithTTLOnly(K key);
/**
* Returns map slice contained the mappings with defined <code>keys</code>.
* <p>
* If map doesn't contain value/values for specified key/keys and {@link MapLoader} is defined
* then value/values will be loaded in read-through mode.
* <p>
* NOTE: Idle time of entry is not taken into account.
* Entry last access time isn't modified if map limited by size.
*
* @param keys map keys
* @return Map slice
*/
Single<Map<K, V>> getAllWithTTLOnly(Set<K> keys);
/**
* Returns the number of entries in cache.
* This number can reflects expired entries too

@ -49,6 +49,24 @@ public class RedissonMapCacheTest extends BaseMapTest {
assertThat(mapCache.get("k1")).isEqualTo("v2");
}
@Test
public void testGetAllWithTTLOnly() throws InterruptedException {
RMapCache<Integer, Integer> cache = redisson.getMapCache("testGetAllWithTTLOnly");
cache.put(1, 2, 3, TimeUnit.SECONDS);
cache.put(3, 4, 1, TimeUnit.SECONDS);
cache.put(5, 6, 1, TimeUnit.SECONDS);
Map<Integer, Integer> map = cache.getAllWithTTLOnly(new HashSet<>(Arrays.asList(1, 3, 5)));
assertThat(map).containsOnlyKeys(1, 3, 5);
assertThat(map).containsValues(2, 4, 6);
Thread.sleep(1500);
map = cache.getAllWithTTLOnly(new HashSet<>(Arrays.asList(1, 3, 5)));
assertThat(map).containsOnlyKeys(1);
assertThat(map).containsValues(2);
}
@Test
public void testGetWithTTLOnly() throws InterruptedException {
RMapCache<Integer, Integer> cache = redisson.getMapCache("testUpdateEntryExpiration");

Loading…
Cancel
Save