Fixed - RMapCache.computeIfAbsentAsync() isn't implemented. #6276

pull/6287/head
Nikita Koksharov 4 months ago
parent a90000da55
commit 9aaf0a2f85

@ -157,6 +157,38 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
}
}
@Override
public RFuture<V> computeIfAbsentAsync(K key, Duration ttl, Function<? super K, ? extends V> mappingFunction) {
checkNotBatch();
checkKey(key);
Objects.requireNonNull(mappingFunction);
RLock lock = getLock(key);
long threadId = Thread.currentThread().getId();
CompletionStage<V> f = lock.lockAsync(threadId)
.thenCompose(r -> {
RFuture<V> oldValueFuture = getAsync(key, threadId);
return oldValueFuture.thenCompose(oldValue -> {
if (oldValue != null) {
return CompletableFuture.completedFuture(oldValue);
}
return CompletableFuture.supplyAsync(() -> mappingFunction.apply(key), getServiceManager().getExecutor())
.thenCompose(newValue -> {
if (newValue != null) {
return fastPutAsync(key, newValue, ttl.toMillis(), TimeUnit.MILLISECONDS).thenApply(rr -> newValue);
}
return CompletableFuture.completedFuture(null);
});
}).whenComplete((c, e) -> {
lock.unlockAsync(threadId);
});
});
return new CompletableFutureWrapper<>(f);
}
@Override
public void setMaxSize(int maxSize) {
get(setMaxSizeAsync(maxSize));

@ -23,6 +23,7 @@ import java.time.Duration;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/**
* <p>Map-based cache with ability to set TTL for each entry via
@ -253,6 +254,21 @@ public interface RMapCacheAsync<K, V> extends RMapAsync<K, V> {
*/
RFuture<Boolean> fastPutIfAbsentAsync(K key, V value, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit);
/**
* If the specified key is not already associated
* with a value, attempts to compute its value using the given mapping function and enters it into this map .
* <p>
* Stores value mapped by key with specified time to live.
* Entry expires after specified time to live.
*
* @param key - map key
* @param ttl - time to live for key\value entry.
* If <code>0</code> then stores infinitely.
* @param mappingFunction the mapping function to compute a value
* @return current associated value
*/
RFuture<V> computeIfAbsentAsync(K key, Duration ttl, Function<? super K, ? extends V> mappingFunction);
/**
* Use {@link #expireEntryAsync(Object, Duration, Duration)} instead.
*

@ -140,7 +140,8 @@ public interface RMapCacheReactive<K, V> extends RMapReactive<K, V>, RDestroyabl
* @param mappingFunction the mapping function to compute a value
* @return current associated value
*/
Mono<V> computeIfAbsentAsync(K key, Duration ttl, Function<? super K, ? extends V> mappingFunction);
Mono<V> computeIfAbsent(K key, Duration ttl, Function<? super K, ? extends V> mappingFunction);
/**
* Stores value mapped by key with specified time to live.
* Entry expires after specified time to live.

@ -142,7 +142,7 @@ public interface RMapCacheRx<K, V> extends RMapRx<K, V>, RDestroyable {
* @param mappingFunction the mapping function to compute a value
* @return current associated value
*/
Maybe<V> computeIfAbsentAsync(K key, Duration ttl, Function<? super K, ? extends V> mappingFunction);
Maybe<V> computeIfAbsent(K key, Duration ttl, Function<? super K, ? extends V> mappingFunction);
/**
* Stores value mapped by key with specified time to live.
* Entry expires after specified time to live.

@ -1,23 +1,19 @@
package org.redisson;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.redisson.api.RLockReactive;
import org.redisson.api.RMapCacheReactive;
import org.redisson.api.RMapReactive;
import java.io.Serializable;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import static org.assertj.core.api.Assertions.assertThat;
public class RedissonMapCacheReactiveTest extends BaseReactiveTest {
public static class SimpleKey implements Serializable {
@ -251,6 +247,20 @@ public class RedissonMapCacheReactiveTest extends BaseReactiveTest {
assertThat(toIterable(map.keyIterator())).containsOnly(1, 2, 3, 4, 5, 6);
}
@Test
public void testComputeIfAbsent() {
RMapCacheReactive<Integer, String> map = redisson.getMapCache("simple");
map.computeIfAbsent(7, Duration.ofSeconds(1), new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return "1234";
}
}).block();
assertThat(map.get(7).block()).isEqualTo("1234");
}
@Test
public void testContainsValue() throws InterruptedException {
RMapCacheReactive<SimpleKey, SimpleValue> map = redisson.getMapCache("simple31");

Loading…
Cancel
Save