This is an automated email from the ASF dual-hosted git repository. apupier pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit 371ea2edf7c8fdab374f83a3c64bf40ca68260bf Author: smjain <[email protected]> AuthorDate: Wed Sep 30 08:15:53 2026 +0530 CAMEL-25155: camel-spring-redis - make SpringRedisIdempotentRepository.add atomic add() checked the key with SISMEMBER and then added it with SADD, and compared the result of SADD with null, which is true whether SADD added the key or not. Two consumers, on one node or on two nodes sharing the Redis set, that received the same message id at the same time both saw the key missing and both got true from add(), so the Idempotent Consumer processed the message twice. SADD is atomic and returns the number of members it added: 1 for the caller that added the key, 0 when the key is already in the set. Return true only when it added the key, in one round trip instead of two. Co-Authored-By: Claude Opus 5.5 <[email protected]> --- .../idempotent/SpringRedisIdempotentRepository.java | 9 ++++----- .../idempotent/SpringRedisIdempotentRepositoryTest.java | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/components/camel-spring-parent/camel-spring-redis/src/main/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepository.java b/components/camel-spring-parent/camel-spring-redis/src/main/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepository.java index 1418db3eeb85..de77443df74c 100644 --- a/components/camel-spring-parent/camel-spring-redis/src/main/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepository.java +++ b/components/camel-spring-parent/camel-spring-redis/src/main/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepository.java @@ -82,11 +82,10 @@ public class SpringRedisIdempotentRepository extends ServiceSupport implements I @Override @ManagedOperation(description = "Adds the key to the store") public boolean add(String key) { - if (!contains(key)) { - return setOperations.add(repositoryName, key) != null; - } else { - return false; - } + // SADD is atomic and returns the number of members it added, which is 0 when the key is already in the set + // (also when another consumer added it concurrently), so only one caller adds a given key + Long added = setOperations.add(repositoryName, key); + return added != null && added > 0; } @Override diff --git a/components/camel-spring-parent/camel-spring-redis/src/test/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepositoryTest.java b/components/camel-spring-parent/camel-spring-redis/src/test/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepositoryTest.java index 157e86d64a6e..ad0f3cc334a0 100644 --- a/components/camel-spring-parent/camel-spring-redis/src/test/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepositoryTest.java +++ b/components/camel-spring-parent/camel-spring-redis/src/test/java/org/apache/camel/component/redis/processor/idempotent/SpringRedisIdempotentRepositoryTest.java @@ -67,6 +67,22 @@ public class SpringRedisIdempotentRepositoryTest { verify(setOperations).add(REPOSITORY, KEY); } + @Test + public void shouldReturnTrueWhenKeyIsAdded() { + when(setOperations.add(REPOSITORY, KEY)).thenReturn(1L); + + assertTrue(idempotentRepository.add(KEY)); + } + + @Test + public void shouldReturnFalseWhenKeyIsAlreadyInTheSet() { + // the key was not in the set when checked, but another consumer added it before this one: SADD adds nothing + when(setOperations.isMember(REPOSITORY, KEY)).thenReturn(false); + when(setOperations.add(REPOSITORY, KEY)).thenReturn(0L); + + assertFalse(idempotentRepository.add(KEY)); + } + @Test public void shoulCheckForMembers() { idempotentRepository.contains(KEY);
