Polishing.

Make fields final where possible. Reintroduce end of line comment markers to avoid reformatting into unreadable format. Replace HashSet per command instance with String to reduce memory footprint.

Tweak Javadoc wording to represent what we actually expect. Reorder methods.

See #2640
Original pull request: #2644
This commit is contained in:
Mark Paluch
2023-07-18 09:51:12 +02:00
parent ce8b857a2e
commit 377ee1804f
2 changed files with 212 additions and 207 deletions

View File

@@ -15,17 +15,18 @@
*/
package org.springframework.data.redis.core;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* {@link Enum Enumeration} of {@literal Redis commands}.
* {@link Enum Enumeration} of well-known {@literal Redis commands}. This enumeration serves as non-exhaustive set of
* built-in commands for a typical Redis server.
*
* @author Christoph Strobl
* @author Thomas Darimont
@@ -35,185 +36,187 @@ import org.springframework.util.StringUtils;
* @author Sébastien Volle
* @author John Blum
* @since 1.3
* @link <a href="https://github.com/antirez/redis/blob/843de8b786562d8d77c78d83a971060adc61f77a/src/server.c#L180">Redis command list</a>
* @link <a href=
* "https://github.com/antirez/redis/blob/843de8b786562d8d77c78d83a971060adc61f77a/src/server.c#L180">Redis
* command list</a>
*/
public enum RedisCommand {
// -- A
APPEND("rw", 2, 2),
AUTH("rw", 1, 1),
APPEND("rw", 2, 2), //
AUTH("rw", 1, 1), //
// -- B
BGREWRITEAOF("r", 0, 0, "bgwriteaof"),
BGSAVE("r", 0, 0),
BITCOUNT("r", 1, 3),
BITOP("rw", 3),
BITPOS("r", 2, 4),
BLPOP("rw", 2),
BRPOP("rw", 2),
BRPOPLPUSH("rw", 3),
BGREWRITEAOF("r", 0, 0, "bgwriteaof"), //
BGSAVE("r", 0, 0), //
BITCOUNT("r", 1, 3), //
BITOP("rw", 3), //
BITPOS("r", 2, 4), //
BLPOP("rw", 2), //
BRPOP("rw", 2), //
BRPOPLPUSH("rw", 3), //
// -- C
CLIENT_KILL("rw", 1, 1),
CLIENT_LIST("r", 0, 0),
CLIENT_GETNAME("r", 0, 0),
CLIENT_PAUSE("rw", 1, 1),
CLIENT_SETNAME("w", 1, 1),
CONFIG_GET("r", 1, 1, "getconfig"),
CONFIG_REWRITE("rw", 0, 0),
CONFIG_SET("w", 2, 2, "setconfig"),
CONFIG_RESETSTAT("w", 0, 0, "resetconfigstats"),
CLIENT_KILL("rw", 1, 1), //
CLIENT_LIST("r", 0, 0), //
CLIENT_GETNAME("r", 0, 0), //
CLIENT_PAUSE("rw", 1, 1), //
CLIENT_SETNAME("w", 1, 1), //
CONFIG_GET("r", 1, 1, "getconfig"), //
CONFIG_REWRITE("rw", 0, 0), //
CONFIG_SET("w", 2, 2, "setconfig"), //
CONFIG_RESETSTAT("w", 0, 0, "resetconfigstats"), //
// -- D
DBSIZE("r", 0, 0),
DECR("w", 1, 1),
DECRBY("w", 2, 2),
DEL("rw", 1),
DISCARD("rw", 0, 0),
DUMP("r", 1, 1),
DBSIZE("r", 0, 0), //
DECR("w", 1, 1), //
DECRBY("w", 2, 2), //
DEL("rw", 1), //
DISCARD("rw", 0, 0), //
DUMP("r", 1, 1), //
// -- E
ECHO("r", 1, 1),
EVAL("rw", 2),
EVALSHA("rw", 2),
EXEC("rw", 0, 0),
EXISTS("r", 1, 1),
EXPIRE("rw", 2, 2),
EXPIREAT("rw", 2, 2),
ECHO("r", 1, 1), //
EVAL("rw", 2), //
EVALSHA("rw", 2), //
EXEC("rw", 0, 0), //
EXISTS("r", 1, 1), //
EXPIRE("rw", 2, 2), //
EXPIREAT("rw", 2, 2), //
// -- F
FLUSHALL("w", 0, 0),
FLUSHDB("w", 0, 0),
FLUSHALL("w", 0, 0), //
FLUSHDB("w", 0, 0), //
// -- G
GET("r", 1, 1),
GETBIT("r", 2, 2),
GETRANGE("r", 3, 3),
GETSET("rw", 2, 2),
GEOADD("w", 3),
GEODIST("r", 2),
GEOHASH("r", 2),
GEOPOS("r", 2),
GEORADIUS("r", 4),
GEORADIUSBYMEMBER("r", 3),
GET("r", 1, 1), //
GETBIT("r", 2, 2), //
GETRANGE("r", 3, 3), //
GETSET("rw", 2, 2), //
GEOADD("w", 3), //
GEODIST("r", 2), //
GEOHASH("r", 2), //
GEOPOS("r", 2), //
GEORADIUS("r", 4), //
GEORADIUSBYMEMBER("r", 3), //
// -- H
HDEL("rw", 2),
HEXISTS("r", 2, 2),
HGET("r", 2, 2),
HGETALL("r", 1, 1),
HINCRBY("rw", 3, 3),
HINCBYFLOAT("rw", 3, 3),
HKEYS("r", 1),
HLEN("r", 1),
HMGET("r", 2),
HMSET("w", 3),
HSET("w", 3, 3),
HSETNX("w", 3, 3),
HVALS("r", 1, 1),
HDEL("rw", 2), //
HEXISTS("r", 2, 2), //
HGET("r", 2, 2), //
HGETALL("r", 1, 1), //
HINCRBY("rw", 3, 3), //
HINCBYFLOAT("rw", 3, 3), //
HKEYS("r", 1), //
HLEN("r", 1), //
HMGET("r", 2), //
HMSET("w", 3), //
HSET("w", 3, 3), //
HSETNX("w", 3, 3), //
HVALS("r", 1, 1), //
// -- I
INCR("rw", 1),
INCRBYFLOAT("rw", 2, 2),
INFO("r", 0),
INCR("rw", 1), //
INCRBYFLOAT("rw", 2, 2), //
INFO("r", 0), //
// -- K
KEYS("r", 1),
KEYS("r", 1), //
// -- L
LASTSAVE("r", 0),
LINDEX("r", 2, 2),
LINSERT("rw", 4, 4),
LLEN("r", 1, 1),
LPOP("rw", 1, 1),
LPUSH("rw", 2),
LPUSHX("rw", 2),
LRANGE("r", 3, 3),
LREM("rw", 3, 3),
LSET("w", 3, 3),
LTRIM("w", 3, 3),
LASTSAVE("r", 0), //
LINDEX("r", 2, 2), //
LINSERT("rw", 4, 4), //
LLEN("r", 1, 1), //
LPOP("rw", 1, 1), //
LPUSH("rw", 2), //
LPUSHX("rw", 2), //
LRANGE("r", 3, 3), //
LREM("rw", 3, 3), //
LSET("w", 3, 3), //
LTRIM("w", 3, 3), //
// -- M
MGET("r", 1),
MIGRATE("rw", 0),
MONITOR("rw", 0, 0),
MOVE("rw", 2, 2),
MSET("w", 2),
MSETNX("w", 2),
MULTI("rw", 0, 0),
MGET("r", 1), //
MIGRATE("rw", 0), //
MONITOR("rw", 0, 0), //
MOVE("rw", 2, 2), //
MSET("w", 2), //
MSETNX("w", 2), //
MULTI("rw", 0, 0), //
// -- P
PERSIST("rw", 1, 1),
PEXPIRE("rw", 2, 2),
PEXPIREAT("rw", 2, 2),
PING("r", 0, 0),
PSETEX("w", 3),
PSUBSCRIBE("r", 1),
PTTL("r", 1, 1),
PERSIST("rw", 1, 1), //
PEXPIRE("rw", 2, 2), //
PEXPIREAT("rw", 2, 2), //
PING("r", 0, 0), //
PSETEX("w", 3), //
PSUBSCRIBE("r", 1), //
PTTL("r", 1, 1), //
// -- Q
QUIT("rw", 0, 0),
QUIT("rw", 0, 0), //
// -- R
RANDOMKEY("r", 0, 0),
RANDOMKEY("r", 0, 0), //
RENAME("w", 2, 2),
RENAMENX("w", 2, 2),
REPLICAOF("w", 2),
RESTORE("w", 3, 3),
RPOP("rw", 1, 1),
RPOPLPUSH("rw", 2, 2),
RPUSH("rw", 2),
RPUSHX("rw", 2, 2),
RENAME("w", 2, 2), //
RENAMENX("w", 2, 2), //
REPLICAOF("w", 2), //
RESTORE("w", 3, 3), //
RPOP("rw", 1, 1), //
RPOPLPUSH("rw", 2, 2), //
RPUSH("rw", 2), //
RPUSHX("rw", 2, 2), //
// -- S
SADD("rw", 2),
SAVE("rw", 0, 0),
SCARD("r", 1, 1),
SCRIPT_EXISTS("r", 1),
SCRIPT_FLUSH("rw", 0, 0),
SCRIPT_KILL("rw", 0, 0),
SCRIPT_LOAD("rw", 1, 1),
SDIFF("r", 1),
SDIFFSTORE("rw", 2),
SELECT("rw", 1, 1),
SET("w", 2),
SETBIT("rw", 3, 3),
SETEX("w", 3, 3),
SETNX("w", 2, 2),
SETRANGE("rw", 3, 3),
SHUTDOWN("rw", 0),
SINTER("r", 1),
SINTERSTORE("rw", 2),
SISMEMBER("r", 2),
SLAVEOF("w", 2),
SLOWLOG("rw", 1),
SMEMBERS("r", 1, 1),
SMOVE("rw", 3, 3),
SORT("rw", 1),
SPOP("rw", 1, 1),
SRANDMEMBER("r", 1, 1),
SREM("rw", 2),
STRLEN("r", 1, 1),
SUBSCRIBE("rw", 1),
SUNION("r", 1),
SUNIONSTORE("rw ", 2),
SYNC("rw", 0, 0),
SADD("rw", 2), //
SAVE("rw", 0, 0), //
SCARD("r", 1, 1), //
SCRIPT_EXISTS("r", 1), //
SCRIPT_FLUSH("rw", 0, 0), //
SCRIPT_KILL("rw", 0, 0), //
SCRIPT_LOAD("rw", 1, 1), //
SDIFF("r", 1), //
SDIFFSTORE("rw", 2), //
SELECT("rw", 1, 1), //
SET("w", 2), //
SETBIT("rw", 3, 3), //
SETEX("w", 3, 3), //
SETNX("w", 2, 2), //
SETRANGE("rw", 3, 3), //
SHUTDOWN("rw", 0), //
SINTER("r", 1), //
SINTERSTORE("rw", 2), //
SISMEMBER("r", 2), //
SLAVEOF("w", 2), //
SLOWLOG("rw", 1), //
SMEMBERS("r", 1, 1), //
SMOVE("rw", 3, 3), //
SORT("rw", 1), //
SPOP("rw", 1, 1), //
SRANDMEMBER("r", 1, 1), //
SREM("rw", 2), //
STRLEN("r", 1, 1), //
SUBSCRIBE("rw", 1), //
SUNION("r", 1), //
SUNIONSTORE("rw ", 2), //
SYNC("rw", 0, 0), //
// -- T
TIME("r", 0, 0),
TTL("r", 1, 1),
TYPE("r", 1, 1),
TIME("r", 0, 0), //
TTL("r", 1, 1), //
TYPE("r", 1, 1), //
// -- U
UNSUBSCRIBE("rw", 0),
UNWATCH("rw", 0, 0),
UNSUBSCRIBE("rw", 0), //
UNWATCH("rw", 0, 0), //
// -- W
WATCH("rw", 1),
WATCH("rw", 1), //
// -- Z
ZADD("rw", 3),
ZCARD("r", 1),
ZCOUNT("r", 3, 3),
ZINCRBY("rw", 3),
ZINTERSTORE("rw", 3),
ZRANGE("r", 3),
ZRANGEBYSCORE("r", 3),
ZRANK("r", 2, 2),
ZREM("rw", 2),
ZREMRANGEBYRANK("rw", 3, 3),
ZREMRANGEBYSCORE("rw", 3, 3),
ZREVRANGE("r", 3),
ZREVRANGEBYSCORE("r", 3),
ZREVRANK("r", 2, 2),
ZSCORE("r", 2, 2),
ZUNIONSTORE("rw", 3),
SCAN("r", 1),
SSCAN("r", 2),
HSCAN("r", 2),
ZSCAN("r", 2),
ZADD("rw", 3), //
ZCARD("r", 1), //
ZCOUNT("r", 3, 3), //
ZINCRBY("rw", 3), //
ZINTERSTORE("rw", 3), //
ZRANGE("r", 3), //
ZRANGEBYSCORE("r", 3), //
ZRANK("r", 2, 2), //
ZREM("rw", 2), //
ZREMRANGEBYRANK("rw", 3, 3), //
ZREMRANGEBYSCORE("rw", 3, 3), //
ZREVRANGE("r", 3), //
ZREVRANGEBYSCORE("r", 3), //
ZREVRANK("r", 2, 2), //
ZSCORE("r", 2, 2), //
ZUNIONSTORE("rw", 3), //
SCAN("r", 1), //
SSCAN("r", 2), //
HSCAN("r", 2), //
ZSCAN("r", 2), //
// -- UNKNOWN / DEFAULT
UNKNOWN("rw", -1);
@@ -226,33 +229,45 @@ public enum RedisCommand {
private static Map<String, RedisCommand> buildCommandLookupTable() {
RedisCommand[] commands = RedisCommand.values();
Map<String, RedisCommand> map = new HashMap<>(commands.length, 1.0f);
Map<String, RedisCommand> map = new HashMap<>(commands.length + 5, 1.0f);
for (RedisCommand command : commands) {
map.put(command.name().toLowerCase(), command);
for (String alias : command.alias) {
map.put(alias, command);
if (!ObjectUtils.isEmpty(command.alias)) {
map.put(command.alias, command);
}
}
return Collections.unmodifiableMap(map);
}
private boolean read = true;
private boolean write = true;
/**
* Returns the command represented by the given {@code key}, otherwise returns {@link #UNKNOWN} if no matching command
* could be found.
*
* @param key {@link String key} to the {@link RedisCommand} to lookup.
* @return a matching {@link RedisCommand} for the given {@code key}, otherwise {@link #UNKNOWN}.
*/
public static RedisCommand failsafeCommandLookup(String key) {
return StringUtils.hasText(key) ? commandLookup.getOrDefault(key.toLowerCase(), UNKNOWN) : UNKNOWN;
}
private final boolean read;
private final boolean write;
private final int minArgs;
private final int maxArgs;
private final Set<String> alias = new HashSet<>(1);
private final @Nullable String alias;
/**
* Creates a new {@link RedisCommand}.
*
* @param mode {@link String} containing the {@literal read, write (rw)} mode of the Redis command.
* @param minArgs {@link Integer minimum number of arguments} accepted by the Redis command.
* @param mode {@link String} containing the mode ({@literal r} for read, {@literal w} for write or {@literal rw} for
* read-write) of the Redis command.
* @param minArgs minimum number of arguments accepted by the Redis command.
*/
RedisCommand(String mode, int minArgs) {
this(mode, minArgs, -1);
@@ -261,36 +276,37 @@ public enum RedisCommand {
/**
* Creates a new {@link RedisCommand}.
*
* @param mode {@link String} containing the {@literal read, write (rw)} mode of the Redis command.
* @param minArgs {@link Integer minimum number of arguments} accepted by the Redis command.
* @param maxArgs {@link Integer maximum number of arguments} accepted by the Redis command.
* @param mode {@link String} containing the mode ({@literal r} for read, {@literal w} for write or {@literal rw} for
* read-write) of the Redis command.
* @param minArgs minimum number of arguments accepted by the Redis command.
* @param maxArgs maximum number of arguments accepted by the Redis command.
*/
RedisCommand(String mode, int minArgs, int maxArgs) {
if (StringUtils.hasText(mode)) {
this.read = mode.toLowerCase().contains("r");
this.write = mode.toLowerCase().contains("w");
}
this.minArgs = minArgs;
this.maxArgs = maxArgs;
this(mode, minArgs, maxArgs, null);
}
/**
* Creates a new {@link RedisCommand}.
*
* @param mode {@link String} containing the {@literal read, write (rw)} mode of the Redis command.
* @param minArgs {@link Integer minimum number of arguments} accepted by the Redis command.
* @param maxArgs {@link Integer maximum number of arguments} accepted by the Redis command.
* @param alias array of {@link String alternate command names} used as {@literal aliases} for the Redis command.
* @param mode {@link String} containing the mode ({@literal r} for read, {@literal w} for write or {@literal rw} for
* read-write) of the Redis command.
* @param minArgs minimum number of arguments accepted by the Redis command.
* @param maxArgs maximum number of arguments accepted by the Redis command.
* @param alias alternate command name used as alias for the Redis command, can be {@literal null}.
*/
RedisCommand(String mode, int minArgs, int maxArgs, String... alias) {
RedisCommand(String mode, int minArgs, int maxArgs, @Nullable String alias) {
this(mode, minArgs, maxArgs);
if (alias.length > 0) {
this.alias.addAll(Arrays.asList(alias));
if (StringUtils.hasText(mode)) {
this.read = mode.toLowerCase().contains("r");
this.write = mode.toLowerCase().contains("w");
} else {
this.read = true;
this.write = true;
}
this.minArgs = minArgs;
this.maxArgs = maxArgs;
this.alias = alias;
}
/**
@@ -313,7 +329,7 @@ public enum RedisCommand {
* @return a {@link Set} of all {@link String aliases} for this {@link RedisCommand}.
*/
Set<String> getAliases() {
return Collections.unmodifiableSet(this.alias);
return ObjectUtils.isEmpty(this.alias) ? Collections.emptySet() : Collections.singleton(this.alias);
}
/**
@@ -347,7 +363,7 @@ public enum RedisCommand {
public boolean isRepresentedBy(String command) {
return StringUtils.hasText(command)
&& (toString().equalsIgnoreCase(command) || this.alias.contains(command.toLowerCase()));
&& (toString().equalsIgnoreCase(command) || command.toLowerCase().equals(this.alias));
}
/**
@@ -361,17 +377,16 @@ public enum RedisCommand {
if (requiresArguments()) {
if (requiresExactNumberOfArguments()) {
if (argumentCount != this.maxArgs) {
throw newIllegalArgumentException("%s command requires %d %s",
name(), this.maxArgs, arguments(this.maxArgs));
throw newIllegalArgumentException("%s command requires %d %s", name(), this.maxArgs, arguments(this.maxArgs));
}
}
if (argumentCount < this.minArgs) {
throw newIllegalArgumentException("%s command requires at least %d %s",
name(), this.minArgs, arguments(this.maxArgs));
throw newIllegalArgumentException("%s command requires at least %d %s", name(), this.minArgs,
arguments(this.maxArgs));
}
if (this.maxArgs > 0 && argumentCount > this.maxArgs) {
throw newIllegalArgumentException("%s command requires at most %s %s",
name(), this.maxArgs, arguments(this.maxArgs));
throw newIllegalArgumentException("%s command requires at most %s %s", name(), this.maxArgs,
arguments(this.maxArgs));
}
}
}
@@ -384,14 +399,4 @@ public enum RedisCommand {
return new IllegalArgumentException(String.format(message, arguments));
}
/**
* Returns the command represented by the given {@code key}, otherwise returns {@link #UNKNOWN}
* if no matching command could be found.
*
* @param key {@link String key} to the {@link RedisCommand} to lookup.
* @return a matching {@link RedisCommand} for the given {@code key}, otherwise {@link #UNKNOWN}.
*/
public static RedisCommand failsafeCommandLookup(String key) {
return StringUtils.hasText(key) ? commandLookup.getOrDefault(key.toLowerCase(), UNKNOWN) : UNKNOWN;
}
}

View File

@@ -72,13 +72,13 @@ class StreamObjectMapper {
this.mapper = (HashMapper) mapper;
if (mapper instanceof ObjectHashMapper objHashMapper) {
if (mapper instanceof ObjectHashMapper ohm) {
this.objectHashMapper = new HashMapper<>() {
@Override
public Map<Object, Object> toHash(Object object) {
return (Map) objHashMapper.toHash(object);
return (Map) ohm.toHash(object);
}
@Override
@@ -88,7 +88,7 @@ class StreamObjectMapper {
keyMapper -> conversionService.convert(keyMapper.getKey(), byte[].class),
valueMapper -> conversionService.convert(valueMapper.getValue(), byte[].class)));
return objHashMapper.fromHash(map);
return ohm.fromHash(map);
}
};
} else {