Replaying phase handling in CommandDecoder

pull/472/head
Nikita 9 years ago
parent 26f2d0a4b9
commit abca09e5b7

@ -36,6 +36,7 @@ import org.redisson.client.protocol.Decoder;
import org.redisson.client.protocol.QueueCommand; import org.redisson.client.protocol.QueueCommand;
import org.redisson.client.protocol.RedisCommand.ValueType; import org.redisson.client.protocol.RedisCommand.ValueType;
import org.redisson.client.protocol.decoder.MultiDecoder; import org.redisson.client.protocol.decoder.MultiDecoder;
import org.redisson.client.protocol.decoder.NestedMultiDecoder;
import org.redisson.client.protocol.pubsub.Message; import org.redisson.client.protocol.pubsub.Message;
import org.redisson.client.protocol.pubsub.PubSubMessage; import org.redisson.client.protocol.pubsub.PubSubMessage;
import org.redisson.client.protocol.pubsub.PubSubPatternMessage; import org.redisson.client.protocol.pubsub.PubSubPatternMessage;
@ -79,61 +80,99 @@ public class CommandDecoder extends ReplayingDecoder<State> {
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
QueueCommand data = ctx.channel().attr(CommandsQueue.CURRENT_COMMAND).get(); QueueCommand data = ctx.channel().attr(CommandsQueue.CURRENT_COMMAND).get();
Decoder<Object> currentDecoder = null; if (log.isTraceEnabled()) {
if (data == null) { log.trace("channel: {} message: {}", ctx.channel(), in.toString(0, in.writerIndex(), CharsetUtil.UTF_8));
currentDecoder = StringCodec.INSTANCE.getValueDecoder();
} }
if (state() == null) { if (state() == null) {
state(new State()); boolean makeCheckpoint = data != null;
if (data != null) {
if (log.isTraceEnabled()) { if (data instanceof CommandsData) {
log.trace("channel: {} message: {}", ctx.channel(), in.toString(0, in.writerIndex(), CharsetUtil.UTF_8)); makeCheckpoint = false;
} else {
CommandData<Object, Object> cmd = (CommandData<Object, Object>)data;
if (cmd.getCommand().getReplayMultiDecoder() != null && NestedMultiDecoder.class.isAssignableFrom(cmd.getCommand().getReplayMultiDecoder().getClass())) {
makeCheckpoint = false;
}
}
} }
state(new State(makeCheckpoint));
} }
state().setDecoderState(null); state().setDecoderState(null);
if (data == null) { if (data == null) {
decode(in, null, null, ctx.channel(), currentDecoder); decode(in, null, null, ctx.channel());
} else if (data instanceof CommandData) { } else if (data instanceof CommandData) {
CommandData<Object, Object> cmd = (CommandData<Object, Object>)data; CommandData<Object, Object> cmd = (CommandData<Object, Object>)data;
try { try {
// if (state().getSize() > 0) { if (state().getLevels().size() > 0) {
// List<Object> respParts = new ArrayList<Object>(); decodeFromCheckpoint(ctx, in, data, cmd);
// if (state().getRespParts() != null) { } else {
// respParts = state().getRespParts(); decode(in, cmd, null, ctx.channel());
// } }
// decodeMulti(in, cmd, null, ctx.channel(), currentDecoder, state().getSize(), respParts, true);
// } else {
decode(in, cmd, null, ctx.channel(), currentDecoder);
// }
} catch (IOException e) { } catch (IOException e) {
cmd.getPromise().tryFailure(e); cmd.getPromise().tryFailure(e);
} }
} else if (data instanceof CommandsData) { } else if (data instanceof CommandsData) {
CommandsData commands = (CommandsData)data; CommandsData commands = (CommandsData)data;
handleCommandsDataResponse(ctx, in, data, currentDecoder, commands); decodeCommandBatch(ctx, in, data, commands);
return; return;
} }
ctx.pipeline().get(CommandsQueue.class).sendNextCommand(ctx.channel()); ctx.pipeline().get(CommandsQueue.class).sendNextCommand(ctx.channel());
state(null); state(null);
} }
private void handleCommandsDataResponse(ChannelHandlerContext ctx, ByteBuf in, QueueCommand data, private void decodeFromCheckpoint(ChannelHandlerContext ctx, ByteBuf in, QueueCommand data,
Decoder<Object> currentDecoder, CommandsData commands) { CommandData<Object, Object> cmd) throws IOException {
int i = state().getIndex(); if (state().getLevels().size() == 2) {
StateLevel secondLevel = state().getLevels().get(1);
if (secondLevel.getParts().isEmpty()) {
state().getLevels().remove(1);
}
}
if (state().getLevels().size() == 2) {
StateLevel firstLevel = state().getLevels().get(0);
StateLevel secondLevel = state().getLevels().get(1);
decodeMulti(in, cmd, firstLevel.getParts(), ctx.channel(), secondLevel.getSize(), secondLevel.getParts());
Channel channel = ctx.channel();
MultiDecoder<Object> decoder = messageDecoder(cmd, firstLevel.getParts(), channel);
if (decoder != null) {
Object result = decoder.decode(firstLevel.getParts(), state());
if (data != null) {
handleResult(cmd, null, result, true, channel);
}
}
}
if (state().getLevels().size() == 1) {
StateLevel firstLevel = state().getLevels().get(0);
if (firstLevel.getParts().isEmpty()) {
state().resetLevel();
decode(in, cmd, null, ctx.channel());
} else {
decodeMulti(in, cmd, null, ctx.channel(), firstLevel.getSize(), firstLevel.getParts());
}
}
}
private void decodeCommandBatch(ChannelHandlerContext ctx, ByteBuf in, QueueCommand data,
CommandsData commandBatch) {
int i = state().getBatchIndex();
RedisException error = null; RedisException error = null;
while (in.writerIndex() > in.readerIndex()) { while (in.writerIndex() > in.readerIndex()) {
CommandData<Object, Object> cmd = null; CommandData<Object, Object> cmd = null;
try { try {
checkpoint(); checkpoint();
state().setIndex(i); state().setBatchIndex(i);
cmd = (CommandData<Object, Object>) commands.getCommands().get(i); cmd = (CommandData<Object, Object>) commandBatch.getCommands().get(i);
decode(in, cmd, null, ctx.channel(), currentDecoder); decode(in, cmd, null, ctx.channel());
i++; i++;
} catch (IOException e) { } catch (IOException e) {
cmd.getPromise().tryFailure(e); cmd.getPromise().tryFailure(e);
@ -147,8 +186,8 @@ public class CommandDecoder extends ReplayingDecoder<State> {
} }
} }
if (i == commands.getCommands().size()) { if (i == commandBatch.getCommands().size()) {
Promise<Void> promise = commands.getPromise(); Promise<Void> promise = commandBatch.getPromise();
if (error != null) { if (error != null) {
if (!promise.tryFailure(error) && promise.cause() instanceof RedisTimeoutException) { if (!promise.tryFailure(error) && promise.cause() instanceof RedisTimeoutException) {
log.warn("response has been skipped due to timeout! channel: {}, command: {}", ctx.channel(), data); log.warn("response has been skipped due to timeout! channel: {}, command: {}", ctx.channel(), data);
@ -164,11 +203,11 @@ public class CommandDecoder extends ReplayingDecoder<State> {
state(null); state(null);
} else { } else {
checkpoint(); checkpoint();
state().setIndex(i); state().setBatchIndex(i);
} }
} }
private void decode(ByteBuf in, CommandData<Object, Object> data, List<Object> parts, Channel channel, Decoder<Object> currentDecoder) throws IOException { private void decode(ByteBuf in, CommandData<Object, Object> data, List<Object> parts, Channel channel) throws IOException {
int code = in.readByte(); int code = in.readByte();
if (code == '+') { if (code == '+') {
String result = in.readBytes(in.bytesBefore((byte) '\r')).toString(CharsetUtil.UTF_8); String result = in.readBytes(in.bytesBefore((byte) '\r')).toString(CharsetUtil.UTF_8);
@ -212,32 +251,40 @@ public class CommandDecoder extends ReplayingDecoder<State> {
ByteBuf buf = readBytes(in); ByteBuf buf = readBytes(in);
Object result = null; Object result = null;
if (buf != null) { if (buf != null) {
result = decoder(data, parts, currentDecoder).decode(buf, state()); Decoder<Object> decoder = selectDecoder(data, parts);
result = decoder.decode(buf, state());
} }
handleResult(data, parts, result, false, channel); handleResult(data, parts, result, false, channel);
} else if (code == '*') { } else if (code == '*') {
int level = state().incLevel();
long size = readLong(in); long size = readLong(in);
List<Object> respParts = new ArrayList<Object>(); List<Object> respParts;
boolean top = false; if (state().getLevels().size()-1 >= level) {
// if (state().trySetSize(size)) { StateLevel stateLevel = state().getLevels().get(level);
// state().setRespParts(respParts); respParts = stateLevel.getParts();
// top = true; size = stateLevel.getSize();
// } } else {
respParts = new ArrayList<Object>();
decodeMulti(in, data, parts, channel, currentDecoder, size, respParts, top); if (state().isMakeCheckpoint()) {
state().addLevel(new StateLevel(size, respParts));
}
}
decodeMulti(in, data, parts, channel, size, respParts);
} else { } else {
throw new IllegalStateException("Can't decode replay " + (char)code); throw new IllegalStateException("Can't decode replay " + (char)code);
} }
} }
private void decodeMulti(ByteBuf in, CommandData<Object, Object> data, List<Object> parts, private void decodeMulti(ByteBuf in, CommandData<Object, Object> data, List<Object> parts,
Channel channel, Decoder<Object> currentDecoder, long size, List<Object> respParts, boolean top) Channel channel, long size, List<Object> respParts)
throws IOException { throws IOException {
for (int i = respParts.size(); i < size; i++) { for (int i = respParts.size(); i < size; i++) {
decode(in, data, respParts, channel, currentDecoder); decode(in, data, respParts, channel);
// if (top) { if (state().isMakeCheckpoint()) {
// checkpoint(); checkpoint();
// } }
} }
MultiDecoder<Object> decoder = messageDecoder(data, respParts, channel); MultiDecoder<Object> decoder = messageDecoder(data, respParts, channel);
@ -246,7 +293,10 @@ public class CommandDecoder extends ReplayingDecoder<State> {
} }
Object result = decoder.decode(respParts, state()); Object result = decoder.decode(respParts, state());
if (data != null) {
handleResult(data, parts, result, true, channel);
return;
}
if (result instanceof Message) { if (result instanceof Message) {
// store current message index // store current message index
@ -255,40 +305,34 @@ public class CommandDecoder extends ReplayingDecoder<State> {
handleMultiResult(data, null, channel, result); handleMultiResult(data, null, channel, result);
// has next messages? // has next messages?
if (in.writerIndex() > in.readerIndex()) { if (in.writerIndex() > in.readerIndex()) {
decode(in, data, null, channel, currentDecoder); decode(in, data, null, channel);
} }
} else {
handleMultiResult(data, parts, channel, result);
} }
} }
private void handleMultiResult(CommandData<Object, Object> data, List<Object> parts, private void handleMultiResult(CommandData<Object, Object> data, List<Object> parts,
Channel channel, Object result) { Channel channel, Object result) {
if (data != null) { if (result instanceof PubSubStatusMessage) {
handleResult(data, parts, result, true, channel); String channelName = ((PubSubStatusMessage) result).getChannel();
} else { CommandData<Object, Object> d = pubSubChannels.get(channelName);
if (result instanceof PubSubStatusMessage) { if (Arrays.asList("PSUBSCRIBE", "SUBSCRIBE").contains(d.getCommand().getName())) {
String channelName = ((PubSubStatusMessage) result).getChannel(); pubSubChannels.remove(channelName);
CommandData<Object, Object> d = pubSubChannels.get(channelName); pubSubMessageDecoders.put(channelName, d.getMessageDecoder());
if (Arrays.asList("PSUBSCRIBE", "SUBSCRIBE").contains(d.getCommand().getName())) {
pubSubChannels.remove(channelName);
pubSubMessageDecoders.put(channelName, d.getMessageDecoder());
}
if (Arrays.asList("PUNSUBSCRIBE", "UNSUBSCRIBE").contains(d.getCommand().getName())) {
pubSubChannels.remove(channelName);
pubSubMessageDecoders.remove(channelName);
}
} }
if (Arrays.asList("PUNSUBSCRIBE", "UNSUBSCRIBE").contains(d.getCommand().getName())) {
RedisPubSubConnection pubSubConnection = RedisPubSubConnection.getFrom(channel); pubSubChannels.remove(channelName);
if (result instanceof PubSubStatusMessage) { pubSubMessageDecoders.remove(channelName);
pubSubConnection.onMessage((PubSubStatusMessage) result);
} else if (result instanceof PubSubMessage) {
pubSubConnection.onMessage((PubSubMessage) result);
} else {
pubSubConnection.onMessage((PubSubPatternMessage) result);
} }
} }
RedisPubSubConnection pubSubConnection = RedisPubSubConnection.getFrom(channel);
if (result instanceof PubSubStatusMessage) {
pubSubConnection.onMessage((PubSubStatusMessage) result);
} else if (result instanceof PubSubMessage) {
pubSubConnection.onMessage((PubSubMessage) result);
} else {
pubSubConnection.onMessage((PubSubPatternMessage) result);
}
} }
private void handleResult(CommandData<Object, Object> data, List<Object> parts, Object result, boolean multiResult, Channel channel) { private void handleResult(CommandData<Object, Object> data, List<Object> parts, Object result, boolean multiResult, Channel channel) {
@ -329,7 +373,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
return data.getCommand().getReplayMultiDecoder(); return data.getCommand().getReplayMultiDecoder();
} }
private Decoder<Object> decoder(CommandData<Object, Object> data, List<Object> parts, Decoder<Object> currentDecoder) { private Decoder<Object> selectDecoder(CommandData<Object, Object> data, List<Object> parts) {
if (data == null) { if (data == null) {
if (parts.size() == 2 && parts.get(0).equals("message")) { if (parts.size() == 2 && parts.get(0).equals("message")) {
String channelName = (String) parts.get(1); String channelName = (String) parts.get(1);
@ -339,7 +383,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
String patternName = (String) parts.get(1); String patternName = (String) parts.get(1);
return pubSubMessageDecoders.get(patternName); return pubSubMessageDecoders.get(patternName);
} }
return currentDecoder; return StringCodec.INSTANCE.getValueDecoder();
} }
Decoder<Object> decoder = data.getCommand().getReplayDecoder(); Decoder<Object> decoder = data.getCommand().getReplayDecoder();

@ -15,50 +15,80 @@
*/ */
package org.redisson.client.handler; package org.redisson.client.handler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.redisson.client.protocol.decoder.DecoderState;
public class State { public class State {
private int index; private int batchIndex;
private Object decoderState; private DecoderState decoderState;
private int level = -1;
private List<StateLevel> levels;
private DecoderState decoderStateCopy;
private final boolean makeCheckpoint;
private long size; public State(boolean makeCheckpoint) {
private List<Object> respParts; this.makeCheckpoint = makeCheckpoint;
}
public State() { public boolean isMakeCheckpoint() {
super(); return makeCheckpoint;
} }
public boolean trySetSize(long size) { public void resetLevel() {
if (this.size != 0) { level = -1;
return false; }
public int decLevel() {
return --level;
}
public int incLevel() {
return ++level;
}
public void addLevel(StateLevel stateLevel) {
if (levels == null) {
levels = new ArrayList<StateLevel>(2);
} }
this.size = size; levels.add(stateLevel);
return true;
} }
public long getSize() { public List<StateLevel> getLevels() {
return size; if (levels == null) {
return Collections.emptyList();
}
return levels;
} }
public void setRespParts(List<Object> respParts) { public void setBatchIndex(int index) {
this.respParts = respParts; this.batchIndex = index;
} }
public List<Object> getRespParts() { public int getBatchIndex() {
return respParts; return batchIndex;
} }
public void setIndex(int index) { public <T extends DecoderState> T getDecoderState() {
this.index = index; return (T) decoderState;
} }
public int getIndex() { public void setDecoderState(DecoderState decoderState) {
return index; this.decoderState = decoderState;
} }
public <T> T getDecoderState() { public DecoderState getDecoderStateCopy() {
return (T)decoderState; return decoderStateCopy;
} }
public void setDecoderState(Object decoderState) { public void setDecoderStateCopy(DecoderState decoderStateCopy) {
this.decoderState = decoderState; this.decoderStateCopy = decoderStateCopy;
}
@Override
public String toString() {
return "State [batchIndex=" + batchIndex + ", decoderState=" + decoderState + ", level=" + level + ", levels="
+ levels + ", decoderStateCopy=" + decoderStateCopy + "]";
} }
} }

@ -0,0 +1,29 @@
package org.redisson.client.handler;
import java.util.List;
public class StateLevel {
private long size;
private List<Object> parts;
public StateLevel(long size, List<Object> parts) {
super();
this.size = size;
this.parts = parts;
}
public long getSize() {
return size;
}
public List<Object> getParts() {
return parts;
}
@Override
public String toString() {
return "StateLevel [size=" + size + ", parts=" + parts + "]";
}
}

@ -0,0 +1,7 @@
package org.redisson.client.protocol.decoder;
public interface DecoderState {
DecoderState copy();
}

@ -38,7 +38,7 @@ public class FlatNestedMultiDecoder<T> extends NestedMultiDecoder {
@Override @Override
public boolean isApplicable(int paramNum, State state) { public boolean isApplicable(int paramNum, State state) {
DecoderState ds = getDecoder(state); NestedDecoderState ds = getDecoder(state);
if (paramNum == 0) { if (paramNum == 0) {
ds.resetDecoderIndex(); ds.resetDecoderIndex();
} }

@ -24,13 +24,19 @@ import io.netty.buffer.ByteBuf;
public class NestedMultiDecoder<T> implements MultiDecoder<Object> { public class NestedMultiDecoder<T> implements MultiDecoder<Object> {
public static class DecoderState { public static class NestedDecoderState implements DecoderState {
int decoderIndex; int decoderIndex;
int flipDecoderIndex; int flipDecoderIndex;
public DecoderState() { public NestedDecoderState() {
}
public NestedDecoderState(int decoderIndex, int flipDecoderIndex) {
super();
this.decoderIndex = decoderIndex;
this.flipDecoderIndex = flipDecoderIndex;
} }
public int getDecoderIndex() { public int getDecoderIndex() {
@ -53,6 +59,16 @@ public class NestedMultiDecoder<T> implements MultiDecoder<Object> {
flipDecoderIndex++; flipDecoderIndex++;
} }
@Override
public DecoderState copy() {
return new NestedDecoderState(decoderIndex, flipDecoderIndex);
}
@Override
public String toString() {
return "NestedDecoderState [decoderIndex=" + decoderIndex + ", flipDecoderIndex=" + flipDecoderIndex + "]";
}
} }
protected final MultiDecoder<Object> firstDecoder; protected final MultiDecoder<Object> firstDecoder;
@ -81,7 +97,7 @@ public class NestedMultiDecoder<T> implements MultiDecoder<Object> {
@Override @Override
public Object decode(ByteBuf buf, State state) throws IOException { public Object decode(ByteBuf buf, State state) throws IOException {
DecoderState ds = getDecoder(state); NestedDecoderState ds = getDecoder(state);
MultiDecoder<?> decoder = null; MultiDecoder<?> decoder = null;
if (ds.getFlipDecoderIndex() == 2) { if (ds.getFlipDecoderIndex() == 2) {
@ -96,7 +112,7 @@ public class NestedMultiDecoder<T> implements MultiDecoder<Object> {
@Override @Override
public boolean isApplicable(int paramNum, State state) { public boolean isApplicable(int paramNum, State state) {
DecoderState ds = getDecoder(state); NestedDecoderState ds = getDecoder(state);
if (paramNum == 0) { if (paramNum == 0) {
ds.incFlipDecoderIndex(); ds.incFlipDecoderIndex();
ds.resetDecoderIndex(); ds.resetDecoderIndex();
@ -118,10 +134,10 @@ public class NestedMultiDecoder<T> implements MultiDecoder<Object> {
return decoder.isApplicable(paramNum, state); return decoder.isApplicable(paramNum, state);
} }
protected final DecoderState getDecoder(State state) { protected final NestedDecoderState getDecoder(State state) {
DecoderState ds = state.getDecoderState(); NestedDecoderState ds = state.getDecoderState();
if (ds == null) { if (ds == null) {
ds = new DecoderState(); ds = new NestedDecoderState();
state.setDecoderState(ds); state.setDecoderState(ds);
} }
return ds; return ds;
@ -137,7 +153,7 @@ public class NestedMultiDecoder<T> implements MultiDecoder<Object> {
return decoder.decode(parts, state); return decoder.decode(parts, state);
} }
DecoderState ds = getDecoder(state); NestedDecoderState ds = getDecoder(state);
if (parts.isEmpty()) { if (parts.isEmpty()) {
ds.resetDecoderIndex(); ds.resetDecoderIndex();
} }

@ -21,11 +21,11 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.redisson.client.codec.LongCodec;
import org.redisson.client.handler.State; import org.redisson.client.handler.State;
import org.redisson.client.protocol.decoder.MultiDecoder; import org.redisson.client.protocol.decoder.MultiDecoder;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
public class CacheGetAllDecoder implements MultiDecoder<List<Object>> { public class CacheGetAllDecoder implements MultiDecoder<List<Object>> {
@ -37,7 +37,7 @@ public class CacheGetAllDecoder implements MultiDecoder<List<Object>> {
@Override @Override
public Object decode(ByteBuf buf, State state) throws IOException { public Object decode(ByteBuf buf, State state) throws IOException {
return Long.valueOf(buf.toString(CharsetUtil.UTF_8)); return LongCodec.INSTANCE.getValueDecoder().decode(buf, state);
} }
@Override @Override

@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import org.junit.Test; import org.junit.Test;
import org.redisson.core.GeoEntry; import org.redisson.core.GeoEntry;
@ -103,6 +104,61 @@ public class RedissonGeoTest extends BaseTest {
expected.put("Catania", 56.4413); expected.put("Catania", 56.4413);
assertThat(geo.radiusWithDistance(15, 37, 200, GeoUnit.KILOMETERS)).isEqualTo(expected); assertThat(geo.radiusWithDistance(15, 37, 200, GeoUnit.KILOMETERS)).isEqualTo(expected);
} }
@Test
public void testRadiusWithDistanceHugeAmount() {
RGeo<String> geo = redisson.getGeo("test");
for (int i = 0; i < 10000; i++) {
geo.add(10 + 0.000001*i, 11 + 0.000001*i, "" + i);
}
Map<String, Double> res = geo.radiusWithDistance(10, 11, 200, GeoUnit.KILOMETERS);
assertThat(res).hasSize(10000);
}
@Test
public void testRadiusWithPositionHugeAmount() {
RGeo<String> geo = redisson.getGeo("test");
for (int i = 0; i < 10000; i++) {
geo.add(10 + 0.000001*i, 11 + 0.000001*i, "" + i);
}
Map<String, GeoPosition> res = geo.radiusWithPosition(10, 11, 200, GeoUnit.KILOMETERS);
assertThat(res).hasSize(10000);
}
@Test
public void testRadiusWithDistanceBigObject() {
RGeo<Map<String, String>> geo = redisson.getGeo("test");
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < 150; i++) {
map.put("" + i, "" + i);
}
geo.add(new GeoEntry(13.361389, 38.115556, map));
Map<String, String> map1 = new HashMap<String, String>(map);
map1.remove("100");
geo.add(new GeoEntry(15.087269, 37.502669, map1));
Map<String, String> map2 = new HashMap<String, String>(map);
map2.remove("0");
geo.add(new GeoEntry(15.081269, 37.502169, map2));
Map<Map<String, String>, Double> expected = new HashMap<Map<String, String>, Double>();
expected.put(map, 190.4424);
expected.put(map1, 56.4413);
expected.put(map2, 56.3159);
Map<Map<String, String>, Double> res = geo.radiusWithDistance(15, 37, 200, GeoUnit.KILOMETERS);
assertThat(res.keySet()).containsOnlyElementsOf(expected.keySet());
assertThat(res.values()).containsOnlyElementsOf(expected.values());
}
@Test @Test
public void testRadiusWithDistanceEmpty() { public void testRadiusWithDistanceEmpty() {

@ -5,8 +5,10 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -46,7 +48,20 @@ public class RedissonSetCacheTest extends BaseTest {
RSetCache<Integer> set = redisson.getSetCache("set"); RSetCache<Integer> set = redisson.getSetCache("set");
assertThat(set.readAll()).isEmpty(); assertThat(set.readAll()).isEmpty();
} }
@Test
public void testAddBigBean() {
RSetCache<Map<Integer, Integer>> set = redisson.getSetCache("simple");
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < 150; i++) {
map.put(i, i);
}
set.add(map);
map.remove(0);
set.add(map);
set.iterator().next();
}
@Test @Test
public void testAddBean() throws InterruptedException, ExecutionException { public void testAddBean() throws InterruptedException, ExecutionException {
SimpleBean sb = new SimpleBean(); SimpleBean sb = new SimpleBean();

Loading…
Cancel
Save