From 88999986e49dc05d89e3052a375e48eb8e7bf8ed Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Thu, 21 Apr 2022 09:47:03 +0300 Subject: [PATCH] Fixed - SET command should be an idempotent operation #4250 --- .../java/org/redisson/client/protocol/RedisCommand.java | 5 +++++ .../java/org/redisson/client/protocol/RedisCommands.java | 5 +++-- .../src/main/java/org/redisson/command/RedisExecutor.java | 6 ++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/redisson/src/main/java/org/redisson/client/protocol/RedisCommand.java b/redisson/src/main/java/org/redisson/client/protocol/RedisCommand.java index baa496c95..f88e224b0 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/RedisCommand.java +++ b/redisson/src/main/java/org/redisson/client/protocol/RedisCommand.java @@ -107,6 +107,11 @@ public class RedisCommand { return convertor; } + public boolean isNoRetry() { + return RedisCommands.NO_RETRY.contains(getName()) + || RedisCommands.NO_RETRY_COMMANDS.contains(this); + } + public boolean isBlockingCommand() { return RedisCommands.BLOCKING_COMMAND_NAMES.contains(getName()) || RedisCommands.BLOCKING_COMMANDS.contains(this); diff --git a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java index e4a905c8a..7dbb20883 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -668,11 +668,12 @@ public interface RedisCommands { RedisStrictCommand> INFO_CLUSTER = new RedisStrictCommand>("INFO", "CLUSTER", new StringMapDataDecoder()); RedisStrictCommand> INFO_KEYSPACE = new RedisStrictCommand>("INFO", "KEYSPACE", new StringMapDataDecoder()); + Set NO_RETRY_COMMANDS = new HashSet<>(Arrays.asList(SET_BOOLEAN)); + Set NO_RETRY = new HashSet<>( Arrays.asList(RPOPLPUSH.getName(), LPOP.getName(), RPOP.getName(), LPUSH.getName(), RPUSH.getName(), LPUSHX.getName(), RPUSHX.getName(), GEOADD.getName(), XADD.getName(), APPEND.getName(), DECR.getName(), "DECRBY", INCR.getName(), INCRBY.getName(), ZINCRBY.getName(), - "HINCRBYFLOAT", "HINCRBY", "INCRBYFLOAT", SET_BOOLEAN.getName(), SETNX.getName(), - MSETNX.getName(), HSETNX.getName())); + "HINCRBYFLOAT", "HINCRBY", "INCRBYFLOAT", SETNX.getName(), MSETNX.getName(), HSETNX.getName())); } diff --git a/redisson/src/main/java/org/redisson/command/RedisExecutor.java b/redisson/src/main/java/org/redisson/command/RedisExecutor.java index 3103f8729..329cfdf0e 100644 --- a/redisson/src/main/java/org/redisson/command/RedisExecutor.java +++ b/redisson/src/main/java/org/redisson/command/RedisExecutor.java @@ -336,7 +336,9 @@ public class RedisExecutor { attemptPromise.completeExceptionally( new RedisResponseTimeoutException("Redis server response timeout (" + timeoutAmount + " ms) occured" - + " after " + attempt + " retry attempts. Increase nettyThreads and/or timeout settings. Try to define pingConnectionInterval setting. Command: " + + " after " + attempt + " retry attempts," + + " is non-idempotent command: " + (command != null && command.isNoRetry()) + + ". Increase nettyThreads and/or timeout settings. Try to define pingConnectionInterval setting. Command: " + LogHelper.toString(command, params) + ", channel: " + connection.getChannel())); }; @@ -346,7 +348,7 @@ public class RedisExecutor { protected boolean isResendAllowed(int attempt, int attempts) { return attempt < attempts && !noRetry - && (command == null || (!command.isBlockingCommand() && !RedisCommands.NO_RETRY.contains(command.getName()))); + && (command == null || (!command.isBlockingCommand() && !command.isNoRetry())); } private void handleBlockingOperations(CompletableFuture attemptPromise, RedisConnection connection, Long popTimeout) {