Feature - tryAdd() method added to RSet and RSetCache objects #3218

pull/3235/head
Nikita Koksharov 4 years ago
parent a51e6190ed
commit 7ec4c8f519

@ -610,6 +610,27 @@ public class RedissonSet<V> extends RedissonExpirable implements RSet<V>, ScanIt
return commandExecutor.writeAsync(getName(), codec, RedisCommands.SORT_TO, params.toArray());
}
@Override
public boolean tryAdd(V... values) {
return get(tryAddAsync(values));
}
@Override
public RFuture<Boolean> tryAddAsync(V... values) {
return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"for i, v in ipairs(ARGV) do " +
"if redis.call('sismember', KEYS[1], v) == 1 then " +
"return 0; " +
"end; " +
"end; " +
"for i=1, #ARGV, 5000 do " +
"redis.call('sadd', KEYS[1], unpack(ARGV, i, math.min(i+4999, #ARGV))); " +
"end; " +
"return 1; ",
Arrays.asList(getName()), encode(values).toArray());
}
@Override
public RPermitExpirableSemaphore getPermitExpirableSemaphore(V value) {
String lockName = getLockByValue(value, "permitexpirablesemaphore");

@ -255,6 +255,48 @@ public class RedissonSetCache<V> extends RedissonExpirable implements RSetCache<
Arrays.asList(name), System.currentTimeMillis(), timeoutDate, objectState);
}
@Override
public boolean tryAdd(V... values) {
return get(tryAddAsync(values));
}
@Override
public RFuture<Boolean> tryAddAsync(V... values) {
return tryAddAsync(92233720368547758L - System.currentTimeMillis(), TimeUnit.MILLISECONDS, values);
}
@Override
public boolean tryAdd(long ttl, TimeUnit unit, V... values) {
return get(tryAddAsync(ttl, unit, values));
}
@Override
public RFuture<Boolean> tryAddAsync(long ttl, TimeUnit unit, V... values) {
long timeoutDate = System.currentTimeMillis() + unit.toMillis(ttl);
if (ttl == 0) {
timeoutDate = 92233720368547758L - System.currentTimeMillis();
}
List<Object> params = new ArrayList<>();
params.add(System.currentTimeMillis());
params.add(timeoutDate);
params.addAll(encode(values));
return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN,
"for i, v in ipairs(ARGV) do " +
"local expireDateScore = redis.call('zscore', KEYS[1], v); " +
"if expireDateScore ~= false and tonumber(expireDateScore) > tonumber(ARGV[1]) then " +
"return 0; " +
"end; " +
"end; " +
"for i=3, #ARGV, 1 do " +
"redis.call('zadd', KEYS[1], ARGV[2], ARGV[i]); " +
"end; " +
"return 1; ",
Arrays.asList(getName()), params.toArray());
}
@Override
public RFuture<Boolean> addAsync(V value) {
return addAsync(value, 92233720368547758L - System.currentTimeMillis(), TimeUnit.MILLISECONDS);

@ -78,6 +78,16 @@ public class RedissonSetMultimapValues<V> extends RedissonExpirable implements R
return null;
}
@Override
public boolean tryAdd(V... values) {
return get(tryAddAsync(values));
}
@Override
public RFuture<Boolean> tryAddAsync(V... values) {
return set.tryAddAsync(values);
}
@Override
public RFuture<Boolean> clearExpireAsync() {
throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set");

@ -15,12 +15,12 @@
*/
package org.redisson.api;
import org.redisson.api.mapreduce.RCollectionMapReduce;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Stream;
import org.redisson.api.mapreduce.RCollectionMapReduce;
/**
* Redis based implementation of {@link java.util.Set}
*
@ -246,4 +246,13 @@ public interface RSet<V> extends Set<V>, RExpirable, RSetAsync<V>, RSortable<Set
*/
Set<V> readIntersection(String... names);
/**
* Tries to add elements only if none of them in set.
*
* @param values - values to add
* @return <code>true</code> if elements successfully added,
* otherwise <code>false</code>.
*/
boolean tryAdd(V... values);
}

@ -129,5 +129,14 @@ public interface RSetAsync<V> extends RCollectionAsync<V>, RSortableAsync<Set<V>
* @return values
*/
RFuture<Set<V>> readIntersectionAsync(String... names);
/**
* Tries to add elements only if none of them in set.
*
* @param values - values to add
* @return <code>true</code> if elements successfully added,
* otherwise <code>false</code>.
*/
RFuture<Boolean> tryAddAsync(V... values);
}

@ -184,4 +184,25 @@ public interface RSetCache<V> extends Set<V>, RExpirable, RSetCacheAsync<V>, RDe
*/
Set<V> readAll();
/**
* Tries to add elements only if none of them in set.
*
* @param values - values to add
* @return <code>true</code> if elements successfully added,
* otherwise <code>false</code>.
*/
boolean tryAdd(V... values);
/**
* Tries to add elements only if none of them in set.
*
* @param values - values to add
* @param ttl - time to live for value.
* If <code>0</code> then stores infinitely.
* @param unit - time unit
* @return <code>true</code> if elements successfully added,
* otherwise <code>false</code>.
*/
boolean tryAdd(long ttl, TimeUnit unit, V... values);
}

@ -57,4 +57,25 @@ public interface RSetCacheAsync<V> extends RCollectionAsync<V> {
*/
RFuture<Set<V>> readAllAsync();
/**
* Tries to add elements only if none of them in set.
*
* @param values - values to add
* @return <code>true</code> if elements successfully added,
* otherwise <code>false</code>.
*/
RFuture<Boolean> tryAddAsync(V... values);
/**
* Tries to add elements only if none of them in set.
*
* @param values - values to add
* @param ttl - time to live for value.
* If <code>0</code> then stores infinitely.
* @param unit - time unit
* @return <code>true</code> if elements successfully added,
* otherwise <code>false</code>.
*/
RFuture<Boolean> tryAddAsync(long ttl, TimeUnit unit, V... values);
}

@ -16,7 +16,9 @@ import java.util.concurrent.TimeUnit;
import org.joor.Reflect;
import org.junit.Assert;
import org.junit.Test;
import org.redisson.api.RSet;
import org.redisson.api.RSetCache;
import org.redisson.client.codec.IntegerCodec;
import org.redisson.eviction.EvictionScheduler;
public class RedissonSetCacheTest extends BaseTest {
@ -34,7 +36,31 @@ public class RedissonSetCacheTest extends BaseTest {
}
}
@Test
public void testTryAdd() {
RSetCache<String> cache = redisson.getSetCache("list", IntegerCodec.INSTANCE);
Set<String> names = new HashSet<>();
int elements = 200000;
for (int i = 0; i < elements; i++) {
names.add("name" + i);
}
boolean s = cache.tryAdd(names.toArray(new String[]{}));
assertThat(s).isTrue();
assertThat(cache.size()).isEqualTo(elements);
Set<String> names2 = new HashSet<>();
for (int i = elements+1; i < elements + 10000; i++) {
names2.add("name" + i);
}
names2.add("name10");
boolean r = cache.tryAdd(names2.toArray(new String[]{}));
assertThat(r).isFalse();
assertThat(cache.size()).isEqualTo(elements);
}
@Test
public void testDestroy() {
RSetCache<String> cache = redisson.getSetCache("test");

@ -42,6 +42,30 @@ public class RedissonSetTest extends BaseTest {
}
@Test
public void testTryAdd() {
RSet<String> set = redisson.getSet("list", IntegerCodec.INSTANCE);
Set<String> names = new HashSet<>();
int elements = 200000;
for (int i = 0; i < elements; i++) {
names.add("name" + i);
}
boolean s = set.tryAdd(names.toArray(new String[]{}));
assertThat(s).isTrue();
assertThat(set.size()).isEqualTo(elements);
Set<String> names2 = new HashSet<>();
for (int i = elements+1; i < elements + 10000; i++) {
names2.add("name" + i);
}
names2.add("name10");
boolean r = set.tryAdd(names2.toArray(new String[]{}));
assertThat(r).isFalse();
assertThat(set.size()).isEqualTo(elements);
}
@Test
public void testSortOrder() {
RSet<Integer> list = redisson.getSet("list", IntegerCodec.INSTANCE);

Loading…
Cancel
Save