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);

Reply via email to