Aias00 opened a new pull request, #10606:
URL: https://github.com/apache/rocketmq/pull/10606

   ## What problem does this PR solve?
   
   Issue: #10263
   
   This PR adds message deduplication capability for consumers to prevent 
duplicate message processing, with correct handling of `ackIndex` semantics 
when duplicates are filtered.
   
   ### Problem Summary
   When messages are redelivered due to network issues, rebalancing, or broker 
restarts, consumers may process the same message multiple times, causing:
   - Duplicate database writes
   - Repeated business logic execution
   - Data inconsistency
   
   ### Key Changes
   
   1. **MessageDeduplicator**: Lightweight deduplication cache using Caffeine
      - Keys: user-defined message keys (preferred) or msgId
      - Configurable cache size and expiration time
      - Thread-safe concurrent access
   
   2. **ConsumeMessageConcurrentlyService**: Filter duplicates before listener 
invocation
      - Skip duplicate messages, advancing offset correctly
      - Correctly handle `ackIndex` semantics for partial success:
        - Only mark messages up to `ackIndex` in filteredMsgs
        - Map filtered-list `ackIndex` to original msgs position
   
   3. **Configuration**: 
      - `deduplicationEnabled`: Enable/disable feature (default: false)
      - `deduplicationCacheSize`: Max cache entries (default: 10000)
      - `deduplicationExpireTime`: Entry expiration in ms (default: 60000)
   
   ### Critical Fix for ackIndex Semantics
   When duplicates exist and listener returns partial success:
   - **Before**: All filteredMsgs marked as processed, ackIndex set to 
msgs.size()-1 → **Message loss**
   - **After**: Only filteredMsgs[0..ackIndex] marked, ackIndex mapped to 
original position → **Correct retry behavior**
   
   Example:
   ```
   msgs = [dup, new1, new2]
   filteredMsgs = [new1, new2]
   listener returns: ackIndex=0 (only new1 success)
   
   Old behavior: new1, new2 both marked → new2 lost
   New behavior: only new1 marked → new2 correctly retried
   ```
   
   ### Tests
   - `MessageDeduplicationTest`: 13 tests covering:
     - Basic duplicate detection
     - Key extraction (user keys vs msgId)
     - Cache expiration and size limits
     - Concurrent access safety
     - ackIndex mapping for partial/full success
     - Filtering order preservation
   
   - `ConsumeMessageConcurrentlyServiceTest`: Existing tests pass
   
   ## How to use
   
   ```java
   DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group");
   consumer.setDeduplicationEnabled(true);
   consumer.setDeduplicationCacheSize(10000);
   consumer.setDeduplicationExpireTime(60000);
   consumer.start();
   ```
   
   ## Documentation
   - Updated `DefaultMQPushConsumer.md` with deduplication configuration
   
   ## Verification
   - All unit tests pass
   - Diff format check passes
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to