From 3a09aa3566ecdb69cc2226e0bb4a2cd125aaa3a0 Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Wed, 24 May 2023 09:04:57 +0300 Subject: [PATCH] Feature - commandName setting added #3998 --- .../redisson/client/RedisClientConfig.java | 14 ++++++ .../client/handler/CommandEncoder.java | 14 ++++-- .../handler/RedisChannelInitializer.java | 2 +- .../java/org/redisson/config/BaseConfig.java | 18 ++++++++ .../org/redisson/config/CommandMapper.java | 43 +++++++++++++++++++ .../redisson/config/DefaultCommandMapper.java | 28 ++++++++++++ .../MasterSlaveConnectionManager.java | 7 ++- .../connection/SingleConnectionManager.java | 8 +++- .../test/java/org/redisson/RedissonTest.java | 19 ++++++++ 9 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 redisson/src/main/java/org/redisson/config/CommandMapper.java create mode 100644 redisson/src/main/java/org/redisson/config/DefaultCommandMapper.java diff --git a/redisson/src/main/java/org/redisson/client/RedisClientConfig.java b/redisson/src/main/java/org/redisson/client/RedisClientConfig.java index 28d2a2b13..1e20a1efc 100644 --- a/redisson/src/main/java/org/redisson/client/RedisClientConfig.java +++ b/redisson/src/main/java/org/redisson/client/RedisClientConfig.java @@ -20,7 +20,9 @@ import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.resolver.AddressResolverGroup; import io.netty.util.Timer; +import org.redisson.config.CommandMapper; import org.redisson.config.CredentialsResolver; +import org.redisson.config.DefaultCommandMapper; import org.redisson.config.SslProvider; import org.redisson.misc.RedisURI; @@ -75,6 +77,8 @@ public class RedisClientConfig { private Consumer connectedListener; private Consumer disconnectedListener; + private CommandMapper commandMapper = new DefaultCommandMapper(); + public RedisClientConfig() { } @@ -113,6 +117,7 @@ public class RedisClientConfig { this.disconnectedListener = config.disconnectedListener; this.sslKeyManagerFactory = config.sslKeyManagerFactory; this.sslTrustManagerFactory = config.sslTrustManagerFactory; + this.commandMapper = config.commandMapper; } public NettyHook getNettyHook() { @@ -390,4 +395,13 @@ public class RedisClientConfig { this.sslKeyManagerFactory = sslKeyManagerFactory; return this; } + + public CommandMapper getCommandMapper() { + return commandMapper; + } + + public RedisClientConfig setCommandMapper(CommandMapper commandMapper) { + this.commandMapper = commandMapper; + return this; + } } diff --git a/redisson/src/main/java/org/redisson/client/handler/CommandEncoder.java b/redisson/src/main/java/org/redisson/client/handler/CommandEncoder.java index 5e6088920..ba67c55f8 100644 --- a/redisson/src/main/java/org/redisson/client/handler/CommandEncoder.java +++ b/redisson/src/main/java/org/redisson/client/handler/CommandEncoder.java @@ -40,6 +40,7 @@ import io.netty.util.CharsetUtil; import org.redisson.client.ChannelName; import org.redisson.client.protocol.CommandData; import org.redisson.client.protocol.RedisCommands; +import org.redisson.config.CommandMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,14 +53,18 @@ import org.slf4j.LoggerFactory; @Sharable public class CommandEncoder extends MessageToByteEncoder> { - public static final CommandEncoder INSTANCE = new CommandEncoder(); - private final Logger log = LoggerFactory.getLogger(getClass()); private static final char ARGS_PREFIX = '*'; private static final char BYTES_PREFIX = '$'; private static final byte[] CRLF = "\r\n".getBytes(); + private CommandMapper commandMapper; + + public CommandEncoder(CommandMapper commandMapper) { + this.commandMapper = commandMapper; + } + @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { if (acceptOutboundMessage(msg)) { @@ -86,8 +91,9 @@ public class CommandEncoder extends MessageToByteEncoder> { } out.writeCharSequence(Long.toString(len), CharsetUtil.US_ASCII); out.writeBytes(CRLF); - - writeArgument(out, msg.getCommand().getName().getBytes(CharsetUtil.UTF_8)); + + String name = commandMapper.map(msg.getCommand().getName()); + writeArgument(out, name.getBytes(CharsetUtil.UTF_8)); if (msg.getCommand().getSubName() != null) { writeArgument(out, msg.getCommand().getSubName().getBytes(CharsetUtil.UTF_8)); } diff --git a/redisson/src/main/java/org/redisson/client/handler/RedisChannelInitializer.java b/redisson/src/main/java/org/redisson/client/handler/RedisChannelInitializer.java index e61088bc3..18f123805 100644 --- a/redisson/src/main/java/org/redisson/client/handler/RedisChannelInitializer.java +++ b/redisson/src/main/java/org/redisson/client/handler/RedisChannelInitializer.java @@ -83,7 +83,7 @@ public class RedisChannelInitializer extends ChannelInitializer { ch.pipeline().addLast( connectionWatchdog, - CommandEncoder.INSTANCE, + new CommandEncoder(config.getCommandMapper()), CommandBatchEncoder.INSTANCE); if (type == Type.PLAIN) { diff --git a/redisson/src/main/java/org/redisson/config/BaseConfig.java b/redisson/src/main/java/org/redisson/config/BaseConfig.java index 5e5e6f5a6..c36a9383e 100644 --- a/redisson/src/main/java/org/redisson/config/BaseConfig.java +++ b/redisson/src/main/java/org/redisson/config/BaseConfig.java @@ -108,6 +108,7 @@ public class BaseConfig> { private NameMapper nameMapper = NameMapper.direct(); + private CommandMapper commandMapper = CommandMapper.direct(); BaseConfig() { } @@ -137,6 +138,7 @@ public class BaseConfig> { setTcpNoDelay(config.isTcpNoDelay()); setNameMapper(config.getNameMapper()); setCredentialsResolver(config.getCredentialsResolver()); + setCommandMapper(config.getCommandMapper()); } /** @@ -557,4 +559,20 @@ public class BaseConfig> { this.sslKeyManagerFactory = keyManagerFactory; return this; } + + public CommandMapper getCommandMapper() { + return commandMapper; + } + + /** + * Defines Command mapper which maps Redis command name. + * Applied to all Redis commands. + * + * @param commandMapper Redis command name mapper object + * @return config + */ + public BaseConfig setCommandMapper(CommandMapper commandMapper) { + this.commandMapper = commandMapper; + return this; + } } diff --git a/redisson/src/main/java/org/redisson/config/CommandMapper.java b/redisson/src/main/java/org/redisson/config/CommandMapper.java new file mode 100644 index 000000000..730b3434e --- /dev/null +++ b/redisson/src/main/java/org/redisson/config/CommandMapper.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2013-2022 Nikita Koksharov + * + * Licensed 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 + * + * http://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 org.redisson.config; + +/** + * Maps Redis command names. + * + * @author Nikita Koksharov + * + */ +public interface CommandMapper { + + /** + * Applies map function to the input Redis command name + * + * @param name - original command name + * @return mapped command name + */ + String map(String name); + + /** + * Returns input Redis command name. Used by default + * + * @return NameMapper instance + */ + static CommandMapper direct() { + return new DefaultCommandMapper(); + } + +} diff --git a/redisson/src/main/java/org/redisson/config/DefaultCommandMapper.java b/redisson/src/main/java/org/redisson/config/DefaultCommandMapper.java new file mode 100644 index 000000000..0f3da0791 --- /dev/null +++ b/redisson/src/main/java/org/redisson/config/DefaultCommandMapper.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2013-2022 Nikita Koksharov + * + * Licensed 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 + * + * http://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 org.redisson.config; + +/** + * + * @author Nikita Koksharov + * + */ +public class DefaultCommandMapper implements CommandMapper { + @Override + public String map(String name) { + return name; + } +} diff --git a/redisson/src/main/java/org/redisson/connection/MasterSlaveConnectionManager.java b/redisson/src/main/java/org/redisson/connection/MasterSlaveConnectionManager.java index fa67ac022..2502a303f 100644 --- a/redisson/src/main/java/org/redisson/connection/MasterSlaveConnectionManager.java +++ b/redisson/src/main/java/org/redisson/connection/MasterSlaveConnectionManager.java @@ -204,7 +204,10 @@ public class MasterSlaveConnectionManager implements ConnectionManager { c.setSslKeystore(cfg.getSslKeystore()); c.setSslKeystorePassword(cfg.getSslKeystorePassword()); c.setSslProtocols(cfg.getSslProtocols()); - + c.setSslCiphers(cfg.getSslCiphers()); + c.setSslKeyManagerFactory(cfg.getSslKeyManagerFactory()); + c.setSslTrustManagerFactory(cfg.getSslTrustManagerFactory()); + c.setRetryInterval(cfg.getRetryInterval()); c.setRetryAttempts(cfg.getRetryAttempts()); c.setTimeout(cfg.getTimeout()); @@ -231,6 +234,7 @@ public class MasterSlaveConnectionManager implements ConnectionManager { c.setTcpNoDelay(cfg.isTcpNoDelay()); c.setNameMapper(cfg.getNameMapper()); c.setCredentialsResolver(cfg.getCredentialsResolver()); + c.setCommandMapper(cfg.getCommandMapper()); return c; } @@ -287,6 +291,7 @@ public class MasterSlaveConnectionManager implements ConnectionManager { .setUsername(config.getUsername()) .setPassword(config.getPassword()) .setNettyHook(serviceManager.getCfg().getNettyHook()) + .setCommandMapper(config.getCommandMapper()) .setCredentialsResolver(config.getCredentialsResolver()) .setConnectedListener(addr -> { if (!serviceManager.isShuttingDown()) { diff --git a/redisson/src/main/java/org/redisson/connection/SingleConnectionManager.java b/redisson/src/main/java/org/redisson/connection/SingleConnectionManager.java index cd8a57743..8afa1fe4d 100644 --- a/redisson/src/main/java/org/redisson/connection/SingleConnectionManager.java +++ b/redisson/src/main/java/org/redisson/connection/SingleConnectionManager.java @@ -42,7 +42,10 @@ public class SingleConnectionManager extends MasterSlaveConnectionManager { newconfig.setSslKeystore(cfg.getSslKeystore()); newconfig.setSslKeystorePassword(cfg.getSslKeystorePassword()); newconfig.setSslProtocols(cfg.getSslProtocols()); - + newconfig.setSslCiphers(cfg.getSslCiphers()); + newconfig.setSslKeyManagerFactory(cfg.getSslKeyManagerFactory()); + newconfig.setSslTrustManagerFactory(cfg.getSslTrustManagerFactory()); + newconfig.setRetryAttempts(cfg.getRetryAttempts()); newconfig.setRetryInterval(cfg.getRetryInterval()); newconfig.setTimeout(cfg.getTimeout()); @@ -66,7 +69,8 @@ public class SingleConnectionManager extends MasterSlaveConnectionManager { newconfig.setTcpNoDelay(cfg.isTcpNoDelay()); newconfig.setNameMapper(cfg.getNameMapper()); newconfig.setCredentialsResolver(cfg.getCredentialsResolver()); - + newconfig.setCommandMapper(cfg.getCommandMapper()); + return newconfig; } diff --git a/redisson/src/test/java/org/redisson/RedissonTest.java b/redisson/src/test/java/org/redisson/RedissonTest.java index 6e37eb7b9..c2f1c2fce 100644 --- a/redisson/src/test/java/org/redisson/RedissonTest.java +++ b/redisson/src/test/java/org/redisson/RedissonTest.java @@ -891,6 +891,25 @@ public class RedissonTest extends BaseTest { } + @Test + public void testCommandMapper() { + Config c = createConfig(); + c.useSingleServer().setCommandMapper(n -> { + if (n.equals("EVAL")) { + return "EVAL_111"; + } + return n; + }); + RedissonClient redisson = Redisson.create(c); + RBucket b = redisson.getBucket("test"); + RedisException e = Assertions.assertThrows(RedisException.class, () -> { + b.compareAndSet("test", "v1"); + }); + assertThat(e.getMessage()).startsWith("ERR unknown command `EVAL_111`"); + + redisson.shutdown(); + } + @Test public void testURIPassword() throws InterruptedException, IOException { RedisProcess runner = new RedisRunner()