Modify List to Map of pooled redis message in FixedRedisMessagePool (#11300)
Motivation: To simplify retrieving pooled message messages, add enums that can be used as key. Modifications: - Modify pooled collections from List to Map in FixedRedisMessagePool - Allow to use enum as the key to easy get pooled message. - Add unit tests Result: Users can get pooled message by enum instead of the whole string Co-authored-by: Norman Maurer <norman_maurer@apple.com>
This commit is contained in:
parent
625a7a1075
commit
e12ae47666
@ -31,33 +31,42 @@ import java.util.Map;
|
||||
@UnstableApi
|
||||
public final class FixedRedisMessagePool implements RedisMessagePool {
|
||||
|
||||
private static final String[] DEFAULT_SIMPLE_STRINGS = {
|
||||
"OK",
|
||||
"PONG",
|
||||
"QUEUED",
|
||||
};
|
||||
public enum RedisReplyKey {
|
||||
OK, PONG, QUEUED
|
||||
}
|
||||
|
||||
private static final String[] DEFAULT_ERRORS = {
|
||||
"ERR",
|
||||
"ERR index out of range",
|
||||
"ERR no such key",
|
||||
"ERR source and destination objects are the same",
|
||||
"ERR syntax error",
|
||||
"BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.",
|
||||
"BUSYKEY Target key name already exists.",
|
||||
"EXECABORT Transaction discarded because of previous errors.",
|
||||
"LOADING Redis is loading the dataset in memory",
|
||||
"MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'.",
|
||||
"MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. " +
|
||||
public enum RedisErrorKey {
|
||||
ERR("ERR"),
|
||||
ERR_IDX("ERR index out of range"),
|
||||
ERR_NOKEY("ERR no such key"),
|
||||
ERR_SAMEOBJ("ERR source and destination objects are the same"),
|
||||
ERR_SYNTAX("ERR syntax error"),
|
||||
BUSY("BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE."),
|
||||
BUSYKEY("BUSYKEY Target key name already exists."),
|
||||
EXECABORT("EXECABORT Transaction discarded because of previous errors."),
|
||||
LOADING("LOADING Redis is loading the dataset in memory"),
|
||||
MASTERDOWN("MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'."),
|
||||
MISCONF("MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. " +
|
||||
"Commands that may modify the data set are disabled. Please check Redis logs for details " +
|
||||
"about the error.",
|
||||
"NOAUTH Authentication required.",
|
||||
"NOREPLICAS Not enough good slaves to write.",
|
||||
"NOSCRIPT No matching script. Please use EVAL.",
|
||||
"OOM command not allowed when used memory > 'maxmemory'.",
|
||||
"READONLY You can't write against a read only slave.",
|
||||
"WRONGTYPE Operation against a key holding the wrong kind of value",
|
||||
};
|
||||
"about the error."),
|
||||
NOREPLICAS("NOREPLICAS Not enough good slaves to write."),
|
||||
NOSCRIPT("NOSCRIPT No matching script. Please use EVAL."),
|
||||
OOM("OOM command not allowed when used memory > 'maxmemory'."),
|
||||
READONLY("READONLY You can't write against a read only slave."),
|
||||
WRONGTYPE("WRONGTYPE Operation against a key holding the wrong kind of value"),
|
||||
NOT_AUTH("NOAUTH Authentication required.");
|
||||
|
||||
private String msg;
|
||||
|
||||
RedisErrorKey(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
private static final long MIN_CACHED_INTEGER_NUMBER = RedisConstants.NULL_VALUE; // inclusive
|
||||
private static final long MAX_CACHED_INTEGER_NUMBER = 128; // exclusive
|
||||
@ -73,8 +82,10 @@ public final class FixedRedisMessagePool implements RedisMessagePool {
|
||||
// internal caches.
|
||||
private final Map<ByteBuf, SimpleStringRedisMessage> byteBufToSimpleStrings;
|
||||
private final Map<String, SimpleStringRedisMessage> stringToSimpleStrings;
|
||||
private final Map<RedisReplyKey, SimpleStringRedisMessage> keyToSimpleStrings;
|
||||
private final Map<ByteBuf, ErrorRedisMessage> byteBufToErrors;
|
||||
private final Map<String, ErrorRedisMessage> stringToErrors;
|
||||
private final Map<RedisErrorKey, ErrorRedisMessage> keyToErrors;
|
||||
private final Map<ByteBuf, IntegerRedisMessage> byteBufToIntegers;
|
||||
private final LongObjectMap<IntegerRedisMessage> longToIntegers;
|
||||
private final LongObjectMap<byte[]> longToByteBufs;
|
||||
@ -83,24 +94,30 @@ public final class FixedRedisMessagePool implements RedisMessagePool {
|
||||
* Creates a {@link FixedRedisMessagePool} instance.
|
||||
*/
|
||||
private FixedRedisMessagePool() {
|
||||
byteBufToSimpleStrings = new HashMap<ByteBuf, SimpleStringRedisMessage>(DEFAULT_SIMPLE_STRINGS.length, 1.0f);
|
||||
stringToSimpleStrings = new HashMap<String, SimpleStringRedisMessage>(DEFAULT_SIMPLE_STRINGS.length, 1.0f);
|
||||
for (String message : DEFAULT_SIMPLE_STRINGS) {
|
||||
ByteBuf key = Unpooled.unmodifiableBuffer(
|
||||
Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(message.getBytes(CharsetUtil.UTF_8))));
|
||||
SimpleStringRedisMessage cached = new SimpleStringRedisMessage(message);
|
||||
byteBufToSimpleStrings.put(key, cached);
|
||||
stringToSimpleStrings.put(message, cached);
|
||||
keyToSimpleStrings = new HashMap<RedisReplyKey, SimpleStringRedisMessage>(RedisReplyKey.values().length, 1.0f);
|
||||
stringToSimpleStrings = new HashMap<String, SimpleStringRedisMessage>(RedisReplyKey.values().length, 1.0f);
|
||||
byteBufToSimpleStrings = new HashMap<ByteBuf, SimpleStringRedisMessage>(RedisReplyKey.values().length, 1.0f);
|
||||
for (RedisReplyKey value : RedisReplyKey.values()) {
|
||||
ByteBuf key = Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(
|
||||
value.name().getBytes(CharsetUtil.UTF_8))).asReadOnly();
|
||||
SimpleStringRedisMessage message = new SimpleStringRedisMessage(new String(Unpooled.unreleasableBuffer(
|
||||
Unpooled.wrappedBuffer(value.name().getBytes(CharsetUtil.UTF_8))).array()));
|
||||
stringToSimpleStrings.put(value.name(), message);
|
||||
keyToSimpleStrings.put(value, message);
|
||||
byteBufToSimpleStrings.put(key, message);
|
||||
}
|
||||
|
||||
byteBufToErrors = new HashMap<ByteBuf, ErrorRedisMessage>(DEFAULT_ERRORS.length, 1.0f);
|
||||
stringToErrors = new HashMap<String, ErrorRedisMessage>(DEFAULT_ERRORS.length, 1.0f);
|
||||
for (String message : DEFAULT_ERRORS) {
|
||||
ByteBuf key = Unpooled.unmodifiableBuffer(
|
||||
Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(message.getBytes(CharsetUtil.UTF_8))));
|
||||
ErrorRedisMessage cached = new ErrorRedisMessage(message);
|
||||
byteBufToErrors.put(key, cached);
|
||||
stringToErrors.put(message, cached);
|
||||
keyToErrors = new HashMap<RedisErrorKey, ErrorRedisMessage>(RedisErrorKey.values().length, 1.0f);
|
||||
stringToErrors = new HashMap<String, ErrorRedisMessage>(RedisErrorKey.values().length, 1.0f);
|
||||
byteBufToErrors = new HashMap<ByteBuf, ErrorRedisMessage>(RedisErrorKey.values().length, 1.0f);
|
||||
for (RedisErrorKey value : RedisErrorKey.values()) {
|
||||
ByteBuf key = Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(
|
||||
value.toString().getBytes(CharsetUtil.UTF_8))).asReadOnly();
|
||||
ErrorRedisMessage message = new ErrorRedisMessage(new String(Unpooled.unreleasableBuffer(
|
||||
Unpooled.wrappedBuffer(value.toString().getBytes(CharsetUtil.UTF_8))).array()));
|
||||
stringToErrors.put(value.toString(), message);
|
||||
keyToErrors.put(value, message);
|
||||
byteBufToErrors.put(key, message);
|
||||
}
|
||||
|
||||
byteBufToIntegers = new HashMap<ByteBuf, IntegerRedisMessage>(SIZE_CACHED_INTEGER_NUMBER, 1.0f);
|
||||
@ -108,8 +125,7 @@ public final class FixedRedisMessagePool implements RedisMessagePool {
|
||||
longToByteBufs = new LongObjectHashMap<byte[]>(SIZE_CACHED_INTEGER_NUMBER, 1.0f);
|
||||
for (long value = MIN_CACHED_INTEGER_NUMBER; value < MAX_CACHED_INTEGER_NUMBER; value++) {
|
||||
byte[] keyBytes = RedisCodecUtil.longToAsciiBytes(value);
|
||||
ByteBuf keyByteBuf = Unpooled.unmodifiableBuffer(Unpooled.unreleasableBuffer(
|
||||
Unpooled.wrappedBuffer(keyBytes)));
|
||||
ByteBuf keyByteBuf = Unpooled.unreleasableBuffer(Unpooled.wrappedBuffer(keyBytes)).asReadOnly();
|
||||
IntegerRedisMessage cached = new IntegerRedisMessage(value);
|
||||
byteBufToIntegers.put(keyByteBuf, cached);
|
||||
longToIntegers.put(value, cached);
|
||||
@ -122,6 +138,14 @@ public final class FixedRedisMessagePool implements RedisMessagePool {
|
||||
return stringToSimpleStrings.get(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link SimpleStringRedisMessage} for the given {@link RedisReplyKey}
|
||||
* or {@code null} if it does not exist.
|
||||
*/
|
||||
public SimpleStringRedisMessage getSimpleString(RedisReplyKey key) {
|
||||
return keyToSimpleStrings.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleStringRedisMessage getSimpleString(ByteBuf content) {
|
||||
return byteBufToSimpleStrings.get(content);
|
||||
@ -132,6 +156,14 @@ public final class FixedRedisMessagePool implements RedisMessagePool {
|
||||
return stringToErrors.get(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link ErrorRedisMessage} for the given {@link RedisErrorKey}
|
||||
* or {@code null} if it does not exist.
|
||||
*/
|
||||
public ErrorRedisMessage getError(RedisErrorKey key) {
|
||||
return keyToErrors.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorRedisMessage getError(ByteBuf content) {
|
||||
return byteBufToErrors.get(content);
|
||||
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2021 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.handler.codec.redis;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static io.netty.handler.codec.redis.RedisCodecTestUtil.byteBufOf;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Verifies the correct functionality of the {@link FixedRedisMessagePool}.
|
||||
*/
|
||||
public class FixedRedisMessagePoolTest {
|
||||
|
||||
@Test
|
||||
public void shouldGetSameMessageObject() {
|
||||
FixedRedisMessagePool pool = FixedRedisMessagePool.INSTANCE;
|
||||
|
||||
SimpleStringRedisMessage fromStr = pool.getSimpleString("OK");
|
||||
SimpleStringRedisMessage fromEnum = pool.getSimpleString(FixedRedisMessagePool.RedisReplyKey.OK);
|
||||
SimpleStringRedisMessage fromByteBuf = pool.getSimpleString(byteBufOf("OK"));
|
||||
|
||||
assertEquals(fromStr.content(), "OK");
|
||||
assertEquals(fromStr, fromEnum);
|
||||
assertEquals(fromStr, fromByteBuf);
|
||||
|
||||
ErrorRedisMessage errorFromStr = pool.getError("NOAUTH Authentication required.");
|
||||
ErrorRedisMessage errorFromEnum = pool.getError(FixedRedisMessagePool.RedisErrorKey.NOT_AUTH);
|
||||
ErrorRedisMessage errorFromByteBuf = pool.getError(byteBufOf("NOAUTH Authentication required."));
|
||||
|
||||
assertEquals(errorFromStr.content(), "NOAUTH Authentication required.");
|
||||
assertEquals(errorFromStr, errorFromEnum);
|
||||
assertEquals(errorFromStr, errorFromByteBuf);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnNullByNotExistKey() {
|
||||
FixedRedisMessagePool pool = FixedRedisMessagePool.INSTANCE;
|
||||
|
||||
SimpleStringRedisMessage message1 = pool.getSimpleString("Not exist");
|
||||
SimpleStringRedisMessage message2 = pool.getSimpleString(byteBufOf("Not exist"));
|
||||
|
||||
assertNull(message1);
|
||||
assertNull(message2);
|
||||
|
||||
ErrorRedisMessage error1 = pool.getError("Not exist");
|
||||
ErrorRedisMessage error2 = pool.getError(byteBufOf("Not exist"));
|
||||
|
||||
assertNull(error1);
|
||||
assertNull(error2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnDifferentMessage() {
|
||||
FixedRedisMessagePool pool = FixedRedisMessagePool.INSTANCE;
|
||||
|
||||
SimpleStringRedisMessage okMessage = pool.getSimpleString(FixedRedisMessagePool.RedisReplyKey.OK);
|
||||
SimpleStringRedisMessage pongMessage = pool.getSimpleString(FixedRedisMessagePool.RedisReplyKey.PONG);
|
||||
|
||||
assertNotEquals(okMessage, pongMessage);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user