Merge branch 'master' into 3.0.0

# Conflicts:
#	pom.xml
#	redisson-all/pom.xml
#	redisson-tomcat/pom.xml
#	redisson-tomcat/redisson-tomcat-6/pom.xml
#	redisson-tomcat/redisson-tomcat-7/pom.xml
#	redisson-tomcat/redisson-tomcat-8/pom.xml
#	redisson-tomcat/redisson-tomcat-9/pom.xml
#	redisson/pom.xml
pull/1821/head
Nikita 7 years ago
commit ec1147ee98

@ -4,6 +4,17 @@ Redisson Releases History
Try __[Redisson PRO](https://redisson.pro)__ version.
### 27-Mar-2018 - versions 2.11.4 and 3.6.4 released
Feature - `RSet.getLock` method added
Fixed - race condition with load balancer node selection
Fixed - `READONLY can't write against a read only slave` error during failover
Fixed - NPE during failover in Sentinel mode
Fixed - `JCache.getAll` causes io.netty.util.IllegalReferenceCountException
Fixed - NPE in CommandDecoder handler while using RBatch object
Fixed - `RSortedSet` object tries to compare wrong types
Fixed - `ClassCastException` in `RListMultimapCache.removeAll` method
### 14-Mar-2018 - versions 2.11.3 and 3.6.3 released
Feature - DNS monitoring for Sentinel nodes

@ -1,13 +1,13 @@
Redisson: Redis based In-Memory Data Grid for Java.
====
[Quick start](https://github.com/redisson/redisson#quick-start) | [Documentation](https://github.com/redisson/redisson/wiki) | [Javadocs](http://www.javadoc.io/doc/org.redisson/redisson/3.5.7) | [Changelog](https://github.com/redisson/redisson/blob/master/CHANGELOG.md) | [Code examples](https://github.com/redisson/redisson-examples) | [Support chat](https://gitter.im/mrniko/redisson) | **[Redisson PRO](https://redisson.pro)**
[Quick start](https://github.com/redisson/redisson#quick-start) | [Documentation](https://github.com/redisson/redisson/wiki) | [Javadocs](http://www.javadoc.io/doc/org.redisson/redisson/3.5.7) | [Changelog](https://github.com/redisson/redisson/blob/master/CHANGELOG.md) | [Code examples](https://github.com/redisson/redisson-examples) | [FAQs](https://github.com/redisson/redisson/wiki/16.-FAQ) | [Support chat](https://gitter.im/mrniko/redisson) | **[Redisson PRO](https://redisson.pro)**
Based on high-performance async and lock-free Java Redis client and [Netty](http://netty.io) framework.
| Stable <br/> Release Version | Release Date | JDK Version<br/> compatibility | `CompletionStage` <br/> support | `ProjectReactor` version<br/> compatibility |
| ------------- | ------------- | ------------| -----------| -----------|
| 3.6.3 | 14.03.2018 | 1.8, 1.9+ | Yes | 3.1.x |
| 2.11.3 | 14.03.2018 | 1.6, 1.7, 1.8, 1.9 and Android | No | 2.0.8 |
| 3.6.4 | 27.03.2018 | 1.8, 1.9+ | Yes | 3.1.x |
| 2.11.4 | 27.03.2018 | 1.6, 1.7, 1.8, 1.9 and Android | No | 2.0.8 |
Features
@ -95,23 +95,23 @@ Quick start
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.3</version>
<version>3.6.4</version>
</dependency>
<!-- JDK 1.6+ compatible -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.11.3</version>
<version>2.11.4</version>
</dependency>
#### Gradle
// JDK 1.8+ compatible
compile 'org.redisson:redisson:3.6.3'
compile 'org.redisson:redisson:3.6.4'
// JDK 1.6+ compatible
compile 'org.redisson:redisson:2.11.3'
compile 'org.redisson:redisson:2.11.4'
#### Java
@ -133,14 +133,32 @@ RExecutorService executor = redisson.getExecutorService("myExecutorService");
```
FAQs
===============================
[Q: I saw a RedisTimeOutException, What does it mean? What shall I do? Can Redisson Team fix it?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-i-saw-a-redistimeoutexception-what-does-it-mean-what-shall-i-do-can-redisson-team-fix-it)
[Q: I saw a com.fasterxml.jackson.databind.JsonMappingException during deserialization process, can you fix it?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-i-saw-a-comfasterxmljacksondatabindjsonmappingexception-during-deserialization-process-can-you-fix-it)
[Q: There were too many quotes appeared in the redis-cli console output, how do I fix it?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-there-were-too-many-quotes-appeared-in-the-redis-cli-console-output-how-do-i-fix-it)
[Q: When do I need to shut down a Redisson instance, at the end of each request or the end of the life of a thread?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-when-do-i-need-to-shut-down-a-redisson-instance-at-the-end-of-each-request-or-the-end-of-the-life-of-a-thread)
[Q: In MapCache/SetCache/SpringCache/JCache, I have set an expiry time to an entry, why is it still there when it should be disappeared?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-in-mapcachesetcachespringcachejcache-i-have-set-an-expiry-time-to-an-entry-why-is-it-still-there-when-it-should-be-disappeared)
[Q: How can I perform Pipelining/Transaction through Redisson?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-how-can-i-perform-pipeliningtransaction-through-redisson)
[Q: Is Redisson thread safe? Can I share an instance of it between different threads?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-is-redisson-thread-safe-can-i-share-an-instance-of-it-between-different-threads)
[Q: Can I use different encoder/decoders for different tasks?](https://github.com/redisson/redisson/wiki/16.-FAQ#q-can-i-use-different-encoderdecoders-for-different-tasks)
Downloads
===============================
[Redisson 3.6.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=3.6.3&e=jar),
[Redisson node 3.6.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.6.3&e=jar)
[Redisson 3.6.4](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=3.6.4&e=jar),
[Redisson node 3.6.4](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.6.4&e=jar)
[Redisson 2.11.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=2.11.3&e=jar),
[Redisson node 2.11.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.11.3&e=jar)
[Redisson 2.11.4](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=2.11.4&e=jar),
[Redisson node 2.11.4](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.11.4&e=jar)
### Supported by

@ -485,15 +485,25 @@ public class RedissonKeys implements RKeys {
}
@Override
public void migrate(String name, String host, int port, int database) {
commandExecutor.get(migrateAsync(name, host, port, database));
public void migrate(String name, String host, int port, int database, long timeout) {
commandExecutor.get(migrateAsync(name, host, port, database, timeout));
}
@Override
public RFuture<Void> migrateAsync(String name, String host, int port, int database) {
return commandExecutor.writeAsync(name, RedisCommands.MIGRATE, host, port, name, database);
public RFuture<Void> migrateAsync(String name, String host, int port, int database, long timeout) {
return commandExecutor.writeAsync(name, RedisCommands.MIGRATE, host, port, name, database, timeout);
}
@Override
public void copy(String name, String host, int port, int database, long timeout) {
commandExecutor.get(copyAsync(name, host, port, database, timeout));
}
@Override
public RFuture<Void> copyAsync(String name, String host, int port, int database, long timeout) {
return commandExecutor.writeAsync(name, RedisCommands.MIGRATE, host, port, name, database, timeout, "COPY");
}
@Override
public boolean move(String name, int database) {
return commandExecutor.get(moveAsync(name, database));

@ -189,6 +189,30 @@ public class RedissonListMultimap<K, V> extends RedissonMultimap<K, V> implement
return new RedissonList<V>(codec, commandExecutor, setName, null) {
@Override
public RFuture<Boolean> addAsync(V value) {
return RedissonListMultimap.this.putAsync(key, value);
}
@Override
public RFuture<Boolean> addAllAsync(Collection<? extends V> c) {
return RedissonListMultimap.this.putAllAsync(key, c);
}
@Override
public RFuture<Boolean> removeAsync(Object value) {
return RedissonListMultimap.this.removeAsync(key, value);
}
@Override
public RFuture<Boolean> removeAllAsync(Collection<?> c) {
ByteBuf keyState = encodeMapKey(key);
return commandExecutor.evalWriteAsync(RedissonListMultimap.this.getName(), codec, RedisCommands.EVAL_BOOLEAN,
"redis.call('hdel', KEYS[1], ARGV[1]); " +
"return redis.call('del', KEYS[2]) > 0; ",
Arrays.<Object>asList(RedissonListMultimap.this.getName(), setName), keyState);
}
@Override
public RFuture<Boolean> deleteAsync() {
ByteBuf keyState = encodeMapKey(key);

@ -94,15 +94,25 @@ public abstract class RedissonObject implements RObject {
}
@Override
public void migrate(String host, int port, int database) {
get(migrateAsync(host, port, database));
public void migrate(String host, int port, int database, long timeout) {
get(migrateAsync(host, port, database, timeout));
}
@Override
public RFuture<Void> migrateAsync(String host, int port, int database) {
return commandExecutor.writeAsync(getName(), RedisCommands.MIGRATE, host, port, getName(), database);
public RFuture<Void> migrateAsync(String host, int port, int database, long timeout) {
return commandExecutor.writeAsync(getName(), RedisCommands.MIGRATE, host, port, getName(), database, timeout);
}
@Override
public void copy(String host, int port, int database, long timeout) {
get(copyAsync(host, port, database, timeout));
}
@Override
public RFuture<Void> copyAsync(String host, int port, int database, long timeout) {
return commandExecutor.writeAsync(getName(), RedisCommands.MIGRATE, host, port, getName(), database, timeout, "COPY");
}
@Override
public boolean move(int database) {
return get(moveAsync(database));

@ -92,7 +92,7 @@ public class RedissonRemoteService extends BaseRemoteService implements RRemoteS
protected RFuture<Boolean> removeAsync(String requestQueueName, RequestId taskId) {
return commandExecutor.evalWriteAsync(name, LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('lrem', KEYS[1], 1, ARGV[1]); "
+ "redis.call('hset', KEYS[2], ARGV[1]);"
+ "redis.call('hdel', KEYS[2], ARGV[1]);"
+ "return 1;",
Arrays.<Object>asList(requestQueueName, requestQueueName + ":tasks"),
taskId.toString());

@ -53,7 +53,7 @@ public class RedissonSet<V> extends RedissonExpirable implements RSet<V>, ScanIt
RedissonClient redisson;
protected RedissonSet(CommandAsyncExecutor commandExecutor, String name, RedissonClient redisson) {
public RedissonSet(CommandAsyncExecutor commandExecutor, String name, RedissonClient redisson) {
super(commandExecutor, name);
this.redisson = redisson;
}

@ -25,6 +25,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.redisson.api.RFuture;
import org.redisson.api.RLock;
import org.redisson.api.RSetCache;
import org.redisson.api.RedissonClient;
import org.redisson.api.mapreduce.RCollectionMapReduce;
@ -37,6 +38,7 @@ import org.redisson.client.protocol.decoder.ScanObjectEntry;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.eviction.EvictionScheduler;
import org.redisson.mapreduce.RedissonCollectionMapReduce;
import org.redisson.misc.Hash;
import org.redisson.misc.RedissonPromise;
import io.netty.buffer.ByteBuf;
@ -351,4 +353,19 @@ public class RedissonSetCache<V> extends RedissonExpirable implements RSetCache<
delete();
}
private String getLockName(Object value) {
ByteBuf state = encode(value);
try {
return suffixName(getName(value), Hash.hash128toBase64(state) + ":lock");
} finally {
state.release();
}
}
@Override
public RLock getLock(V value) {
String lockName = getLockName(value);
return new RedissonLock(commandExecutor, lockName);
}
}

@ -167,6 +167,30 @@ public class RedissonSetMultimap<K, V> extends RedissonMultimap<K, V> implements
return new RedissonSet<V>(codec, commandExecutor, setName, null) {
@Override
public RFuture<Boolean> addAsync(V value) {
return RedissonSetMultimap.this.putAsync(key, value);
}
@Override
public RFuture<Boolean> addAllAsync(Collection<? extends V> c) {
return RedissonSetMultimap.this.putAllAsync(key, c);
}
@Override
public RFuture<Boolean> removeAsync(Object value) {
return RedissonSetMultimap.this.removeAsync(key, value);
}
@Override
public RFuture<Boolean> removeAllAsync(Collection<?> c) {
ByteBuf keyState = encodeMapKey(key);
return commandExecutor.evalWriteAsync(RedissonSetMultimap.this.getName(), codec, RedisCommands.EVAL_BOOLEAN_AMOUNT,
"redis.call('hdel', KEYS[1], ARGV[1]); " +
"return redis.call('del', KEYS[2]); ",
Arrays.<Object>asList(RedissonSetMultimap.this.getName(), setName), keyState);
}
@Override
public RFuture<Boolean> deleteAsync() {
ByteBuf keyState = encodeMapKey(key);

@ -21,7 +21,7 @@ import org.redisson.api.map.MapLoader;
import org.redisson.api.map.MapWriter;
/**
* RLocalCachedMap options object. Used to specify RLocalCachedMap settings.
* Configuration for LocalCachedMap object.
*
* @author Nikita Koksharov
*

@ -19,7 +19,7 @@ import org.redisson.api.map.MapLoader;
import org.redisson.api.map.MapWriter;
/**
* RMap options object.
* Configuration for Map object.
*
* @author Nikita Koksharov
*

@ -35,14 +35,26 @@ public interface RKeys extends RKeysAsync {
boolean move(String name, int database);
/**
* Transfer an object from source Redis instance to destination Redis instance
* Transfer object from source Redis instance to destination Redis instance
*
* @param name of object
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
*/
void migrate(String name, String host, int port, int database);
void migrate(String name, String host, int port, int database, long timeout);
/**
* Copy object from source Redis instance to destination Redis instance
*
* @param name of object
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
*/
void copy(String name, String host, int port, int database, long timeout);
/**
* Set a timeout for object. After the timeout has expired,

@ -35,15 +35,29 @@ public interface RKeysAsync {
RFuture<Boolean> moveAsync(String name, int database);
/**
* Transfer an object from source Redis instance to destination Redis instance
* Transfer object from source Redis instance to destination Redis instance
*
* @param name of object
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
* @return void
*/
RFuture<Void> migrateAsync(String name, String host, int port, int database);
RFuture<Void> migrateAsync(String name, String host, int port, int database, long timeout);
/**
* Copy object from source Redis instance to destination Redis instance
* in async mode
*
* @param name of object
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
* @return void
*/
RFuture<Void> copyAsync(String name, String host, int port, int database, long timeout);
/**
* Set a timeout for object. After the timeout has expired,

@ -33,14 +33,25 @@ public interface RObject extends RObjectAsync {
boolean touch();
/**
* Transfer an object from source Redis instance to destination Redis instance
* Copy object from source Redis instance to destination Redis instance
*
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
*/
void migrate(String host, int port, int database);
void migrate(String host, int port, int database, long timeout);
/**
* Copy object from source Redis instance to destination Redis instance
*
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
*/
void copy(String host, int port, int database, long timeout);
/**
* Move object to another database
*

@ -31,16 +31,29 @@ public interface RObjectAsync {
RFuture<Boolean> touchAsync();
/**
* Transfer an object from source Redis instance to destination Redis instance
* Transfer object from source Redis instance to destination Redis instance
* in async mode
*
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
* @return void
*/
RFuture<Void> migrateAsync(String host, int port, int database);
RFuture<Void> migrateAsync(String host, int port, int database, long timeout);
/**
* Copy object from source Redis instance to destination Redis instance
* in async mode
*
* @param host - destination host
* @param port - destination port
* @param database - destination database
* @param timeout - maximum idle time in any moment of the communication with the destination instance in milliseconds
* @return void
*/
RFuture<Void> copyAsync(String host, int port, int database, long timeout);
/**
* Move object to another database in async mode
*

@ -40,6 +40,14 @@ import org.redisson.api.mapreduce.RCollectionMapReduce;
*/
public interface RSetCache<V> extends Set<V>, RExpirable, RSetCacheAsync<V> {
/**
* Returns lock instance associated with <code>value</code>
*
* @param value - set value
* @return lock
*/
RLock getLock(V value);
/**
* Returns values iterator matches <code>pattern</code>.
*

@ -98,6 +98,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
}
} catch (Exception e) {
log.error("Unable to decode data. channel: {} message: {}", ctx.channel(), in.toString(0, in.writerIndex(), CharsetUtil.UTF_8), e);
sendNext(ctx);
throw e;
}
} else if (data instanceof CommandData) {
@ -111,6 +112,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
} catch (Exception e) {
log.error("Unable to decode data. channel: {} message: {}", ctx.channel(), in.toString(0, in.writerIndex(), CharsetUtil.UTF_8), e);
cmd.tryFailure(e);
sendNext(ctx);
throw e;
}
} else if (data instanceof CommandsData) {
@ -119,13 +121,17 @@ public class CommandDecoder extends ReplayingDecoder<State> {
decodeCommandBatch(ctx, in, data, commands);
} catch (Exception e) {
commands.getPromise().tryFailure(e);
sendNext(ctx);
throw e;
}
return;
}
ctx.pipeline().get(CommandsQueue.class).sendNextCommand(ctx.channel());
sendNext(ctx);
}
protected void sendNext(ChannelHandlerContext ctx) {
ctx.pipeline().get(CommandsQueue.class).sendNextCommand(ctx.channel());
state(null);
}
@ -242,9 +248,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
}
}
ctx.pipeline().get(CommandsQueue.class).sendNextCommand(ctx.channel());
state(null);
sendNext(ctx);
} else {
checkpoint();
state().setBatchIndex(i);

@ -347,7 +347,9 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
private void checkClusterState(final ClusterServersConfig cfg, final Iterator<URI> iterator, final AtomicReference<Throwable> lastException) {
if (!iterator.hasNext()) {
log.error("Can't update cluster state", lastException.get());
if (lastException.get() != null) {
log.error("Can't update cluster state", lastException.get());
}
scheduleClusterChangeCheck(cfg, null);
return;
}

@ -235,16 +235,13 @@ public class CommandBatchService extends CommandAsyncService {
List<Object> responses = new ArrayList<Object>(entries.size());
int syncedSlaves = 0;
for (BatchCommandData<?, ?> commandEntry : entries) {
if (!isWaitCommand(commandEntry)
&& !commandEntry.getCommand().getName().equals(RedisCommands.MULTI.getName())
if (isWaitCommand(commandEntry)) {
syncedSlaves = (Integer) commandEntry.getPromise().getNow();
} else if (!commandEntry.getCommand().getName().equals(RedisCommands.MULTI.getName())
&& !commandEntry.getCommand().getName().equals(RedisCommands.EXEC.getName())) {
Object entryResult = commandEntry.getPromise().getNow();
entryResult = tryHandleReference(entryResult);
responses.add(entryResult);
} else {
if (isWaitCommand(commandEntry)) {
syncedSlaves = (Integer) commandEntry.getPromise().getNow();
}
}
}

@ -604,9 +604,11 @@ public class Config {
* Switch to round robin {@link io.netty.resolver.dns.RoundRobinDnsAddressResolverGroup} when you need to optimize the url resolving.
*
* @param addressResolverGroupFactory
* @return config
*/
public void setAddressResolverGroupFactory(AddressResolverGroupFactory addressResolverGroupFactory) {
public Config setAddressResolverGroupFactory(AddressResolverGroupFactory addressResolverGroupFactory) {
this.addressResolverGroupFactory = addressResolverGroupFactory;
return this;
}
public AddressResolverGroupFactory getAddressResolverGroupFactory() {
return addressResolverGroupFactory;

@ -418,7 +418,7 @@ public class MasterSlaveEntry {
* Shutdown old master client.
*
* @param address of Redis
* @return
* @return client
*/
public RFuture<RedisClient> changeMaster(URI address) {
final ClientConnectionsEntry oldMaster = masterEntry;

@ -248,7 +248,9 @@ public class SentinelConnectionManager extends MasterSlaveConnectionManager {
private void checkState(final SentinelServersConfig cfg, final Iterator<RedisClient> iterator, final AtomicReference<Throwable> lastException) {
if (!iterator.hasNext()) {
log.error("Can't update cluster state", lastException.get());
if (lastException.get() != null) {
log.error("Can't update cluster state", lastException.get());
}
scheduleChangeCheck(cfg, null);
return;
}

@ -2,13 +2,18 @@ package org.redisson;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
import org.junit.Test;
import org.redisson.RedisRunner.FailedToStartRedisException;
import org.redisson.RedisRunner.RedisProcess;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
public class RedissonBucketTest extends BaseTest {
@ -112,6 +117,54 @@ public class RedissonBucketTest extends BaseTest {
Assert.assertEquals("someValue", newBucket.get());
Assert.assertFalse(newBucket.renamenx("test2"));
}
@Test
public void testMigrate() throws FailedToStartRedisException, IOException, InterruptedException {
RedisProcess runner = new RedisRunner()
.appendonly(true)
.randomDir()
.randomPort()
.run();
RBucket<String> bucket = redisson.getBucket("test");
bucket.set("someValue");
bucket.migrate(runner.getRedisServerBindAddress(), runner.getRedisServerPort(), 0, 5000);
Config config = new Config();
config.useSingleServer().setAddress(runner.getRedisServerAddressAndPort());
RedissonClient r = Redisson.create(config);
RBucket<String> bucket2 = r.getBucket("test");
assertThat(bucket2.get()).isEqualTo("someValue");
assertThat(bucket.isExists()).isFalse();
runner.stop();
}
@Test
public void testCopy() throws FailedToStartRedisException, IOException, InterruptedException {
RedisProcess runner = new RedisRunner()
.appendonly(true)
.randomDir()
.randomPort()
.run();
RBucket<String> bucket = redisson.getBucket("test");
bucket.set("someValue");
bucket.copy(runner.getRedisServerBindAddress(), runner.getRedisServerPort(), 0, 5000);
Config config = new Config();
config.useSingleServer().setAddress(runner.getRedisServerAddressAndPort());
RedissonClient r = Redisson.create(config);
RBucket<String> bucket2 = r.getBucket("test");
assertThat(bucket2.get()).isEqualTo("someValue");
assertThat(bucket.get()).isEqualTo("someValue");
runner.stop();
}
@Test
public void testRename() {

@ -117,6 +117,91 @@ public class RedissonSetMultimapTest extends BaseTest {
}
@Test
public void testGetAdd() {
RSetMultimap<String, Integer> multimap1 = redisson.getSetMultimap("myMultimap1");
Set<Integer> one = multimap1.get("1");
Set<Integer> two = multimap1.get("2");
Set<Integer> four = multimap1.get("4");
one.add(1);
one.add(2);
one.add(3);
two.add(5);
two.add(6);
four.add(7);
assertThat(multimap1.keySet()).containsOnly("1", "2", "4");
assertThat(multimap1.keySize()).isEqualTo(3);
assertThat(multimap1.get("1")).containsOnly(1, 2, 3);
assertThat(multimap1.get("2")).containsOnly(5, 6);
assertThat(multimap1.get("4")).containsOnly(7);
}
@Test
public void testGetAddAll() {
RSetMultimap<String, Integer> multimap1 = redisson.getSetMultimap("myMultimap1");
Set<Integer> one = multimap1.get("1");
Set<Integer> two = multimap1.get("2");
Set<Integer> four = multimap1.get("4");
one.addAll(Arrays.asList(1, 2, 3));
two.addAll(Arrays.asList(5, 6));
four.addAll(Arrays.asList(7));
assertThat(multimap1.keySet()).containsOnly("1", "2", "4");
assertThat(multimap1.keySize()).isEqualTo(3);
assertThat(multimap1.get("1")).containsOnly(1, 2, 3);
assertThat(multimap1.get("2")).containsOnly(5, 6);
assertThat(multimap1.get("4")).containsOnly(7);
}
@Test
public void testGetRemove() {
RSetMultimap<String, Integer> multimap1 = redisson.getSetMultimap("myMultimap1");
Set<Integer> one = multimap1.get("1");
Set<Integer> two = multimap1.get("2");
Set<Integer> four = multimap1.get("4");
one.add(1);
one.add(2);
one.add(3);
two.add(5);
two.add(6);
four.add(7);
assertThat(one.remove(1)).isTrue();
assertThat(one.remove(2)).isTrue();
assertThat(two.remove(5)).isTrue();
assertThat(four.remove(7)).isTrue();
assertThat(multimap1.keySet()).containsOnly("1", "2");
assertThat(multimap1.keySize()).isEqualTo(2);
assertThat(multimap1.get("1")).containsOnly(3);
assertThat(multimap1.get("2")).containsOnly(6);
}
@Test
public void testGetRemoveAll() {
RSetMultimap<String, Integer> multimap1 = redisson.getSetMultimap("myMultimap1");
Set<Integer> one = multimap1.get("1");
Set<Integer> two = multimap1.get("2");
Set<Integer> four = multimap1.get("4");
one.add(1);
one.add(2);
one.add(3);
two.add(5);
two.add(6);
four.add(7);
assertThat(one.removeAll(Arrays.asList(1, 2, 3))).isTrue();
assertThat(two.removeAll(Arrays.asList(5, 6))).isTrue();
assertThat(four.removeAll(Arrays.asList(7))).isTrue();
assertThat(four.removeAll(Arrays.asList(9))).isFalse();
assertThat(multimap1.keySet()).isEmpty();
assertThat(multimap1.keySize()).isEqualTo(0);
}
@Test
public void testSize() {
RSetMultimap<SimpleKey, SimpleValue> map = redisson.getSetMultimap("test1");

@ -1,7 +1,7 @@
package org.redisson;
import static org.awaitility.Awaitility.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.redisson.BaseTest.createInstance;
import java.io.IOException;
@ -31,31 +31,44 @@ import org.redisson.RedisRunner.RedisProcess;
import org.redisson.api.ClusterNode;
import org.redisson.api.Node;
import org.redisson.api.Node.InfoSection;
import org.redisson.api.listener.MessageListener;
import org.redisson.api.listener.StatusListener;
import org.redisson.api.NodesGroup;
import org.redisson.api.RFuture;
import org.redisson.api.RMap;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisConnectionException;
import org.redisson.client.RedisOutOfMemoryException;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.decoder.ListScanResult;
import org.redisson.client.protocol.decoder.ScanObjectEntry;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.codec.SerializationCodec;
import org.redisson.config.Config;
import org.redisson.connection.ConnectionListener;
import org.redisson.connection.balancer.RandomLoadBalancer;
import org.redisson.misc.HashValue;
import io.netty.buffer.Unpooled;
public class RedissonTest {
protected RedissonClient redisson;
protected static RedissonClient defaultRedisson;
@Test
public void testDecoderError() {
redisson.getBucket("testbucket", new StringCodec()).set("{INVALID JSON!}");
for (int i = 0; i < 256; i++) {
try {
redisson.getBucket("testbucket", new JsonJacksonCodec()).get();
Assert.fail();
} catch (Exception e) {
// skip
}
}
redisson.getBucket("testbucket2").set("should work");
}
@Test
public void testSmallPool() throws InterruptedException {
Config config = new Config();

Loading…
Cancel
Save