Polishing.

Additionally, applied Java 17 syntax, cleaned up compiler warnings, and edited Javadoc.

Closes #2644
Original pull request: #2640
This commit is contained in:
John Blum
2023-07-17 13:30:32 -07:00
committed by Mark Paluch
parent 95d5b82ac6
commit ce8b857a2e
7 changed files with 309 additions and 272 deletions

View File

@@ -25,203 +25,198 @@ import java.util.Set;
import org.springframework.util.StringUtils;
/**
* {@link Enum Enumeration} of {@literal Redis commands}.
*
* @author Christoph Strobl
* @author Thomas Darimont
* @author Ninad Divadkar
* @author Mark Paluch
* @author Oscar Cai
* @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), //
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);
private boolean read = true;
private boolean write = true;
private Set<String> alias = new HashSet<>(1);
private int minArgs = -1;
private int maxArgs = -1;
private static final Map<String, RedisCommand> commandLookup;
static {
@@ -230,30 +225,51 @@ public enum RedisCommand {
private static Map<String, RedisCommand> buildCommandLookupTable() {
RedisCommand[] cmds = RedisCommand.values();
Map<String, RedisCommand> map = new HashMap<>(cmds.length, 1.0F);
RedisCommand[] commands = RedisCommand.values();
Map<String, RedisCommand> map = new HashMap<>(commands.length, 1.0f);
for (RedisCommand cmd : cmds) {
for (RedisCommand command : commands) {
map.put(cmd.name().toLowerCase(), cmd);
map.put(command.name().toLowerCase(), command);
for (String alias : cmd.alias) {
map.put(alias, cmd);
for (String alias : command.alias) {
map.put(alias, command);
}
}
return Collections.unmodifiableMap(map);
}
private boolean read = true;
private boolean write = true;
private final int minArgs;
private final int maxArgs;
private final Set<String> alias = new HashSet<>(1);
/**
* 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.
*/
RedisCommand(String mode, int minArgs) {
this(mode, minArgs, -1);
}
/**
* 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.
*/
RedisCommand(String mode, int minArgs, int maxArgs) {
if (StringUtils.hasText(mode)) {
this.read = mode.toLowerCase().indexOf('r') > -1;
this.write = mode.toLowerCase().indexOf('w') > -1;
this.read = mode.toLowerCase().contains("r");
this.write = mode.toLowerCase().contains("w");
}
this.minArgs = minArgs;
@@ -263,10 +279,10 @@ public enum RedisCommand {
/**
* Creates a new {@link RedisCommand}.
*
* @param mode
* @param minArgs
* @param maxArgs
* @param alias
* @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.
*/
RedisCommand(String mode, int minArgs, int maxArgs, String... alias) {
@@ -291,6 +307,15 @@ public enum RedisCommand {
return maxArgs == 0 || minArgs == maxArgs;
}
/**
* Returns a {@link Set} of all {@link String aliases} for this {@link RedisCommand}.
*
* @return a {@link Set} of all {@link String aliases} for this {@link RedisCommand}.
*/
Set<String> getAliases() {
return Collections.unmodifiableSet(this.alias);
}
/**
* @return {@literal true} if the command triggers a read operation
*/
@@ -309,78 +334,64 @@ public enum RedisCommand {
* @return {@literal true} if values are read but not written
*/
public boolean isReadonly() {
return read && !write;
return isRead() && !isWrite();
}
/**
* {@link String#equalsIgnoreCase(String)} compare the given string representation of {@literal command} against the
* {@link #toString()} representation of the command as well as its given {@link #alias}.
* {@link String#equalsIgnoreCase(String) Compares} the given {@link String} representing the {@literal Redis command}
* to the {@link #toString()} representation of {@link RedisCommand} as well as any {@link #alias}.
*
* @param command
* @return true if positive match.
* @param command {@link String} representation of the {@literal Redis command} to match.
* @return {@literal true} if a positive match.
*/
public boolean isRepresentedBy(String command) {
if (!StringUtils.hasText(command)) {
return false;
}
if (toString().equalsIgnoreCase(command)) {
return true;
}
return alias.contains(command.toLowerCase());
return StringUtils.hasText(command)
&& (toString().equalsIgnoreCase(command) || this.alias.contains(command.toLowerCase()));
}
/**
* Validates given argument count against expected ones.
* Validates given {@link Integer argument count} against expected ones.
*
* @param nrArguments
* @exception IllegalArgumentException in case argument count does not match expected.
* @param argumentCount {@link Integer number of arguments} passed to the Redis command.
* @exception IllegalArgumentException if the given {@link Integer argument count} does not match expected.
*/
public void validateArgumentCount(int nrArguments) {
public void validateArgumentCount(int argumentCount) {
if (requiresArguments()) {
if (requiresExactNumberOfArguments()) {
if (nrArguments != maxArgs) {
throw new IllegalArgumentException(
String.format("%s command requires %s %s", this.name(), this.maxArgs, arguments(this.maxArgs)));
if (argumentCount != this.maxArgs) {
throw newIllegalArgumentException("%s command requires %d %s",
name(), this.maxArgs, arguments(this.maxArgs));
}
}
if (nrArguments < minArgs) {
throw new IllegalArgumentException(
String.format("%s command requires at least %s %s", this.name(), this.minArgs, arguments(this.maxArgs)));
if (argumentCount < this.minArgs) {
throw newIllegalArgumentException("%s command requires at least %d %s",
name(), this.minArgs, arguments(this.maxArgs));
}
if (maxArgs > 0 && nrArguments > maxArgs) {
throw new IllegalArgumentException(
String.format("%s command requires at most %s %s", this.name(), this.maxArgs, 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));
}
}
}
private static String arguments(int count) {
private String arguments(int count) {
return count == 1 ? "argument" : "arguments";
}
private IllegalArgumentException newIllegalArgumentException(String message, Object... arguments) {
return new IllegalArgumentException(String.format(message, arguments));
}
/**
* Returns the command represented by the given {@code key}. Returns {@link #UNKNOWN} if no matching command could be
* found.
* Returns the command represented by the given {@code key}, otherwise returns {@link #UNKNOWN}
* if no matching command could be found.
*
* @param key
* @return
* @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) {
if (!StringUtils.hasText(key)) {
return RedisCommand.UNKNOWN;
}
RedisCommand cmd = commandLookup.get(key.toLowerCase());
if (cmd != null) {
return cmd;
}
return RedisCommand.UNKNOWN;
return StringUtils.hasText(key) ? commandLookup.getOrDefault(key.toLowerCase(), UNKNOWN) : UNKNOWN;
}
}

View File

@@ -41,6 +41,7 @@ import org.springframework.util.Assert;
* mapping strategies.
*
* @author Mark Paluch
* @author John Blum
* @since 2.2
* @see ObjectHashMapper
* @see #doGetHashMapper(ConversionService, Class)
@@ -54,9 +55,9 @@ class StreamObjectMapper {
private final @Nullable HashMapper<Object, Object, Object> objectHashMapper;
static {
DefaultConversionService cs = new DefaultConversionService();
customConversions.registerConvertersIn(cs);
conversionService = cs;
DefaultConversionService defaultConversionService = new DefaultConversionService();
customConversions.registerConvertersIn(defaultConversionService);
conversionService = defaultConversionService;
}
/**
@@ -71,24 +72,23 @@ class StreamObjectMapper {
this.mapper = (HashMapper) mapper;
if (mapper instanceof ObjectHashMapper) {
if (mapper instanceof ObjectHashMapper objHashMapper) {
ObjectHashMapper ohm = (ObjectHashMapper) mapper;
this.objectHashMapper = new HashMapper<Object, Object, Object>() {
this.objectHashMapper = new HashMapper<>() {
@Override
public Map<Object, Object> toHash(Object object) {
return (Map) ohm.toHash(object);
return (Map) objHashMapper.toHash(object);
}
@Override
public Object fromHash(Map<Object, Object> hash) {
Map<byte[], byte[]> map = hash.entrySet().stream()
.collect(Collectors.toMap(e -> conversionService.convert(e.getKey(), byte[].class),
e -> conversionService.convert(e.getValue(), byte[].class)));
Map<byte[], byte[]> map = hash.entrySet().stream().collect(Collectors.toMap(
keyMapper -> conversionService.convert(keyMapper.getKey(), byte[].class),
valueMapper -> conversionService.convert(valueMapper.getValue(), byte[].class)));
return ohm.fromHash(map);
return objHashMapper.fromHash(map);
}
};
} else {
@@ -175,7 +175,7 @@ class StreamObjectMapper {
@SuppressWarnings("unchecked")
final <V, HK, HV> HashMapper<V, HK, HV> getHashMapper(Class<V> targetType) {
return (HashMapper) doGetHashMapper(conversionService, targetType);
return (HashMapper<V, HK, HV>) doGetHashMapper(conversionService, targetType);
}
/**

View File

@@ -26,17 +26,18 @@ import org.springframework.util.Assert;
*
* @author Mark Paluch
* @author Christoph Strobl
* @author John Blum
* @since 2.0
*/
class RedisSerializerToSerializationPairAdapter<T> implements SerializationPair<T> {
private static final RedisSerializerToSerializationPairAdapter<?> BYTE_BUFFER = new RedisSerializerToSerializationPairAdapter<>(
null);
private static final RedisSerializerToSerializationPairAdapter<?> BYTE_BUFFER =
new RedisSerializerToSerializationPairAdapter<>(null);
private static final RedisSerializerToSerializationPairAdapter<byte[]> BYTE_ARRAY = new RedisSerializerToSerializationPairAdapter<>(
RedisSerializer.byteArray());
private static final RedisSerializerToSerializationPairAdapter<byte[]> BYTE_ARRAY =
new RedisSerializerToSerializationPairAdapter<>(RedisSerializer.byteArray());
private final DefaultSerializationPair pair;
private final DefaultSerializationPair<T> pair;
RedisSerializerToSerializationPairAdapter(@Nullable RedisSerializer<T> serializer) {
pair = new DefaultSerializationPair<>(new DefaultRedisElementReader<>(serializer),
@@ -50,7 +51,7 @@ class RedisSerializerToSerializationPairAdapter<T> implements SerializationPair<
@SuppressWarnings("unchecked")
@Deprecated
static <T> SerializationPair<T> raw() {
return (SerializationPair) byteBuffer();
return (SerializationPair<T>) byteBuffer();
}
/**
@@ -65,16 +66,17 @@ class RedisSerializerToSerializationPairAdapter<T> implements SerializationPair<
* @return the {@link RedisSerializerToSerializationPairAdapter} for {@link ByteBuffer}.
* @since 2.2
*/
@SuppressWarnings("unchecked")
static SerializationPair<ByteBuffer> byteBuffer() {
return (SerializationPair) BYTE_BUFFER;
return (SerializationPair<ByteBuffer>) BYTE_BUFFER;
}
/**
* Create a {@link SerializationPair} from given {@link RedisSerializer}.
*
* @param <T> {@link Class type} of {@link Object} handled by the {@link RedisSerializer}.
* @param redisSerializer must not be {@literal null}.
* @param <T>
* @return
* @return the given {@link RedisSerializer} adapted as a {@link SerializationPair}.
*/
public static <T> SerializationPair<T> from(RedisSerializer<T> redisSerializer) {