Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ISSUE #1004]🚀optimize and improve consume logic⚡️ #1008

Merged
merged 3 commits into from
Sep 27, 2024
Merged

Conversation

mxsm
Copy link
Owner

@mxsm mxsm commented Sep 27, 2024

Which Issue(s) This PR Fixes(Closes)

Fixes #1004

Brief Description

How Did You Test This Change?

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced asynchronous methods for batch locking and unlocking message queues, enhancing efficiency.
    • Added new modules and data structures for handling batch request and response bodies in the messaging protocol.
    • Enhanced the ProcessQueue struct with methods for better tracking of unlock attempts and timestamps.
    • Expanded the RebalanceLocal trait with several new asynchronous methods for improved message queue management.
  • Bug Fixes

    • Updated locking mechanisms for improved reliability and performance in message queue management.
  • Documentation

    • Expanded protocol capabilities with new request and response modules, improving clarity and functionality.

These updates aim to enhance the overall user experience by improving the efficiency and reliability of message queue operations.

Copy link
Contributor

coderabbitai bot commented Sep 27, 2024

Walkthrough

The changes in this pull request introduce significant modifications to the RocketMQ client implementation, particularly focusing on enhancing the locking and unlocking mechanisms for message queues. New asynchronous methods are added to various structs and traits, improving the handling of message consumption and queue management. Additionally, new request and response structures are introduced to facilitate batch operations for locking and unlocking message queues.

Changes

Files Change Summary
rocketmq-client/src/consumer/consumer_impl/process_queue.rs Updated consume_lock field type and added methods for tracking unlock attempts and timestamps.
rocketmq-client/src/consumer/consumer_impl/re_balance.rs Enhanced RebalanceLocal trait with new asynchronous methods and modified the unlock method to be asynchronous.
rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs Refactored queue management logic, added new asynchronous methods for locking and unlocking queues, and introduced a helper method for building process queue tables.
rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_push_impl.rs Modified unlock method to be asynchronous and updated logic for unlocking message queues with timeout checks.
rocketmq-client/src/implementation/mq_client_api_impl.rs Introduced unlock_batch_mq and lock_batch_mq methods for handling batch locking and unlocking of message queues with appropriate error handling.
rocketmq-remoting/src/protocol/body.rs Added new public modules for handling request and response bodies related to batch operations.
rocketmq-remoting/src/protocol/body/request.rs Introduced lock_batch_request_body module for managing batch lock requests.
rocketmq-remoting/src/protocol/body/request/lock_batch_request_body.rs Defined LockBatchRequestBody struct for batch locking requests with serialization support.
rocketmq-remoting/src/protocol/body/response.rs Added lock_batch_response_body module for handling responses to batch lock requests.
rocketmq-remoting/src/protocol/body/response/lock_batch_response_body.rs Defined LockBatchResponseBody struct for batch lock response with serialization support.
rocketmq-remoting/src/protocol/body/unlock_batch_request_body.rs Defined UnlockBatchRequestBody struct for batch unlock requests with serialization support.
rocketmq-remoting/src/protocol/header.rs Added modules for handling request headers related to batch locking and unlocking.
rocketmq-remoting/src/protocol/header/lock_batch_mq_request_header.rs Introduced LockBatchMqRequestHeader struct for batch lock request headers with serialization and conversion methods.
rocketmq-remoting/src/protocol/header/unlock_batch_mq_request_header.rs Defined UnlockBatchMqRequestHeader struct for batch unlock request headers with serialization and conversion methods.

Assessment against linked issues

Objective Addressed Explanation
Optimize and improve consume logic (1004)

Possibly related PRs

  • [ISSUE #735] 🔥Optimize pull message logic #736: The changes in the main PR involve adding a new dependency (futures = "0.3"), which is related to the addition of the cfg-if dependency in the rocketmq-broker's Cargo.toml file, indicating a potential overlap in dependency management.
  • [ISSUE #1000]✨Add RocketMQTokioRwLock and RocketMQTokioMutex for rocketmq crate🎨 #1001: The addition of RocketMQTokioRwLock and RocketMQTokioMutex in the main PR suggests improvements in concurrency handling, which may relate to similar enhancements in the rocketmq-client and rocketmq-broker implementations that involve managing shared state and concurrency.
  • [ISSUE #1006]🎨Fix code style #1007: The focus on code style improvements in this PR may relate to the overall quality and maintainability of the codebase, which is a general goal that aligns with the changes made in the main PR regarding dependency management and structure.

Suggested labels

approved

Suggested reviewers

  • SpaceXCN
  • TeslaRustor

Poem

🐇 In the meadow where queues do play,
New locks and unlocks brighten the day.
With methods so swift, they dance and they twirl,
RocketMQ hops into a better world!
So let’s cheer for changes, both bold and bright,
For message queues now take flight! 🌼


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1c7dbe0 and 6561ec9.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml (1 hunks)
  • rocketmq-client/Cargo.toml (1 hunks)
  • rocketmq-client/src/consumer/consumer_impl/re_balance.rs (2 hunks)
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs (5 hunks)
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_push_impl.rs (5 hunks)
  • rocketmq-client/src/implementation/mq_client_api_impl.rs (3 hunks)
  • rocketmq-remoting/src/protocol/body/request/lock_batch_request_body.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • rocketmq-client/src/consumer/consumer_impl/re_balance.rs
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_push_impl.rs
  • rocketmq-client/src/implementation/mq_client_api_impl.rs
  • rocketmq-remoting/src/protocol/body/request/lock_batch_request_body.rs
🔇 Additional comments (2)
rocketmq-client/Cargo.toml (1)

42-44: Addition of 'futures' dependency looks good, but requires clarification.

The addition of the 'futures' crate as a dependency is consistent with the existing dependency structure, using the workspace feature. This aligns with the project's dependency management approach.

However, I have a few points to consider:

  1. The PR objectives mention optimizing and improving consume logic, but it's not immediately clear how the 'futures' crate contributes to this goal. Could you provide more context on why this dependency was added and how it relates to the consume logic improvements?

  2. The 'futures' crate is quite versatile. Are there specific features or functionalities from this crate that you plan to use? This information could help in understanding the intended improvements and ensure that we're not adding unnecessary dependencies.

  3. Have you considered any potential conflicts or overlaps with existing asynchronous functionalities provided by the 'tokio' ecosystem, which is already a dependency?

  4. As this change might affect the project's asynchronous behavior, have you conducted thorough testing to ensure compatibility with existing asynchronous code?

To verify the consistency of workspace usage and check for potential conflicts, please run the following script:

✅ Verification successful

Addition of 'futures' dependency is verified and appropriate.

All dependencies, including futures, consistently use the workspace feature, and there are no conflicting version specifications. The futures crate is actively utilized in the codebase, supporting the project's asynchronous functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check consistency of workspace usage and potential conflicts

# Test 1: Check if all dependencies use the workspace feature
echo "Checking workspace feature consistency:"
grep -E '^\w+ = \{ workspace = true \}$' rocketmq-client/Cargo.toml

# Test 2: Check for any direct version specifications that might conflict with workspace
echo "Checking for direct version specifications:"
grep -E '^\w+ = "[0-9]+\.[0-9]+\.[0-9]+"' rocketmq-client/Cargo.toml

# Test 3: Look for any mentions of 'futures' in the codebase to understand its usage
echo "Searching for 'futures' usage in the codebase:"
rg --type rust 'use futures::'

Length of output: 794

Cargo.toml (1)

79-82: Addition of futures crate: Verify necessity and impact

The futures crate (version 0.3) has been added as a dependency. This addition aligns with the PR objective of optimizing and improving consume logic, as futures provides abstractions for asynchronous programming which can be beneficial for handling message consumption efficiently.

However, please consider the following points:

  1. Ensure that the futures crate is actually used in the changes made to improve the consume logic. If it's not directly used, it might be unnecessary.
  2. Version 0.3 is appropriate as it's the latest stable version of the futures crate.
  3. There doesn't appear to be any conflict with existing dependencies.
  4. The addition of futures might impact the project's asynchronous runtime behavior, especially if it's used in conjunction with tokio (which is already a dependency).

To confirm the necessity of this addition, let's check for usage of the futures crate in the changed files:

If the script doesn't return any results, consider removing this dependency to keep the project lean.

✅ Verification successful

Addition of futures crate is justified and properly used

The usage of the futures crate (version 0.3) in multiple files confirms its necessity for the asynchronous operations introduced in this PR. No conflicts with existing dependencies were found, and the version specified is appropriate.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of the futures crate in changed files

# Search for 'use futures' or 'futures::' in all Rust files
rg --type rust -e 'use futures' -e 'futures::'

Length of output: 913


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@mxsm
Copy link
Owner Author

mxsm commented Sep 27, 2024

🚀Thanks for your contribution🎉. CodeRabbit(AI) will review your code first🔥

Copy link

codecov bot commented Sep 27, 2024

Codecov Report

Attention: Patch coverage is 0% with 67 lines in your changes missing coverage. Please review.

Project coverage is 19.92%. Comparing base (e0e896f) to head (6561ec9).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...rc/protocol/header/lock_batch_mq_request_header.rs 0.00% 14 Missing ⚠️
.../protocol/header/unlock_batch_mq_request_header.rs 0.00% 14 Missing ⚠️
...c/protocol/body/request/lock_batch_request_body.rs 0.00% 10 Missing ⚠️
...ing/src/protocol/body/unlock_batch_request_body.rs 0.00% 10 Missing ⚠️
...client/src/consumer/consumer_impl/process_queue.rs 0.00% 9 Missing ⚠️
...mq-client/src/implementation/mq_client_api_impl.rs 0.00% 6 Missing ⚠️
...er/consumer_impl/re_balance/rebalance_push_impl.rs 0.00% 2 Missing ⚠️
...protocol/body/response/lock_batch_response_body.rs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1008      +/-   ##
==========================================
- Coverage   19.95%   19.92%   -0.04%     
==========================================
  Files         413      418       +5     
  Lines       34440    34502      +62     
==========================================
+ Hits         6874     6876       +2     
- Misses      27566    27626      +60     

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

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: 22

🧹 Outside diff range and nitpick comments (18)
rocketmq-remoting/src/protocol/body/response/lock_batch_response_body.rs (1)

23-27: Consider adding documentation and reviewing trait derivations.

The LockBatchResponseBody struct looks good overall, but consider the following suggestions:

  1. Add documentation comments (///) for the struct and its field to improve API clarity.
  2. The #[serde(rename = "lockOKMQSet")] attribute uses camelCase, which is atypical for Rust. If this is for compatibility with an external JSON format, consider adding a comment explaining this choice.
  3. Review if the Default trait derivation is necessary. If there's no clear default state for this response body, it might be better to omit it to avoid potential misuse.

Example improvement:

/// Represents the response body for a batch locking operation in RocketMQ.
#[derive(Serialize, Deserialize, Debug)]
pub struct LockBatchResponseBody {
    /// Set of message queues that were successfully locked.
    #[serde(rename = "lockOKMQSet")]
    // Note: camelCase used for compatibility with external JSON format
    pub lock_ok_mq_set: HashSet<MessageQueue>,
}
rocketmq-remoting/src/protocol/body/request/lock_batch_request_body.rs (1)

24-31: LGTM! Consider adding documentation.

The LockBatchRequestBody struct is well-designed with appropriate field types and derive macros. The use of Option<String> for consumer_group and client_id, and HashSet<MessageQueue> for mq_set are good choices.

Consider adding documentation comments to the struct and its fields to improve code readability and maintainability. For example:

/// Represents a batch request for locking message queues.
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct LockBatchRequestBody {
    /// The consumer group making the lock request.
    pub consumer_group: Option<String>,
    /// The ID of the client making the lock request.
    pub client_id: Option<String>,
    /// Whether to restrict the operation to the current broker only.
    pub only_this_broker: bool,
    /// The set of message queues to be locked.
    pub mq_set: HashSet<MessageQueue>,
}
rocketmq-remoting/src/protocol/body/unlock_batch_request_body.rs (2)

24-31: LGTM: Struct definition is well-structured. Consider adding documentation.

The UnlockBatchRequestBody struct is correctly defined with appropriate field types and derive macros. The use of Option<String> for optional fields and HashSet<MessageQueue> for unique message queues is a good design choice.

Consider adding documentation comments (///) for the struct and its fields to improve code readability and maintainability. For example:

/// Represents a request body for unlocking a batch of messages.
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct UnlockBatchRequestBody {
    /// The consumer group associated with the unlock request.
    pub consumer_group: Option<String>,
    /// The client ID associated with the unlock request.
    pub client_id: Option<String>,
    /// Indicates whether the operation should be restricted to the current broker.
    pub only_this_broker: bool,
    /// The set of message queues to be unlocked.
    pub mq_set: HashSet<MessageQueue>,
}

33-45: LGTM: Display trait implementation is correct. Minor style improvement suggested.

The Display trait implementation for UnlockBatchRequestBody is well-structured and correctly handles optional fields. It provides a comprehensive string representation of the struct.

Consider using the format! macro instead of write! for better readability:

impl Display for UnlockBatchRequestBody {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", format!(
            "UnlockBatchRequestBody [consumer_group={}, client_id={}, only_this_broker={}, mq_set={:?}]",
            self.consumer_group.as_deref().unwrap_or(""),
            self.client_id.as_deref().unwrap_or(""),
            self.only_this_broker,
            self.mq_set
        ))
    }
}

This change also uses as_deref() instead of as_ref() for a more idiomatic approach to handling Option<String>.

rocketmq-remoting/src/protocol/header/lock_batch_mq_request_header.rs (2)

26-31: LGTM! Consider adding documentation.

The LockBatchMqRequestHeader struct is well-defined with appropriate derive macros and serde attributes. The use of Option<RpcRequestHeader> provides flexibility.

Consider adding documentation comments to describe the purpose of this struct and its field. This would improve code readability and maintainability. For example:

/// Represents the header for a batch lock request in the RocketMQ protocol.
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct LockBatchMqRequestHeader {
    /// The RPC request header, flattened into the JSON structure.
    #[serde(flatten)]
    pub rpc_request_header: Option<RpcRequestHeader>,
}

33-43: LGTM! Consider handling empty map case.

The implementation of CommandCustomHeader for LockBatchMqRequestHeader is correct and efficiently handles the optional rpc_request_header.

Consider returning None if the resulting map is empty. This could provide more meaningful information to the caller. Here's a suggested implementation:

impl CommandCustomHeader for LockBatchMqRequestHeader {
    fn to_map(&self) -> Option<HashMap<String, String>> {
        self.rpc_request_header
            .as_ref()
            .and_then(|header| header.to_map())
            .filter(|map| !map.is_empty())
    }
}

This implementation is more concise and returns None if rpc_request_header is None or if its to_map() method returns an empty map.

rocketmq-remoting/src/protocol/header/unlock_batch_mq_request_header.rs (1)

26-31: LGTM: Struct definition is correct. Consider adding documentation.

The UnlockBatchMqRequestHeader struct is well-defined with appropriate serde attributes. The use of Option<RpcRequestHeader> is a good choice for handling cases where the header might not be present.

Consider adding documentation comments to explain the purpose of this struct and its field. For example:

/// Represents a request header for unlocking a batch of message queues.
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct UnlockBatchMqRequestHeader {
    /// The RPC request header, if present.
    #[serde(flatten)]
    pub rpc_request_header: Option<RpcRequestHeader>,
}
rocketmq-client/src/consumer/consumer_impl/re_balance.rs (3)

Line range hint 47-51: Possible Redundancy in Function Name

The method remove_unnecessary_pop_message_queue_pop has "pop" repeated twice in its name, which may be redundant or a typo. Consider renaming it to remove_unnecessary_pop_message_queue or remove_unnecessary_pop_process_queue for clarity.


61-61: Inconsistent Return Types between compute_pull_from_where Methods

The method compute_pull_from_where_with_exception returns a Result<i64>, whereas compute_pull_from_where returns an i64 directly. For consistency and better error handling, consider having compute_pull_from_where also return a Result<i64>.


65-67: Inconsistent Asynchronicity Between Dispatch Methods

The method dispatch_pull_request is asynchronous (async fn), while dispatch_pop_pull_request is synchronous (fn). If both methods perform operations that could be asynchronous, consider making dispatch_pop_pull_request asynchronous for consistency and maintainability.

rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_push_impl.rs (1)

470-476: Use appropriate logging level for successful operations

In the success case of the unlock method, you are using warn! to log the message indicating a successful unlock:

warn!(
    "unlock messageQueue. group:{}, clientId:{}, mq:{}",
    self.rebalance_impl_inner.consumer_group.as_ref().unwrap(),
    client.client_id,
    mq
)

Logging successful operations at the warning level can be misleading. Consider using info! instead to indicate normal operation.

Apply this diff to change the logging level:

 } else {
-    warn!(
+    info!(
         "unlock messageQueue. group:{}, clientId:{}, mq:{}",
         self.rebalance_impl_inner.consumer_group.as_ref().unwrap(),
         client.client_id,
         mq
     )
 }
rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs (7)

20-20: Import DerefMut may not be necessary

The import use std::ops::DerefMut; is added, but it's only used once with deref_mut() in the code. Consider removing the explicit call to deref_mut() and use pattern matching or adjust the code to avoid needing this import if possible.


Line range hint 242-253: Check for proper lock acquisition in update_process_queue_table_in_rebalance

At line 242, the code attempts to lock message queues if is_order is true. The lock method is now asynchronous and modifies process_queue_table. Ensure that the mutable borrow of process_queue_table does not conflict with other borrows in the loop.

Consider restructuring the code to prevent mutable and immutable borrows from overlapping. Alternatively, move the lock acquisition outside the loop or collect the queues to lock and process them after releasing the write lock.


469-522: New method lock_all lacks error handling for broker unavailability

In the lock_all method, if find_broker_result is None, the code silently continues without logging or handling the error. This might make debugging broker connectivity issues difficult.

Consider adding a warning log when find_broker_result is None:

if let Some(find_broker_result) = find_broker_result {
    // existing code
} else {
    warn!(
        "Could not find broker address for broker: {}",
        broker_name
    );
}

445-463: Improve error handling in lock method

When handling the result of lock_batch_mq, the error case at lines 459-462 only logs the error but does not provide detailed context.

Enhance the error logging to include more context:

error!(
    "Failed to lock batch MQ for {:?} at broker {}: {}",
    self.consumer_group,
    find_broker_result.broker_addr,
    e
);

185-200: Incorrect logging level and message formatting

At lines 194-200, an error! macro is used for logging. The message seems to indicate an attempt to fix an issue rather than an actual error.

Consider changing the logging level to warn! and improving the message clarity.

-error!(
+warn!(
    "doRebalance, {:?}, removing unnecessary mq: {}, because pull is paused.",
    self.consumer_group,
    mq.get_topic()
);

Line range hint 242-253: Avoid holding write lock during asynchronous operations

At line 239, a write lock on process_queue_table is acquired. Inside the loop starting at line 241, asynchronous operations are performed, including calls to self.lock. Holding the write lock across awaits can lead to contention and potential deadlocks.

Refactor the code to minimize the time the write lock is held. Collect necessary data, release the lock, and then perform asynchronous operations.


469-522: Lack of timeout handling for lock_batch_mq requests

The lock_batch_mq method is called with a timeout of 1_000 milliseconds. If the broker does not respond in time, the method will fail silently for that broker.

Consider implementing retries or exponential backoff when a timeout occurs to improve reliability.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 190a50f and 1c7dbe0.

📒 Files selected for processing (14)
  • rocketmq-client/src/consumer/consumer_impl/process_queue.rs (5 hunks)
  • rocketmq-client/src/consumer/consumer_impl/re_balance.rs (2 hunks)
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs (5 hunks)
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_push_impl.rs (4 hunks)
  • rocketmq-client/src/implementation/mq_client_api_impl.rs (3 hunks)
  • rocketmq-remoting/src/protocol/body.rs (1 hunks)
  • rocketmq-remoting/src/protocol/body/request.rs (1 hunks)
  • rocketmq-remoting/src/protocol/body/request/lock_batch_request_body.rs (1 hunks)
  • rocketmq-remoting/src/protocol/body/response.rs (1 hunks)
  • rocketmq-remoting/src/protocol/body/response/lock_batch_response_body.rs (1 hunks)
  • rocketmq-remoting/src/protocol/body/unlock_batch_request_body.rs (1 hunks)
  • rocketmq-remoting/src/protocol/header.rs (2 hunks)
  • rocketmq-remoting/src/protocol/header/lock_batch_mq_request_header.rs (1 hunks)
  • rocketmq-remoting/src/protocol/header/unlock_batch_mq_request_header.rs (1 hunks)
🔇 Additional comments (24)
rocketmq-remoting/src/protocol/body/request.rs (1)

17-17: LGTM! New module added for batch locking requests.

The addition of the lock_batch_request_body module aligns with the PR objectives of optimizing and improving consume logic. This new module likely encapsulates functionality for handling batch lock requests, which could potentially improve efficiency in message queue management.

To ensure the proper implementation of this new module, please run the following verification script:

This script will help verify:

  1. The existence of the implementation file
  2. The basic structure of the LockBatchRequestBody
  3. Any usage of the new module in other parts of the codebase

Please review the results to ensure the new module is properly implemented and integrated.

✅ Verification successful

It seems there was an error in the verification script when checking for the implementation file. Let's correct the fd command and rerun the tests to ensure everything is in order.


Verification Successful 🚀

The lock_batch_request_body module is properly implemented and integrated into the codebase. The LockBatchRequestBody struct is correctly defined, and the module is actively used in the following locations:

  • rocketmq-client/src/implementation/mq_client_api_impl.rs
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs

All tests passed, and no issues were found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of the new lock_batch_request_body module

# Test 1: Check if the implementation file exists
echo "Checking for the implementation file..."
fd --type f --full-path "*/lock_batch_request_body.rs"

# Test 2: Verify the contents of the implementation file
echo "Checking the contents of the implementation file..."
rg --type rust "pub struct LockBatchRequestBody" -A 10

# Test 3: Check for any usage of the new module
echo "Checking for usage of the new module..."
rg --type rust "use .*lock_batch_request_body::LockBatchRequestBody"

Length of output: 2210


Script:

#!/bin/bash
# Description: Corrected verification of the new lock_batch_request_body module

# Test 1: Check if the implementation file exists
echo "Checking for the implementation file..."
fd --glob '*lock_batch_request_body.rs'

# Test 2: Verify the contents of the implementation file
echo "Checking the contents of the implementation file..."
rg --type rust "pub struct LockBatchRequestBody" -A 10

# Test 3: Check for any usage of the new module
echo "Checking for usage of the new module..."
rg --type rust "use .*lock_batch_request_body::LockBatchRequestBody"

Length of output: 2023

rocketmq-remoting/src/protocol/body/response.rs (2)

1-17: LGTM: License header is correctly included.

The Apache License 2.0 header is properly included at the beginning of the file, which is essential for maintaining compliance with open-source licensing requirements.


17-17: Verify the implementation of the new module.

The addition of the lock_batch_response_body module is a good step towards expanding the functionality for batch locking operations. However, it's important to ensure that the implementation of this module is complete and consistent with the project's standards.

To verify the implementation, please run the following script:

This script will help verify:

  1. The existence of the module file.
  2. The presence of expected structures or types within the module.
  3. The existence of related unit tests.

Please review the output of this script to ensure the module is properly implemented and tested.

rocketmq-remoting/src/protocol/body/response/lock_batch_response_body.rs (2)

1-16: LGTM: Appropriate license header included.

The file includes the correct Apache License, Version 2.0 header, which is essential for open-source projects and consistent with the RocketMQ project's licensing.


17-21: LGTM: Appropriate imports.

The imports are concise and relevant to the struct being defined:

  • HashSet from the standard library for the main field type.
  • MessageQueue from a custom module, likely representing the elements in the set.
  • Serialize and Deserialize traits from serde for JSON serialization/deserialization.

These imports provide all necessary types and traits for the struct's functionality.

rocketmq-remoting/src/protocol/body.rs (1)

33-34: Approved: New modules align with PR objectives. Please provide more context.

The addition of request, response, and unlock_batch_request_body modules aligns with the PR objectives to optimize and improve consume logic. These new modules likely introduce structures for enhanced request-response handling and batch unlocking operations, which could significantly improve the efficiency of message queue management.

To better understand the impact of these changes, could you please provide more information about the contents and purpose of these new modules? This will help ensure they integrate well with the existing codebase.

To verify the integration and usage of these new modules, please run the following script:

This script will help us understand how these new modules are being used throughout the codebase, ensuring they're properly integrated and not introducing any unintended side effects.

Also applies to: 37-37

✅ Verification successful

Verified: New modules are properly integrated and utilized within the codebase.

The request, response, and unlock_batch_request_body modules are being used appropriately in the following locations:

  • rocketmq-client/src/implementation/mq_client_api_impl.rs
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs
  • rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_push_impl.rs

No issues were found regarding the integration of these modules.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of new modules in the codebase

echo "Checking usage of new request module:"
rg --type rust -g '!src/protocol/body.rs' 'use .*protocol::body::request'

echo "Checking usage of new response module:"
rg --type rust -g '!src/protocol/body.rs' 'use .*protocol::body::response'

echo "Checking usage of new unlock_batch_request_body module:"
rg --type rust -g '!src/protocol/body.rs' 'use .*protocol::body::unlock_batch_request_body'

echo "Checking for any direct references to the new modules:"
rg --type rust -g '!src/protocol/body.rs' 'body::(request|response|unlock_batch_request_body)'

Length of output: 2331

rocketmq-remoting/src/protocol/body/request/lock_batch_request_body.rs (1)

1-45: LGTM! Well-structured and follows best practices.

The overall structure of the file is good, and it adheres to Rust best practices:

  • Appropriate license header is included.
  • Imports are well-organized and grouped.
  • The code follows Rust naming conventions.
  • The use of external crates and types is appropriate.
  • The visibility of the struct and its implementation is correctly set to public.
rocketmq-remoting/src/protocol/body/unlock_batch_request_body.rs (2)

1-16: LGTM: License header is correct and properly formatted.

The Apache License 2.0 header is present and correctly formatted at the beginning of the file.


17-22: LGTM: Imports are correct and well-organized.

The necessary imports from std, rocketmq_common, and serde are present and logically grouped. There are no unused imports.

rocketmq-remoting/src/protocol/header/unlock_batch_mq_request_header.rs (2)

1-24: LGTM: License and imports are correctly implemented.

The file includes the appropriate Apache 2.0 license header, and the import statements are well-organized and relevant to the functionality implemented in this file.


1-52: Overall assessment: Good implementation with room for minor improvements.

The UnlockBatchMqRequestHeader struct and its trait implementations provide a solid foundation for handling batch unlock requests in RocketMQ. The code is generally well-structured and follows Rust conventions.

To further enhance the quality of this implementation, consider:

  1. Adding documentation comments to explain the purpose and usage of the struct and its methods.
  2. Optimizing the to_map method in the CommandCustomHeader implementation for better efficiency.
  3. Improving error handling in the FromMap implementation to handle cases where RpcRequestHeader creation fails.

These improvements will make the code more robust, maintainable, and easier to use for other developers working on the project.

rocketmq-remoting/src/protocol/header.rs (3)

36-36: Request for additional context on batch locking/unlocking improvements.

The additions of lock_batch_mq_request_header and unlock_batch_mq_request_header modules suggest improvements in batch operations for message queue locking. However, the PR description lacks details about the specific enhancements these new modules bring.

Could you please provide more information on:

  1. The motivation behind introducing batch locking/unlocking.
  2. The expected performance improvements or other benefits.
  3. Any potential impacts on existing consume logic.

This context will help in better understanding the optimization efforts and their alignment with the project's goals.

Also applies to: 50-50


36-36: LGTM: New module for batch locking of message queues.

The addition of the lock_batch_mq_request_header module aligns with the PR objective of optimizing and improving consume logic. Its placement in the file follows the alphabetical order convention.

To ensure the module is properly implemented, please run the following script:

#!/bin/bash
# Description: Verify the implementation of the lock_batch_mq_request_header module

# Test: Check if the module file exists and contains expected content
rg --type rust -g 'lock_batch_mq_request_header.rs' -C 5 'struct LockBatchMqRequestHeader'

50-50: LGTM: New module for batch unlocking of message queues.

The addition of the unlock_batch_mq_request_header module complements the lock_batch_mq_request_header module and aligns with the PR objective of optimizing and improving consume logic. Its placement in the file follows the alphabetical order convention.

To ensure the module is properly implemented, please run the following script:

✅ Verification successful

Verified: unlock_batch_mq_request_header module is correctly implemented.

The unlock_batch_mq_request_header module contains the expected UnlockBatchMqRequestHeader struct, confirming its proper implementation and alignment with the project's objectives.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of the unlock_batch_mq_request_header module

# Test: Check if the module file exists and contains expected content
rg --type rust -g 'unlock_batch_mq_request_header.rs' -C 5 'struct UnlockBatchMqRequestHeader'

Length of output: 1256

rocketmq-client/src/consumer/consumer_impl/process_queue.rs (4)

128-130: LGTM: New method inc_try_unlock_times looks good.

The new inc_try_unlock_times method is a clean and thread-safe way to increment the try_unlock_times counter. It uses atomic operations, which is appropriate for this use case.


316-319: LGTM: New method set_last_lock_timestamp is well-implemented.

The set_last_lock_timestamp method is a clean and thread-safe way to update the last_lock_timestamp. It correctly uses an atomic store operation, which is appropriate for this concurrent scenario.


Line range hint 1-334: Summary: Changes align well with PR objectives.

The modifications in this file, including the switch to RocketMQTokioRwLock and the addition of methods for tracking unlock attempts and lock timestamps, are consistent with the PR's goal of optimizing and improving the consume logic. These changes enhance the locking mechanism and provide better management of concurrent operations, which should contribute to improved performance and reliability of the message consumption process.


33-33: Approve the change to RocketMQTokioRwLock and verify its impact.

The change from Arc<RwLock<()>> to Arc<RocketMQTokioRwLock<()>> for the consume_lock field is a good optimization for asynchronous operations. This custom lock is likely designed to work more efficiently with the Tokio runtime.

To ensure this change doesn't introduce any unexpected behavior, please run the following verification:

This will help identify any places where the standard RwLock is still being used, ensuring consistency across the codebase.

Also applies to: 60-60, 81-81

rocketmq-client/src/consumer/consumer_impl/re_balance.rs (1)

76-76: Updated Signature of unlock Requires Verification

The method unlock has been changed to be asynchronous and now takes &mut self instead of &self, and mq is now passed by reference &MessageQueue instead of by value MessageQueue. Ensure that all implementations of the RebalanceLocal trait and all calls to unlock are updated to match the new signature.

Run the following script to verify all usages of unlock:

✅ Verification successful

Verification Successful: All unlock Method Usages Are Correctly Updated

All implementations of the RebalanceLocal trait and calls to the unlock method have been updated to match the new asynchronous signature.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all implementations and calls of `unlock` that may need updating.

# Find all implementations of `RebalanceLocal` and inspect `unlock` method signatures.
rg --type rust 'impl.*RebalanceLocal' -A 20 | rg 'fn unlock'

# Find all calls to the `unlock` method.
rg --type rust 'unlock\('

Length of output: 635

rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_push_impl.rs (2)

20-20: Importing Duration for timeout handling

The addition of use std::time::Duration; is appropriate and necessary for handling timeouts when attempting to acquire locks.


32-32: Importing UnlockBatchRequestBody for unlock requests

The import of UnlockBatchRequestBody is essential for constructing unlock batch requests to the broker.

rocketmq-client/src/consumer/consumer_impl/re_balance/rebalance_impl.rs (3)

421-467: ⚠️ Potential issue

Modified lock method signature impacts existing implementations

The lock method signature has changed to:

pub async fn lock(
    &mut self,
    mq: &MessageQueue,
    process_queue_table: &mut HashMap<MessageQueue, Arc<ProcessQueue>>,
) -> bool

This modification requires updating all calls to lock to pass process_queue_table. Ensure that all callers are updated accordingly to prevent compilation errors.

Run the following script to find all usages of lock and verify they are updated:

#!/bin/bash
# Find all usages of the `lock` method
rg --type rust 'self\.lock\('

207-227: Potential race condition when modifying process_queue_table

When removing items from process_queue_table at lines 219-220, ensure that no other asynchronous tasks are modifying the same data concurrently without proper synchronization. Since the write lock is acquired, this should prevent concurrent writes, but verify that all accesses are properly synchronized.

Automate verification by checking all accesses to process_queue_table:

Ensure that all accesses are protected by appropriate locks.


421-467: Potential infinite recursion in lock method

The lock method calls client.get_broker_name_from_message_queue(mq).await, which may internally rely on methods that eventually call lock again, leading to potential infinite recursion.

Check the implementation of get_broker_name_from_message_queue to ensure it doesn't create a recursive loop.

Comment on lines 33 to 45
impl Display for LockBatchRequestBody {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"UnlockBatchRequestBody [consumer_group={}, client_id={}, only_this_broker={}, \
mq_set={:?}]",
self.consumer_group.as_ref().unwrap_or(&"".to_string()),
self.client_id.as_ref().unwrap_or(&"".to_string()),
self.only_this_broker,
self.mq_set
)
}
}
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

Fix incorrect struct name in Display implementation.

The Display implementation for LockBatchRequestBody is generally well-implemented. However, there's a minor issue in the output string:

The struct name in the output string is incorrect. It says "UnlockBatchRequestBody" instead of "LockBatchRequestBody". Please apply the following fix:

-            "UnlockBatchRequestBody [consumer_group={}, client_id={}, only_this_broker={}, \
+            "LockBatchRequestBody [consumer_group={}, client_id={}, only_this_broker={}, \
             mq_set={:?}]",

This will ensure that the string representation accurately reflects the struct name.

📝 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
impl Display for LockBatchRequestBody {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"UnlockBatchRequestBody [consumer_group={}, client_id={}, only_this_broker={}, \
mq_set={:?}]",
self.consumer_group.as_ref().unwrap_or(&"".to_string()),
self.client_id.as_ref().unwrap_or(&"".to_string()),
self.only_this_broker,
self.mq_set
)
}
}
impl Display for LockBatchRequestBody {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"LockBatchRequestBody [consumer_group={}, client_id={}, only_this_broker={}, \
mq_set={:?}]",
self.consumer_group.as_ref().unwrap_or(&"".to_string()),
self.client_id.as_ref().unwrap_or(&"".to_string()),
self.only_this_broker,
self.mq_set
)
}
}

Comment on lines +45 to +52
impl FromMap for LockBatchMqRequestHeader {
type Target = Self;

fn from(map: &HashMap<String, String>) -> Option<Self::Target> {
let rpc_request_header = <RpcRequestHeader as FromMap>::from(map);
Some(LockBatchMqRequestHeader { rpc_request_header })
}
}
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

Improve error handling and consistency with to_map.

While the implementation of FromMap for LockBatchMqRequestHeader is functional, there are opportunities for improvement:

  1. Error Handling: The current implementation always returns Some(...), even if RpcRequestHeader::from returns None. This could lead to unexpected behavior.

  2. Consistency: The to_map method returns None for an empty map (after the suggested improvement), but from always returns Some(...). This inconsistency could be confusing.

Consider the following implementation to address these issues:

impl FromMap for LockBatchMqRequestHeader {
    type Target = Self;

    fn from(map: &HashMap<String, String>) -> Option<Self::Target> {
        if map.is_empty() {
            None
        } else {
            Some(LockBatchMqRequestHeader {
                rpc_request_header: <RpcRequestHeader as FromMap>::from(map),
            })
        }
    }
}

This implementation:

  1. Returns None if the input map is empty, maintaining consistency with the to_map method.
  2. Preserves the Option returned by RpcRequestHeader::from, allowing for better error handling downstream.

Comment on lines +33 to +43
impl CommandCustomHeader for UnlockBatchMqRequestHeader {
fn to_map(&self) -> Option<HashMap<String, String>> {
let mut map = HashMap::new();
if let Some(value) = self.rpc_request_header.as_ref() {
if let Some(value) = value.to_map() {
map.extend(value);
}
}
Some(map)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider optimizing the to_map method implementation.

The current implementation of to_map is functional but can be improved for better efficiency and idiomatic Rust.

Consider refactoring the to_map method as follows:

impl CommandCustomHeader for UnlockBatchMqRequestHeader {
    fn to_map(&self) -> Option<HashMap<String, String>> {
        self.rpc_request_header
            .as_ref()
            .and_then(|header| header.to_map())
    }
}

This implementation:

  1. Directly returns None if rpc_request_header is None.
  2. Only creates a HashMap if rpc_request_header is Some and its to_map method returns Some.
  3. Avoids creating an empty HashMap when it's not needed.

Comment on lines +45 to +52
impl FromMap for UnlockBatchMqRequestHeader {
type Target = Self;

fn from(map: &HashMap<String, String>) -> Option<Self::Target> {
let rpc_request_header = <RpcRequestHeader as FromMap>::from(map);
Some(UnlockBatchMqRequestHeader { rpc_request_header })
}
}
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

Improve error handling in the FromMap implementation.

The current implementation of from always returns Some, which might not be appropriate for all cases.

Consider refactoring the from method to handle potential errors:

impl FromMap for UnlockBatchMqRequestHeader {
    type Target = Self;

    fn from(map: &HashMap<String, String>) -> Option<Self::Target> {
        let rpc_request_header = <RpcRequestHeader as FromMap>::from(map);
        // Only create the UnlockBatchMqRequestHeader if RpcRequestHeader was successfully created
        rpc_request_header.map(|header| UnlockBatchMqRequestHeader {
            rpc_request_header: Some(header),
        })
    }
}

This implementation:

  1. Only creates an UnlockBatchMqRequestHeader if RpcRequestHeader was successfully created from the map.
  2. Returns None if RpcRequestHeader couldn't be created, which is more appropriate for error cases.

@@ -53,22 +54,34 @@ pub trait RebalanceLocal {
}

fn consume_type(&self) -> ConsumeType;

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

Consider Changing &self to &mut self in remove_dirty_offset

The method remove_dirty_offset may modify internal state when removing offsets. If this is the case, it should take a mutable reference &mut self instead of an immutable reference &self to reflect that it mutates the receiver.

use rocketmq_common::WeakCellWrapper;
use rocketmq_remoting::protocol::body::request::lock_batch_request_body::LockBatchRequestBody;
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

Unused import LockBatchRequestBody

The import LockBatchRequestBody is added but not used in the code provided. If it's intended for future use, consider adding a comment explaining its purpose. Otherwise, remove the unused import.

Apply this diff to remove the unused import:

-use rocketmq_remoting::protocol::body::request::lock_batch_request_body::LockBatchRequestBody;
📝 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
use rocketmq_remoting::protocol::body::request::lock_batch_request_body::LockBatchRequestBody;

Comment on lines 524 to 538
async fn build_process_queue_table_by_broker_name(
&self,
) -> HashMap<String /* brokerName */, HashSet<MessageQueue>> {
let mut result = HashMap::new();
let process_queue_table = self.process_queue_table.read().await;
let client = self.client_instance.as_ref().unwrap();
for (mq, pq) in process_queue_table.iter() {
if pq.is_dropped() {
continue;
}
let broker_name = client.get_broker_name_from_message_queue(mq).await;
let entry = result.entry(broker_name).or_insert(HashSet::new());
entry.insert(mq.clone());
}
result
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Inefficient cloning in build_process_queue_table_by_broker_name

At line 536, message queues are cloned and inserted into a HashSet. If MessageQueue implements Copy, cloning can be avoided. If not, consider if it's necessary to clone here or if references can be used instead.

Adjust the code to avoid unnecessary cloning:

- entry.insert(mq.clone());
+ entry.insert(mq.to_owned());

Ensure that to_owned() is implemented efficiently for MessageQueue.

Committable suggestion was skipped due to low confidence.

Comment on lines +1045 to +1083
pub async fn unlock_batch_mq(
&mut self,
addr: &str,
request_body: UnlockBatchRequestBody,
timeout_millis: u64,
oneway: bool,
) -> Result<()> {
let mut request = RemotingCommand::create_request_command(
RequestCode::UnlockBatchMq,
UnlockBatchMqRequestHeader::default(),
);
request.set_body_mut_ref(Some(request_body.encode()));
if oneway {
self.remoting_client
.invoke_oneway(addr.to_string(), request, timeout_millis)
.await;
Ok(())
} else {
let response = self
.remoting_client
.invoke_async(
Some(mix_all::broker_vip_channel(
self.client_config.vip_channel_enabled,
addr,
)),
request,
timeout_millis,
)
.await?;
if ResponseCode::from(response.code()) == ResponseCode::Success {
Ok(())
} else {
Err(MQBrokerError(
response.code(),
response.remark().map_or("".to_string(), |s| s.to_string()),
addr.to_string(),
))
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor to reduce code duplication in unlock_batch_mq

Both branches of the if oneway condition in unlock_batch_mq share similar logic for creating the request and handling the response. Consider refactoring to reduce code duplication and improve maintainability.

You could extract the common request creation into a separate function or reorganize the code to minimize repetition.

Comment on lines 1109 to 1111
LockBatchResponseBody::decode(response.body().as_ref().unwrap().as_ref())
.map(|body| body.lock_ok_mq_set)
.map_err(|e| MQBrokerError(response.code(), e.to_string(), addr.to_string()))
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

Avoid potential panic due to unwrap() on response.body()

In lock_batch_mq, the call to response.body().as_ref().unwrap() may panic if response.body() is None. This can happen if the response does not contain a body, leading to a runtime panic.

To prevent a potential panic, you should check if response.body() is Some before attempting to use it. Handle the None case appropriately.

Apply this diff:

-        LockBatchResponseBody::decode(response.body().as_ref().unwrap().as_ref())
+        if let Some(body) = response.body() {
+            LockBatchResponseBody::decode(body.as_ref())
                 .map(|body| body.lock_ok_mq_set)
                 .map_err(|e| MQBrokerError(response.code(), e.to_string(), addr.to_string()))
+        } else {
+            Err(MQBrokerError(
+                response.code(),
+                "Response body is empty".to_string(),
+                addr.to_string(),
+            ))
+        }
📝 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
LockBatchResponseBody::decode(response.body().as_ref().unwrap().as_ref())
.map(|body| body.lock_ok_mq_set)
.map_err(|e| MQBrokerError(response.code(), e.to_string(), addr.to_string()))
if let Some(body) = response.body() {
LockBatchResponseBody::decode(body.as_ref())
.map(|body| body.lock_ok_mq_set)
.map_err(|e| MQBrokerError(response.code(), e.to_string(), addr.to_string()))
} else {
Err(MQBrokerError(
response.code(),
"Response body is empty".to_string(),
addr.to_string(),
))
}

Comment on lines +1058 to +1060
self.remoting_client
.invoke_oneway(addr.to_string(), request, timeout_millis)
.await;
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

Handle errors from invoke_oneway in unlock_batch_mq

In the oneway branch of unlock_batch_mq, the result of invoke_oneway is awaited, but any potential errors are not being handled. This could lead to unhandled errors if the method fails.

To properly handle errors, you should propagate the error by using await?, so that any errors are returned to the caller.

Apply this diff:

             self.remoting_client
-                .invoke_oneway(addr.to_string(), request, timeout_millis)
-                .await;
+                .invoke_oneway(addr.to_string(), request, timeout_millis)
+                .await?;
             Ok(())
📝 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
self.remoting_client
.invoke_oneway(addr.to_string(), request, timeout_millis)
.await;
self.remoting_client
.invoke_oneway(addr.to_string(), request, timeout_millis)
.await?;
Ok(())

⚠️ Potential issue

Ensure consistent use of VIP channel in invoke_oneway

In the oneway branch, invoke_oneway is called with addr.to_string(), while in the else branch, invoke_async uses mix_all::broker_vip_channel to potentially adjust the address based on the VIP channel configuration. This inconsistency may cause issues when vip_channel_enabled is true.

Consider modifying the invoke_oneway call to use mix_all::broker_vip_channel for consistent address handling.

Apply this diff:

             self.remoting_client
-                .invoke_oneway(addr.to_string(), request, timeout_millis)
+                .invoke_oneway(
+                    mix_all::broker_vip_channel(self.client_config.vip_channel_enabled, addr),
+                    request,
+                    timeout_millis,
+                )
                 .await?;
             Ok(())
📝 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
self.remoting_client
.invoke_oneway(addr.to_string(), request, timeout_millis)
.await;
self.remoting_client
.invoke_oneway(
mix_all::broker_vip_channel(self.client_config.vip_channel_enabled, addr),
request,
timeout_millis,
)
.await;

@mxsm
Copy link
Owner Author

mxsm commented Sep 27, 2024

🚀Thanks for your contribution🎉. CodeRabbit(AI) will review your code first🔥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Enhancement⚡️] optimize and improve consume logic
2 participants