Skip to content

[ISSUE #6592]🚀Add lite pull consumer implementation with assigned message queue management#6593

Merged
rocketmq-rust-bot merged 1 commit intomainfrom
feat-6592
Mar 1, 2026
Merged

[ISSUE #6592]🚀Add lite pull consumer implementation with assigned message queue management#6593
rocketmq-rust-bot merged 1 commit intomainfrom
feat-6592

Conversation

@mxsm
Copy link
Owner

@mxsm mxsm commented Mar 1, 2026

Which Issue(s) This PR Fixes(Closes)

Brief Description

How Did You Test This Change?

Summary by CodeRabbit

  • New Features
    • Introduced lite pull consumer with configurable subscription modes (None, Subscribe, Assign), service state lifecycle management, and consumer configuration options.
    • Added message queue assignment management system supporting per-queue offset tracking, pause state control, and dynamic queue operations.
    • Implemented batch message consumption request handling for efficient message processing with associated queue and process queue lifecycle coordination.

@rocketmq-rust-robot rocketmq-rust-robot added the feature🚀 Suggest an idea for this project. label Mar 1, 2026
@rocketmq-rust-bot
Copy link
Collaborator

🔊@mxsm 🚀Thanks for your contribution🎉!

💡CodeRabbit(AI) will review your code first🔥!

Note

🚨The code review suggestions from CodeRabbit are to be used as a reference only, and the PR submitter can decide whether to make changes based on their own judgment. Ultimately, the project management personnel will conduct the final code review💥.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 1, 2026

Walkthrough

This PR introduces a lite pull consumer implementation for RocketMQ by adding three new modules: assigned_message_queue for managing assigned queues with offset tracking, default_lite_pull_consumer_impl for the core consumer configuration and lifecycle, and lite_pull_consume_request for encapsulating consume request batches. It declares these modules in consumer_impl.rs.

Changes

Cohort / File(s) Summary
Module Declarations
rocketmq-client/src/consumer/consumer_impl.rs
Added three new crate-level public module declarations for lite pull consumer components.
Queue Management
rocketmq-client/src/consumer/consumer_impl/assigned_message_queue.rs
Introduces AssignedMessageQueue type with thread-safe RwLock-based map of message queues. Implements async APIs for queue lifecycle (put, remove), pause state management, and atomic offset tracking (pull, consume, seek) per queue.
Consumer Implementation
rocketmq-client/src/consumer/consumer_impl/default_lite_pull_consumer_impl.rs
Adds SubscriptionType enum, LitePullConsumerConfig struct with configuration fields, ServiceState enum, and DefaultLitePullConsumerImpl main struct. Implements MQConsumerInner trait with partial stubs for rebalance and offset persistence logic.
Consume Request
rocketmq-client/src/consumer/consumer_impl/lite_pull_consume_request.rs
Defines LitePullConsumeRequest struct encapsulating message batches, associated message queue, and process queue reference with constructor and accessor methods.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Three modules hop into the fold,
Queues assigned, offsets bold,
With locks and states to guide the way,
A lite pull consumer's grand display!
✨ The warren grows each day.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a lite pull consumer implementation with assigned message queue management, matching the code additions.
Linked Issues check ✅ Passed The PR implements the feature described in #6592: adds lite pull consumer implementation with assigned message queue management through three new modules.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the lite pull consumer feature. The three new modules (assigned message queue, default lite pull consumer, and consume request) are all core components of the lite pull consumer system.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-6592

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
rocketmq-client/src/consumer/consumer_impl/default_lite_pull_consumer_impl.rs (1)

168-175: Use .try_into() or clamp unsigned conversions for safer config mapping.

Lines 168, 170, and 175 cast from signed types (i64, i32) to u32 without validation. While these fields are never set to negative values in practice (defaults: 1000, 100, 10) and -1 sentinels appear only on different fields (pull_threshold_for_topic/-size), defensive conversion patterns would improve code robustness:

+        let pull_threshold_for_queue = u32::try_from(self.pull_threshold_for_queue)
+            .unwrap_or(1000);
+        let pull_threshold_size_for_queue = u32::try_from(self.pull_threshold_size_for_queue)
+            .unwrap_or(100);
+        let pull_batch_size = u32::try_from(self.pull_batch_size)
+            .unwrap_or(10);
+
         ArcMut::new(ConsumerConfig {
-            pull_threshold_for_queue: self.pull_threshold_for_queue as u32,
+            pull_threshold_for_queue,
-            pull_threshold_size_for_queue: self.pull_threshold_size_for_queue as u32,
+            pull_threshold_size_for_queue,
-            pull_batch_size: self.pull_batch_size as u32,
+            pull_batch_size,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@rocketmq-client/src/consumer/consumer_impl/default_lite_pull_consumer_impl.rs`
around lines 168 - 175, The struct construction in
default_lite_pull_consumer_impl.rs is unsafely casting signed integers to u32
for pull_threshold_for_queue, pull_threshold_size_for_queue and pull_batch_size;
replace the direct casts with fallible conversions (e.g. use
std::convert::TryInto or u32::try_from) and handle the Err case by clamping
negatives to 0 and values exceeding u32::MAX to u32::MAX (or otherwise providing
a safe default), so the mapping from the original signed types to the target u32
fields is validated and defensive.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rocketmq-client/src/consumer/consumer_impl/assigned_message_queue.rs`:
- Around line 150-155: The update_consume_offset currently updates offsets by
MessageQueue key only and can be overwritten by stale tasks; modify
update_consume_offset to first read the queue_map entry (as you do) and then
verify the assigned ProcessQueue identity/generation token on the retrieved
value before storing: e.g., read an atomic identifier field on the retrieved aq
(use the existing process_queue_id/generation field on the AssignedMessageQueue
or add one if missing), compare it to the expected id from the incoming
MessageQueue (or pass the expected id into update_consume_offset), and only call
aq.consume_offset.store(offset, Ordering::Release) if the ids match; otherwise
skip the update to avoid stale-task overwrites. Ensure the id read and
comparison are done atomically to avoid races.

In
`@rocketmq-client/src/consumer/consumer_impl/default_lite_pull_consumer_impl.rs`:
- Around line 342-346: The current do_rebalance method uses unimplemented! and
will panic at runtime; replace the panic with a concrete implementation that
either delegates to the existing RebalanceLitePullImpl via the Rebalance trait
or performs a safe no-op that returns/propagates an appropriate error;
specifically, in async fn do_rebalance(&self) when SubscriptionType::Subscribe
is detected, call the Rebalance trait implementation on the
RebalanceLitePullImpl instance used by this consumer (or call its rebalance
method) and propagate any Result/Err back to the caller instead of panicking,
and for the other similar methods (the places flagged at the other line ranges)
follow the same pattern: remove unimplemented!, implement delegation to the
Rebalance impl or return a defined error type so callers never cause a process
panic.

---

Nitpick comments:
In
`@rocketmq-client/src/consumer/consumer_impl/default_lite_pull_consumer_impl.rs`:
- Around line 168-175: The struct construction in
default_lite_pull_consumer_impl.rs is unsafely casting signed integers to u32
for pull_threshold_for_queue, pull_threshold_size_for_queue and pull_batch_size;
replace the direct casts with fallible conversions (e.g. use
std::convert::TryInto or u32::try_from) and handle the Err case by clamping
negatives to 0 and values exceeding u32::MAX to u32::MAX (or otherwise providing
a safe default), so the mapping from the original signed types to the target u32
fields is validated and defensive.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5b1a29 and 8b23e54.

📒 Files selected for processing (4)
  • rocketmq-client/src/consumer/consumer_impl.rs
  • rocketmq-client/src/consumer/consumer_impl/assigned_message_queue.rs
  • rocketmq-client/src/consumer/consumer_impl/default_lite_pull_consumer_impl.rs
  • rocketmq-client/src/consumer/consumer_impl/lite_pull_consume_request.rs

Comment on lines +150 to +155
/// Updates the consume offset for the specified queue.
pub async fn update_consume_offset(&self, mq: &MessageQueue, offset: i64) {
let map = self.queue_map.read().await;
if let Some(aq) = map.get(mq) {
aq.consume_offset.store(offset, Ordering::Release);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard consume offset updates with process-queue identity.

At Line 151-Line 155, consume offsets are updated by MessageQueue key only. A stale task from a previous assignment can overwrite offsets after reassignment.

Proposed fix
-    pub async fn update_consume_offset(&self, mq: &MessageQueue, offset: i64) {
+    pub async fn update_consume_offset(
+        &self,
+        mq: &MessageQueue,
+        offset: i64,
+        process_queue: &Arc<ProcessQueue>,
+    ) {
         let map = self.queue_map.read().await;
         if let Some(aq) = map.get(mq) {
-            aq.consume_offset.store(offset, Ordering::Release);
+            if Arc::ptr_eq(&aq.process_queue, process_queue) {
+                aq.consume_offset.store(offset, Ordering::Release);
+            }
         }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Updates the consume offset for the specified queue.
pub async fn update_consume_offset(&self, mq: &MessageQueue, offset: i64) {
let map = self.queue_map.read().await;
if let Some(aq) = map.get(mq) {
aq.consume_offset.store(offset, Ordering::Release);
}
/// Updates the consume offset for the specified queue.
pub async fn update_consume_offset(
&self,
mq: &MessageQueue,
offset: i64,
process_queue: &Arc<ProcessQueue>,
) {
let map = self.queue_map.read().await;
if let Some(aq) = map.get(mq) {
if Arc::ptr_eq(&aq.process_queue, process_queue) {
aq.consume_offset.store(offset, Ordering::Release);
}
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rocketmq-client/src/consumer/consumer_impl/assigned_message_queue.rs` around
lines 150 - 155, The update_consume_offset currently updates offsets by
MessageQueue key only and can be overwritten by stale tasks; modify
update_consume_offset to first read the queue_map entry (as you do) and then
verify the assigned ProcessQueue identity/generation token on the retrieved
value before storing: e.g., read an atomic identifier field on the retrieved aq
(use the existing process_queue_id/generation field on the AssignedMessageQueue
or add one if missing), compare it to the expected id from the incoming
MessageQueue (or pass the expected id into update_consume_offset), and only call
aq.consume_offset.store(offset, Ordering::Release) if the ids match; otherwise
skip the update to avoid stale-task overwrites. Ensure the id read and
comparison are done atomically to avoid races.

Comment on lines +342 to +346
async fn do_rebalance(&self) {
if *self.subscription_type.read().await == SubscriptionType::Subscribe {
// Rebalance implementation delegates to RebalanceLitePullImpl via the Rebalance trait
unimplemented!("do_rebalance is not yet implemented")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

unimplemented! in runtime trait methods will panic consumers.

At Line 345, Line 356, and Line 361, any call path hitting these methods will crash the process. These need concrete behavior (or a safe no-op with explicit error propagation) before merge.

Also applies to: 354-357, 359-362

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@rocketmq-client/src/consumer/consumer_impl/default_lite_pull_consumer_impl.rs`
around lines 342 - 346, The current do_rebalance method uses unimplemented! and
will panic at runtime; replace the panic with a concrete implementation that
either delegates to the existing RebalanceLitePullImpl via the Rebalance trait
or performs a safe no-op that returns/propagates an appropriate error;
specifically, in async fn do_rebalance(&self) when SubscriptionType::Subscribe
is detected, call the Rebalance trait implementation on the
RebalanceLitePullImpl instance used by this consumer (or call its rebalance
method) and propagate any Result/Err back to the caller instead of panicking,
and for the other similar methods (the places flagged at the other line ranges)
follow the same pattern: remove unimplemented!, implement delegation to the
Rebalance impl or return a defined error type so callers never cause a process
panic.

@codecov
Copy link

codecov bot commented Mar 1, 2026

Codecov Report

❌ Patch coverage is 0% with 267 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.77%. Comparing base (c5b1a29) to head (8b23e54).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...r/consumer_impl/default_lite_pull_consumer_impl.rs 0.00% 149 Missing ⚠️
...c/consumer/consumer_impl/assigned_message_queue.rs 0.00% 99 Missing ⚠️
...onsumer/consumer_impl/lite_pull_consume_request.rs 0.00% 19 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6593      +/-   ##
==========================================
- Coverage   41.84%   41.77%   -0.07%     
==========================================
  Files         956      959       +3     
  Lines      133557   133824     +267     
==========================================
+ Hits        55884    55905      +21     
- Misses      77673    77919     +246     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rocketmq-rust-bot rocketmq-rust-bot merged commit 1453509 into main Mar 1, 2026
17 of 20 checks passed
@rocketmq-rust-bot rocketmq-rust-bot added approved PR has approved and removed ready to review waiting-review waiting review this PR labels Mar 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI review first Ai review pr first approved PR has approved auto merge feature🚀 Suggest an idea for this project.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature🚀] Add lite pull consumer implementation with assigned message queue management

3 participants