Repository: mxsm/rocketmq-rust
Pull request #3092: [ISSUE #3091]♻️Refactor Channel💫
Author: login: mxsm
Labels: name: refactor♻️
description: refactor code
name: approved
description: PR has approved
name: auto merge
name: AI review first
description: Ai review pr first
Created: 2025-04-11T15:18:07Z | Merged: 2025-04-11T15:22:59Z

<!-- Please make sure the target branch is right. In most case, the target branch should be `main`. -->

### Which Issue(s) This PR Fixes(Closes)

<!-- Please ensure that the related issue has already been created, and [link this pull request to that issue using keywords](<https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword>) to ensure automatic closure. -->

Fixes #3091

### Brief Description

<!-- Write a brief description for your pull request to help the maintainer understand the reasons behind your changes. -->

### How Did You Test This Change?

<!-- In order to ensure the code quality of Apache RocketMQ Rust, we expect every pull request to have undergone thorough testing. -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Refactor**
  - Enhanced network channel handling to improve connection stability and reliability.
  - Streamlined logging across consumer, producer, and messaging events for clearer, less verbose notifications.
  - Improved error handling during message processing and long polling to ensure operations proceed only when connections are valid.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #3091: [Refactor♻️]Refactor Channel
### Which part of the code will be refactored?

_No response_

### What problems does the refactor aim to solve?

_No response_

### Do you have any specific design or implementation considerations?

_No response_

### Is there a related issue or PR?

_No response_

### Checklist

- [ ] Ensure the refactor does not introduce new bugs

- [ ] Update unit tests if applicable

- [ ] Ensure the refactor does not negatively impact performance

- [ ] Document any new patterns or architecture changes

- [ ] Test the refactor in different environments (e.g., staging, production)


Diff:
diff --git a/rocketmq-broker/src/client/client_channel_info.rs b/rocketmq-broker/src/client/client_channel_info.rs
index 96d1356de..e1e4d4f2f 100644
--- a/rocketmq-broker/src/client/client_channel_info.rs
+++ b/rocketmq-broker/src/client/client_channel_info.rs
@@ -19,7 +19,7 @@ use rocketmq_common::TimeUtils::get_current_millis;
 use rocketmq_remoting::net::channel::Channel;
 use rocketmq_remoting::protocol::LanguageCode;
 
-#[derive(Debug, Clone, Hash, PartialEq)]
+#[derive(Clone, Hash, PartialEq)]
 pub struct ClientChannelInfo {
     channel: Channel,
     client_id: CheetahString,
diff --git a/rocketmq-broker/src/client/consumer_group_info.rs b/rocketmq-broker/src/client/consumer_group_info.rs
index 85c107f66..3ac48435e 100644
--- a/rocketmq-broker/src/client/consumer_group_info.rs
+++ b/rocketmq-broker/src/client/consumer_group_info.rs
@@ -32,7 +32,7 @@ use tracing::warn;
 
 use crate::client::client_channel_info::ClientChannelInfo;
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct ConsumerGroupInfo {
     group_name: CheetahString,
     subscription_table: Arc<DashMap<CheetahString, SubscriptionData>>,
@@ -130,9 +130,9 @@ impl ConsumerGroupInfo {
     pub fn handle_channel_close_event(&self, channel: &Channel) -> Option<ClientChannelInfo> {
         if let Some((_, info)) = self.channel_info_table.remove(channel) {
             warn!(
-                "NETTY EVENT: remove not active channel [{:?}] from ConsumerGroupInfo \
+                "NETTY EVENT: remove not active channel [{}] from ConsumerGroupInfo \
                  groupChannelTable, consumer group: {}",
-                info.channel(),
+                info.channel().remote_address(),
                 self.group_name
             );
             Some(info)
@@ -172,9 +172,9 @@ impl ConsumerGroupInfo {
             self.channel_info_table
                 .insert(info_new.channel().clone(), info_new.clone());
             info!(
-                "New consumer connected, group: {} channel: {:?}",
+                "New consumer connected, group: {} channel: {}",
                 self.group_name,
-                info_new.channel()
+                info_new.channel().remote_address()
             );
             updated = true;
         }
diff --git a/rocketmq-broker/src/client/manager/producer_manager.rs b/rocketmq-broker/src/client/manager/producer_manager.rs
index 3cba41989..5042d8c27 100644
--- a/rocketmq-broker/src/client/manager/producer_manager.rs
+++ b/rocketmq-broker/src/client/manager/producer_manager.rs
@@ -77,7 +77,7 @@ impl ProducerManager {
     pub fn unregister_producer(
         &self,
         group: &str,
-        client_channel_info: &ClientChannelInfo,
+        _client_channel_info: &ClientChannelInfo,
         ctx: &ConnectionHandlerContext,
     ) {
         let mut mutex_guard = self.group_channel_table.lock();
@@ -87,10 +87,11 @@ impl ProducerManager {
                 let old = ct.remove(ctx.channel());
                 //let old = ct.remove(client_channel_info.channel());
                 if old.is_some() {
-                    info!(
+                    /*info!(
                         "unregister a producer[{}] from groupChannelTable {:?}",
                         group, client_channel_info
-                    );
+                    );*/
+                    info!("unregister a producer[{}] from groupChannelTable", group);
                 }
             }
             if ct.is_empty() {
diff --git a/rocketmq-broker/src/client/net/broker_to_client.rs b/rocketmq-broker/src/client/net/broker_to_client.rs
index 96ee6cbcd..032ed4434 100644
--- a/rocketmq-broker/src/client/net/broker_to_client.rs
+++ b/rocketmq-broker/src/client/net/broker_to_client.rs
@@ -36,9 +36,14 @@ impl Broker2Client {
         request: RemotingCommand,
         timeout_millis: u64,
     ) -> Result<RemotingCommand> {
-        match channel.send_wait_response(request, timeout_millis).await {
-            Ok(value) => Ok(value),
-            Err(e) => Err(BrokerRemotingError(e)),
+        match channel.upgrade() {
+            None => {
+                unimplemented!("channel is closed");
+            }
+            Some(mut channel) => match channel.send_wait_response(request, timeout_millis).await {
+                Ok(value) => Ok(value),
+                Err(e) => Err(BrokerRemotingError(e)),
+            },
         }
     }
 
@@ -61,9 +66,14 @@ impl Broker2Client {
                 return Err(BrokerCommonError(e));
             }
         }
-        match channel.send_one_way(request, 100).await {
-            Ok(_) => Ok(()),
-            Err(e) => Err(BrokerRemotingError(e)),
+        match channel.upgrade() {
+            None => {
+                unimplemented!("channel is closed");
+            }
+            Some(channel) => match channel.send_one_way(request, 100).await {
+                Ok(_) => Ok(()),
+                Err(e) => Err(BrokerRemotingError(e)),
+            },
         }
     }
 }
diff --git a/rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs b/rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs
index 74cf951ac..020c940f1 100644
--- a/rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs
+++ b/rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs
@@ -480,10 +480,11 @@ impl<MS: MessageStore, RP: RequestProcessor + Sync + 'static> PopLongPollingServ
                     match response {
                         Ok(result) => {
                             if let Some(response) = result {
-                                let _ = pop_request
-                                    .get_channel()
-                                    .send_one_way(response.set_opaque(opaque), 1000)
-                                    .await;
+                                if let Some(channel) = pop_request.get_channel().upgrade() {
+                                    let _ = channel
+                                        .send_one_way(response.set_opaque(opaque), 1000)
+                                        .await;
+                                }
                             }
                         }
                         Err(e) => {
@@ -519,7 +520,14 @@ impl<MS: MessageStore, RP: RequestProcessor + Sync + 'static> PopLongPollingServ
             }
 
             self.total_polling_num.fetch_sub(1, Ordering::AcqRel);
-            if pop_request.is_some() && !pop_request.as_ref().unwrap().get_channel().is_ok() {
+            if pop_request.is_some()
+                && !pop_request
+                    .as_ref()
+                    .unwrap()
+                    .get_channel()
+                    .upgrade()
+                    .is_some_and(|item| item.is_ok())
+            {
                 continue;
             } else {
                 break;
diff --git a/rocketmq-broker/src/long_polling/long_polling_service/pull_request_hold_service.rs b/rocketmq-broker/src/long_polling/long_polling_service/pull_request_hold_service.rs
index 43caa2192..ee4eb1a05 100644
--- a/rocketmq-broker/src/long_polling/long_polling_service/pull_request_hold_service.rs
+++ b/rocketmq-broker/src/long_polling/long_polling_service/pull_request_hold_service.rs
@@ -234,8 +234,8 @@ where
             if let Some(request_list) = mpr.clone_list_and_clear() {
                 for request in request_list {
                     info!(
-                        "notify master online, wakeup {} {}",
-                        request.client_channel(),
+                        "notify master online, wakeup {}",
+                        //  request.client_channel(),
                         request.request_command()
                     );
                     let pull_message_this = self.pull_message_processor.clone();
diff --git a/rocketmq-broker/src/processor/default_pull_message_result_handler.rs b/rocketmq-broker/src/processor/default_pull_message_result_handler.rs
index eb51bea31..a9736bca7 100644
--- a/rocketmq-broker/src/processor/default_pull_message_result_handler.rs
+++ b/rocketmq-broker/src/processor/default_pull_message_result_handler.rs
@@ -91,7 +91,7 @@ impl<MS: MessageStore> PullMessageResultHandler for DefaultPullMessageResultHand
         mut get_message_result: GetMessageResult,
         request: RemotingCommand,
         request_header: PullMessageRequestHeader,
-        mut channel: Channel,
+        channel: Channel,
         ctx: ConnectionHandlerContext,
         subscription_data: SubscriptionData,
         subscription_group_config: SubscriptionGroupConfig,
@@ -193,14 +193,16 @@ impl<MS: MessageStore> PullMessageResultHandler for DefaultPullMessageResultHand
                     Some(response)
                 } else {
                     //zero copy transfer
-                    if let Some(header_bytes) = response.encode_header_with_body_length(
-                        get_message_result.buffer_total_size() as usize,
-                    ) {
-                        let _ = channel.connection_mut().send_bytes(header_bytes).await;
-                    }
-                    for select_result in get_message_result.message_mapped_list_mut() {
-                        if let Some(message) = select_result.bytes.take() {
-                            let _ = channel.connection_mut().send_bytes(message).await;
+                    if let Some(mut channel) = channel.upgrade() {
+                        if let Some(header_bytes) = response.encode_header_with_body_length(
+                            get_message_result.buffer_total_size() as usize,
+                        ) {
+                            let _ = channel.connection_mut().send_bytes(header_bytes).await;
+                        }
+                        for select_result in get_message_result.message_mapped_list_mut() {
+                            if let Some(message) = select_result.bytes.take() {
+                                let _ = channel.connection_mut().send_bytes(message).await;
+                            }
                         }
                     }
                     None
diff --git a/rocketmq-broker/src/processor/pop_message_processor.rs b/rocketmq-broker/src/processor/pop_message_processor.rs
index a9ae414dd..24aba9b6f 100644
--- a/rocketmq-broker/src/processor/pop_message_processor.rs
+++ b/rocketmq-broker/src/processor/pop_message_processor.rs
@@ -184,7 +184,7 @@ where
 {
     pub async fn _process_request(
         &mut self,
-        mut channel: Channel,
+        channel: Channel,
         ctx: ConnectionHandlerContext,
         request_code: RequestCode,
         mut request: RemotingCommand,
@@ -761,14 +761,16 @@ where
                     Ok(Some(final_response))
                 } else {
                     //zero copy transfer
-                    if let Some(header_bytes) = final_response.encode_header_with_body_length(
-                        get_message_result.buffer_total_size() as usize,
-                    ) {
-                        channel.connection_mut().send_bytes(header_bytes).await?;
-                    }
-                    for select_result in get_message_result.message_mapped_list_mut() {
-                        if let Some(message) = select_result.bytes.take() {
-                            channel.connection_mut().send_bytes(message).await?;
+                    if let Some(mut channel) = channel.upgrade() {
+                        if let Some(header_bytes) = final_response.encode_header_with_body_length(
+                            get_message_result.buffer_total_size() as usize,
+                        ) {
+                            channel.connection_mut().send_bytes(header_bytes).await?;
+                        }
+                        for select_result in get_message_result.message_mapped_list_mut() {
+                            if let Some(message) = select_result.bytes.take() {
+                                channel.connection_mut().send_bytes(message).await?;
+                            }
                         }
                     }
                     Ok(None)
diff --git a/rocketmq-client/src/implementation/client_remoting_processor.rs b/rocketmq-client/src/implementation/client_remoting_processor.rs
index 0ab29c50a..228b98bdd 100644
--- a/rocketmq-client/src/implementation/client_remoting_processor.rs
+++ b/rocketmq-client/src/implementation/client_remoting_processor.rs
@@ -204,6 +204,7 @@ impl ClientRemotingProcessor {
         let request_header = request
             .decode_command_custom_header::<NotifyConsumerIdsChangedRequestHeader>()
             .unwrap();
+
         info!(
             "receive broker's notification[{}], the consumer group: {} changed, rebalance \
              immediately",
diff --git a/rocketmq-remoting/src/clients/client.rs b/rocketmq-remoting/src/clients/client.rs
index 469b5ee07..29b4094fd 100644
--- a/rocketmq-remoting/src/clients/client.rs
+++ b/rocketmq-remoting/src/clients/client.rs
@@ -26,6 +26,7 @@ use crate::base::response_future::ResponseFuture;
 use crate::code::response_code::ResponseCode;
 use crate::connection::Connection;
 use crate::net::channel::Channel;
+use crate::net::channel::ChannelInner;
 use crate::protocol::remoting_command::RemotingCommand;
 use crate::protocol::RemotingCommandType;
 use crate::remoting_error::RemotingError::ConnectionInvalid;
@@ -52,7 +53,7 @@ pub struct Client {
 
 struct ClientInner {
     response_table: ArcMut<HashMap<i32, ResponseFuture>>,
-    channel: Channel,
+    channel: (ArcMut<ChannelInner>, Channel),
     ctx: ConnectionHandlerContext,
     tx: tokio::sync::mpsc::Sender<SendMessage>,
 }
@@ -70,14 +71,14 @@ async fn run_send(mut client: ArcMut<ClientInner>, mut rx: Receiver<SendMessage>
 }
 
 async fn run_recv<PR: RequestProcessor>(mut client: ArcMut<ClientInner>, mut processor: PR) {
-    while let Some(response) = client.ctx.channel.connection.receive_command().await {
+    while let Some(response) = client.channel.0.connection.receive_command().await {
         match response {
             Ok(msg) => match msg.get_type() {
                 // handle request
                 RemotingCommandType::REQUEST => {
                     let opaque = msg.opaque();
                     let process_result = processor
-                        .process_request(client.channel.clone(), client.ctx.clone(), msg)
+                        .process_request(client.channel.1.clone(), client.ctx.clone(), msg)
                         .await;
                     match process_result {
                         Ok(response) => {
@@ -107,14 +108,14 @@ async fn run_recv<PR: RequestProcessor>(mut client: ArcMut<ClientInner>, mut pro
                         warn!(
                             "receive response, cmd={}, but not matched any request, address={}",
                             msg,
-                            client.channel.remote_address()
+                            client.channel.0.remote_address()
                         )
                     }
                 }
             },
             Err(error) => match error {
                 Io(value) => {
-                    client.ctx.channel.connection.ok = false;
+                    client.channel.0.connection.ok = false;
                     error!("error: {:?}", value);
                     return;
                 }
@@ -145,13 +146,19 @@ impl ClientInner {
         let remote_address = stream.peer_addr()?;
         let connection = Connection::new(stream);
         let response_table = ArcMut::new(HashMap::with_capacity(128));
-        let channel = Channel::new(
+        let channel_inner = ArcMut::new(ChannelInner::new(
             local_addr,
             remote_address,
             connection,
             response_table.clone(),
+        ));
+        let weak_channel = ArcMut::downgrade(&channel_inner);
+        let channel = Channel::new(
+            weak_channel,
+            local_addr,
+            remote_address,
+            channel_inner.channel_id().into(),
         );
-
         let (tx_, rx) = tokio::sync::mpsc::channel(1024);
         let client = ClientInner {
             ctx: ArcMut::new(ConnectionHandlerContextWrapper::new(
@@ -159,7 +166,7 @@ impl ClientInner {
                 channel.clone(),
             )),
             response_table,
-            channel,
+            channel: (channel_inner, channel),
             tx: tx_.clone(),
         };
         let client = ArcMut::new(client);
@@ -168,7 +175,7 @@ impl ClientInner {
         tokio::spawn(run_send(client.clone(), rx));
         if let Some(tx) = tx {
             let _ = tx.send(ConnectionNetEvent::CONNECTED(
-                client.channel.remote_address(),
+                client.channel.0.remote_address(),
                 //client.channel.clone(),
             ));
         }
@@ -188,12 +195,12 @@ impl ClientInner {
                 ResponseFuture::new(opaque, timeout_millis.unwrap_or(0), true, tx),
             );
         }
-        match self.ctx.channel.connection.send_command(request).await {
+        match self.channel.0.connection.send_command(request).await {
             Ok(_) => Ok(()),
             Err(error) => match error {
                 Io(value) => {
                     self.response_table.remove(&opaque);
-                    self.ctx.channel.connection.ok = false;
+                    self.channel.0.connection.ok = false;
                     Err(ConnectionInvalid(value.to_string()))
                 }
                 _ => {
@@ -224,13 +231,6 @@ impl Client {
         T: tokio::net::ToSocketAddrs,
         PR: RequestProcessor + 'static,
     {
-        /*let tcp_stream = tokio::net::TcpStream::connect(addr).await;
-        if tcp_stream.is_err() {
-            return Err(Io(tcp_stream.err().unwrap()));
-        }
-        Ok(Client {
-            connection: Connection::new(tcp_stream?),
-        })*/
         let (tx, inner) = ClientInner::connect(addr, processor, tx).await?;
         Ok(Client {
             //connection: inner.connection.clone(),
@@ -321,16 +321,16 @@ impl Client {
     /// The `RemotingCommand` representing the response, wrapped in a `Result`. Returns an error if
     /// reading the response fails.
     async fn read(&mut self) -> Result<RemotingCommand> {
-        match self.inner.ctx.channel.connection.receive_command().await {
+        match self.inner.channel.0.connection.receive_command().await {
             None => {
-                self.inner.ctx.channel.connection.ok = false;
+                self.inner.channel.0.connection.ok = false;
                 Err(ConnectionInvalid("connection disconnection".to_string()))
             }
             Some(result) => match result {
                 Ok(response) => Ok(response),
                 Err(error) => match error {
                     Io(value) => {
-                        self.inner.ctx.channel.connection.ok = false;
+                        self.inner.channel.0.connection.ok = false;
                         Err(ConnectionInvalid(value.to_string()))
                     }
                     _ => Err(error),
@@ -340,10 +340,10 @@ impl Client {
     }
 
     pub fn connection(&self) -> &Connection {
-        self.inner.ctx.channel.connection_ref()
+        self.inner.channel.0.connection_ref()
     }
 
     pub fn connection_mut(&mut self) -> &mut Connection {
-        self.inner.ctx.channel.connection_mut()
+        self.inner.channel.0.connection_mut()
     }
 }
diff --git a/rocketmq-remoting/src/net/channel.rs b/rocketmq-remoting/src/net/channel.rs
index 6b70ee8b3..6cb54002c 100644
--- a/rocketmq-remoting/src/net/channel.rs
+++ b/rocketmq-remoting/src/net/channel.rs
@@ -23,7 +23,9 @@ use std::net::SocketAddr;
 use std::sync::Arc;
 use std::time::Duration;
 
+use cheetah_string::CheetahString;
 use rocketmq_rust::ArcMut;
+use rocketmq_rust::WeakArcMut;
 use tokio::sync::mpsc::Receiver;
 use tokio::time::timeout;
 use tracing::error;
@@ -37,11 +39,50 @@ use crate::remoting_error::RemotingError::ChannelSendRequestFailed;
 use crate::remoting_error::RemotingError::Io;
 use crate::Result;
 
-#[derive(Clone)]
+#[derive(Clone, Eq, PartialEq, Hash)]
 pub struct Channel {
+    inner: WeakArcMut<ChannelInner>,
     local_address: SocketAddr,
     remote_address: SocketAddr,
-    channel_id: String,
+    channel_id: CheetahString,
+}
+
+impl Channel {
+    pub fn new(
+        inner: WeakArcMut<ChannelInner>,
+        local_address: SocketAddr,
+        remote_address: SocketAddr,
+        channel_id: CheetahString,
+    ) -> Self {
+        Self {
+            inner,
+            local_address,
+            remote_address,
+            channel_id,
+        }
+    }
+
+    pub fn local_address(&self) -> SocketAddr {
+        self.local_address
+    }
+
+    pub fn remote_address(&self) -> SocketAddr {
+        self.remote_address
+    }
+
+    pub fn upgrade(&self) -> Option<ArcMut<ChannelInner>> {
+        self.inner.upgrade()
+    }
+
+    pub fn channel_id(&self) -> &CheetahString {
+        &self.channel_id
+    }
+}
+
+pub struct ChannelInner {
+    local_address: SocketAddr,
+    remote_address: SocketAddr,
+    channel_id: CheetahString,
     tx: tokio::sync::mpsc::Sender<ChannelMessage>,
     pub(crate) connection: ArcMut<Connection>,
     pub(crate) response_table: ArcMut<HashMap<i32, ResponseFuture>>,
@@ -83,7 +124,7 @@ pub(crate) async fn run_send(
     }
 }
 
-impl PartialEq for Channel {
+impl PartialEq for ChannelInner {
     fn eq(&self, other: &Self) -> bool {
         self.local_address == other.local_address
             && self.remote_address == other.remote_address
@@ -96,9 +137,9 @@ impl PartialEq for Channel {
     }
 }
 
-impl Eq for Channel {}
+impl Eq for ChannelInner {}
 
-impl Hash for Channel {
+impl Hash for ChannelInner {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.local_address.hash(state);
         self.remote_address.hash(state);
@@ -108,7 +149,7 @@ impl Hash for Channel {
     }
 }
 
-impl Debug for Channel {
+impl Debug for ChannelInner {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(
             f,
@@ -118,7 +159,7 @@ impl Debug for Channel {
     }
 }
 
-impl Display for Channel {
+impl Display for ChannelInner {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(
             f,
@@ -128,14 +169,14 @@ impl Display for Channel {
     }
 }
 
-impl Channel {
+impl ChannelInner {
     pub fn new(
         local_address: SocketAddr,
         remote_address: SocketAddr,
         connection: Connection,
         response_table: ArcMut<HashMap<i32, ResponseFuture>>,
     ) -> Self {
-        let channel_id = Uuid::new_v4().to_string();
+        let channel_id = Uuid::new_v4().to_string().into();
         let (tx, rx) = tokio::sync::mpsc::channel(1024);
         //let response_table = ArcMut::new(HashMap::with_capacity(32));
         let connection = ArcMut::new(connection);
@@ -151,7 +192,7 @@ impl Channel {
     }
 }
 
-impl Channel {
+impl ChannelInner {
     #[inline]
     pub fn set_local_address(&mut self, local_address: SocketAddr) {
         self.local_address = local_address;
@@ -163,8 +204,8 @@ impl Channel {
     }
 
     #[inline]
-    pub fn set_channel_id(&mut self, channel_id: String) {
-        self.channel_id = channel_id;
+    pub fn set_channel_id(&mut self, channel_id: impl Into<CheetahString>) {
+        self.channel_id = channel_id.into();
     }
 
     #[inline]
@@ -255,36 +296,3 @@ impl Channel {
         self.connection.ok
     }
 }
-
-#[cfg(test)]
-mod tests {
-
-    #[test]
-    fn channel_creation_with_new() {
-        /*let local_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-        let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)), 8080);
-        let channel = Channel::new(local_address, remote_address);
-
-        assert_eq!(channel.local_address(), local_address);
-        assert_eq!(channel.remote_address(), remote_address);
-        assert!(Uuid::parse_str(channel.channel_id()).is_ok());*/
-    }
-
-    #[test]
-    fn channel_setters_work_correctly() {
-        /* let local_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-        let remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)), 8080);
-        let new_local_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)), 8080);
-        let new_remote_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1)), 8080);
-        let new_channel_id = Uuid::new_v4().to_string();
-
-        let mut channel = Channel::new(local_address, remote_address);
-        channel.set_local_address(new_local_address);
-        channel.set_remote_address(new_remote_address);
-        channel.set_channel_id(new_channel_id.clone());
-
-        assert_eq!(channel.local_address(), new_local_address);
-        assert_eq!(channel.remote_address(), new_remote_address);
-        assert_eq!(channel.channel_id(), new_channel_id);*/
-    }
-}
diff --git a/rocketmq-remoting/src/remoting_server/server.rs b/rocketmq-remoting/src/remoting_server/server.rs
index 10206b808..5c7ff7a4e 100644
--- a/rocketmq-remoting/src/remoting_server/server.rs
+++ b/rocketmq-remoting/src/remoting_server/server.rs
@@ -38,6 +38,7 @@ use crate::base::response_future::ResponseFuture;
 use crate::code::response_code::ResponseCode;
 use crate::connection::Connection;
 use crate::net::channel::Channel;
+use crate::net::channel::ChannelInner;
 use crate::protocol::remoting_command::RemotingCommand;
 use crate::protocol::RemotingCommandType;
 use crate::remoting_error::RemotingError;
@@ -59,7 +60,7 @@ type Rx = mpsc::UnboundedReceiver<RemotingCommand>;
 pub struct ConnectionHandler<RP> {
     request_processor: RP,
     connection_handler_context: ConnectionHandlerContext,
-    channel: Channel,
+    channel_inner: (ArcMut<ChannelInner>, Channel),
     shutdown: Shutdown,
     _shutdown_complete: mpsc::Sender<()>,
     conn_disconnect_notify: Option<broadcast::Sender<SocketAddr>>,
@@ -70,7 +71,7 @@ pub struct ConnectionHandler<RP> {
 impl<RP> Drop for ConnectionHandler<RP> {
     fn drop(&mut self) {
         if let Some(ref sender) = self.conn_disconnect_notify {
-            let socket_addr = self.channel.remote_address();
+            let socket_addr = self.channel_inner.0.remote_address();
             warn!(
                 "connection[{}] disconnected, Send notify message.",
                 socket_addr
@@ -83,7 +84,7 @@ impl<RP> Drop for ConnectionHandler<RP> {
 impl<RP> ConnectionHandler<RP> {
     pub fn do_before_rpc_hooks(
         &self,
-        channel: &Channel,
+        channel: &ChannelInner,
         request: Option<&mut RemotingCommand>,
     ) -> Result<()> {
         if let Some(request) = request {
@@ -96,7 +97,7 @@ impl<RP> ConnectionHandler<RP> {
 
     pub fn do_after_rpc_hooks(
         &self,
-        channel: &Channel,
+        channel: &ChannelInner,
         response: Option<&mut RemotingCommand>,
     ) -> Result<()> {
         if let Some(response) = response {
@@ -113,10 +114,10 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
         while !self.shutdown.is_shutdown {
             //Get the next frame from the connection.
             let frame = tokio::select! {
-                res = self.connection_handler_context.channel.connection.receive_command() => res,
+                res = self.channel_inner.0.connection.receive_command() => res,
                 _ = self.shutdown.recv() =>{
                     //If a shutdown signal is received, return from `handle`.
-                    self.channel.connection_mut().ok = false;
+                    self.channel_inner.0.connection_mut().ok = false;
                     return Ok(());
                 }
             };
@@ -137,7 +138,7 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
                     warn!(
                         "receive response, cmd={}, but not matched any request, address={}",
                         cmd,
-                        self.connection_handler_context.channel.remote_address()
+                        self.channel_inner.0.remote_address()
                     )
                 }
                 continue;
@@ -147,7 +148,7 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
             //before handle request hooks
 
             let exception = self
-                .do_before_rpc_hooks(&self.channel, Some(&mut cmd))
+                .do_before_rpc_hooks(&(self.channel_inner.0), Some(&mut cmd))
                 .err();
             //handle error if return have
             match self.handle_error(oneway_rpc, opaque, exception).await {
@@ -157,7 +158,7 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
             }
 
             let mut response = {
-                let channel = self.channel.clone();
+                let channel = self.channel_inner.1.clone();
                 let ctx = self.connection_handler_context.clone();
                 tokio::select! {
                     result = self.request_processor.process_request(channel,ctx,cmd) =>  match result{
@@ -170,7 +171,7 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
             };
 
             let exception = self
-                .do_before_rpc_hooks(&self.channel, response.as_mut())
+                .do_after_rpc_hooks(&self.channel_inner.0, response.as_mut())
                 .err();
 
             match self.handle_error(oneway_rpc, opaque, exception).await {
@@ -183,7 +184,7 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
             }
             let response = response.unwrap();
             tokio::select! {
-                result =self.connection_handler_context.channel.connection.send_command(response.set_opaque(opaque)) => match result{
+                result =self.channel_inner.0.connection.send_command(response.set_opaque(opaque)) => match result{
                     Ok(_) =>{},
                     Err(err) => {
                         match err {
@@ -215,7 +216,7 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
                     let response =
                         RemotingCommand::create_response_command_with_code_remark(code, message);
                     tokio::select! {
-                        result =self.connection_handler_context.channel.connection.send_command(response.set_opaque(opaque)) => match result{
+                        result =self.channel_inner.0.connection.send_command(response.set_opaque(opaque)) => match result{
                             Ok(_) =>{},
                             Err(err) => {
                                 match err {
@@ -236,7 +237,7 @@ impl<RP: RequestProcessor + Sync + 'static> ConnectionHandler<RP> {
                             exception_inner.to_string(),
                         );
                         tokio::select! {
-                            result =self.connection_handler_context.channel.connection.send_command(response.set_opaque(opaque)) => match result{
+                            result =self.channel_inner.0.connection.send_command(response.set_opaque(opaque)) => match result{
                                 Ok(_) =>{},
                                 Err(err) => {
                                     match err {
@@ -313,21 +314,26 @@ impl<RP: RequestProcessor + Sync + 'static + Clone> ConnectionListener<RP> {
             socket.set_nodelay(true).expect("set nodelay failed");
 
             let response_table = ArcMut::new(HashMap::with_capacity(128));
-            let channel = Channel::new(
+            let channel_inner = ArcMut::new(ChannelInner::new(
                 socket.local_addr()?,
                 remote_addr,
                 Connection::new(socket),
                 response_table.clone(),
-            );
+            ));
             //create per connection handler state
+            let weak_channel = ArcMut::downgrade(&channel_inner);
+            let channel = Channel::new(
+                weak_channel,
+                channel_inner.local_address(),
+                channel_inner.remote_address(),
+                channel_inner.channel_id().into(),
+            );
             let mut handler = ConnectionHandler {
                 request_processor: self.request_processor.clone(),
-                //connection: Connection::new(socket, remote_addr),
                 connection_handler_context: ArcMut::new(ConnectionHandlerContextWrapper {
-                    // connection: Connection::new(socket),
                     channel: channel.clone(),
                 }),
-                channel,
+                channel_inner: (channel_inner, channel),
                 shutdown: Shutdown::new(self.notify_shutdown.subscribe()),
                 _shutdown_complete: self.shutdown_complete_tx.clone(),
                 conn_disconnect_notify: self.conn_disconnect_notify.clone(),
diff --git a/rocketmq-remoting/src/runtime/connection_handler_context.rs b/rocketmq-remoting/src/runtime/connection_handler_context.rs
index 6fe005699..6231aeddd 100644
--- a/rocketmq-remoting/src/runtime/connection_handler_context.rs
+++ b/rocketmq-remoting/src/runtime/connection_handler_context.rs
@@ -39,15 +39,24 @@ impl ConnectionHandlerContextWrapper {
         }
     }
 
-    pub fn connection(&self) -> &Connection {
-        self.channel.connection_ref()
+    pub fn connection(&self) -> Option<&Connection> {
+        /*match self.channel.upgrade() {
+            None => None,
+            Some(channel) => Some(channel.connection_ref()),
+        }*/
+        unimplemented!("connection() is not implemented");
     }
 
     pub async fn write(&mut self, cmd: RemotingCommand) {
-        match self.channel.connection_mut().send_command(cmd).await {
-            Ok(_) => {}
-            Err(error) => {
-                error!("send response failed: {}", error);
+        match self.channel.upgrade() {
+            Some(mut channel) => match channel.connection_mut().send_command(cmd).await {
+                Ok(_) => {}
+                Err(error) => {
+                    error!("send response failed: {}", error);
+                }
+            },
+            None => {
+                error!("channel is closed");
             }
         }
     }


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.


<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**rocketmq-broker/src/long_polling/long_polling_service/pull_request_hold_service.rs:237**
* [nitpick] The updated log message omits the client channel details that were previously displayed. Consider restoring relevant details if they are important for debugging.
```
"notify master online, wakeup {}",
```
**rocketmq-broker/src/client/manager/producer_manager.rs:90**
* [nitpick] Commenting out the detailed log message removes useful context for troubleshooting producer unregistration. Consider either removing the commented code entirely or ensuring that critical channel details are logged.
```
/*info!("unregister a producer[{}] from groupChannelTable {:?}", group, client_channel_info);*/
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T15:19:22Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 6**

<details>
<summary>📜 Review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between abf247ca943e60071c437b201cb7d84edfecba98 and 986cbf29cd2dadb015e06fb4f2e8c836d4055f4f.

</details>

<details>
<summary>📒 Files selected for processing (13)</summary>

* `rocketmq-broker/src/client/client_channel_info.rs` (1 hunks)
* `rocketmq-broker/src/client/consumer_group_info.rs` (3 hunks)
* `rocketmq-broker/src/client/manager/producer_manager.rs` (2 hunks)
* `rocketmq-broker/src/client/net/broker_to_client.rs` (2 hunks)
* `rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs` (2 hunks)
* `rocketmq-broker/src/long_polling/long_polling_service/pull_request_hold_service.rs` (1 hunks)
* `rocketmq-broker/src/processor/default_pull_message_result_handler.rs` (2 hunks)
* `rocketmq-broker/src/processor/pop_message_processor.rs` (2 hunks)
* `rocketmq-client/src/implementation/client_remoting_processor.rs` (1 hunks)
* `rocketmq-remoting/src/clients/client.rs` (9 hunks)
* `rocketmq-remoting/src/net/channel.rs` (9 hunks)
* `rocketmq-remoting/src/remoting_server/server.rs` (14 hunks)
* `rocketmq-remoting/src/runtime/connection_handler_context.rs` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (6)</summary>

<details>
<summary>rocketmq-remoting/src/runtime/connection_handler_context.rs (3)</summary><blockquote>

<details>
<summary>rocketmq-remoting/src/clients/client.rs (1)</summary>

* `connection` (342-344)

</details>
<details>
<summary>rocketmq-remoting/src/net/channel.rs (1)</summary>

* `connection` (227-229)

</details>
<details>
<summary>rocketmq-broker/src/client/client_channel_info.rs (1)</summary>

* `channel` (79-81)

</details>

</blockquote></details>
<details>
<summary>rocketmq-broker/src/client/consumer_group_info.rs (2)</summary><blockquote>

<details>
<summary>rocketmq-broker/src/client/client_channel_info.rs (1)</summary>

* `channel` (79-81)

</details>
<details>
<summary>rocketmq-remoting/src/net/channel.rs (2)</summary>

* `remote_address` (69-71)
* `remote_address` (217-219)

</details>

</blockquote></details>
<details>
<summary>rocketmq-broker/src/processor/pop_message_processor.rs (2)</summary><blockquote>

<details>
<summary>rocketmq-broker/src/client/client_channel_info.rs (1)</summary>

* `channel` (79-81)

</details>
<details>
<summary>rocketmq-remoting/src/runtime/connection_handler_context.rs (1)</summary>

* `channel` (64-66)

</details>

</blockquote></details>
<details>
<summary>rocketmq-remoting/src/clients/client.rs (3)</summary><blockquote>

<details>
<summary>rocketmq-remoting/src/protocol/remoting_command.rs (1)</summary>

* `opaque` (609-611)

</details>
<details>
<summary>rocketmq-remoting/src/net/channel.rs (5)</summary>

* `remote_address` (69-71)
* `remote_address` (217-219)
* `new` (51-63)
* `new` (173-192)
* `connection` (227-229)

</details>
<details>
<summary>rocketmq-remoting/src/connection.rs (1)</summary>

* `new` (101-110)

</details>

</blockquote></details>
<details>
<summary>rocketmq-remoting/src/remoting_server/server.rs (5)</summary><blockquote>

<details>
<summary>rocketmq-remoting/src/runtime/connection_handler_context.rs (2)</summary>

* `channel` (64-66)
* `connection` (42-48)

</details>
<details>
<summary>rocketmq-remoting/src/clients/client.rs (2)</summary>

* `connection` (342-344)
* `connection_mut` (346-348)

</details>
<details>
<summary>rocketmq-remoting/src/net/channel.rs (4)</summary>

* `connection` (227-229)
* `connection_mut` (237-239)
* `remote_address` (69-71)
* `remote_address` (217-219)

</details>
<details>
<summary>rocketmq-remoting/src/connection.rs (2)</summary>

* `receive_command` (127-129)
* `send_command` (140-151)

</details>
<details>
<summary>rocketmq-remoting/src/protocol/remoting_command.rs (2)</summary>

* `set_opaque` (287-290)
* `opaque` (609-611)

</details>

</blockquote></details>
<details>
<summary>rocketmq-remoting/src/net/channel.rs (5)</summary><blockquote>

<details>
<summary>rocketmq-broker/src/client/client_channel_info.rs (1)</summary>

* `new` (32-45)

</details>
<details>
<summary>rocketmq-remoting/src/runtime/connection_handler_context.rs (2)</summary>

* `new` (35-40)
* `connection` (42-48)

</details>
<details>
<summary>rocketmq-remoting/src/connection.rs (1)</summary>

* `new` (101-110)

</details>
<details>
<summary>rocketmq-remoting/src/protocol/body/broker_body/register_broker_body.rs (1)</summary>

* `new` (49-57)

</details>
<details>
<summary>rocketmq-remoting/src/clients/client.rs (1)</summary>

* `connection` (342-344)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (9)</summary>

* GitHub Check: auto-approve
* GitHub Check: build (windows-latest, nightly)
* GitHub Check: build (windows-latest, stable)
* GitHub Check: build (macos-latest, nightly)
* GitHub Check: build (ubuntu-latest, stable)
* GitHub Check: build
* GitHub Check: build (macos-latest, stable)
* GitHub Check: build (ubuntu-latest, nightly)
* GitHub Check: test

</details>

<details>
<summary>🔇 Additional comments (48)</summary><blockquote>

<details>
<summary>rocketmq-client/src/implementation/client_remoting_processor.rs (1)</summary>

`207-213`: **Well placed logging for consumer IDs change notification**

Adding this logging statement provides valuable operational insight by capturing when broker notifications are received for consumer group changes. This helps with debugging rebalance events during runtime.

</details>
<details>
<summary>rocketmq-broker/src/client/client_channel_info.rs (1)</summary>

`22-22`: <details>
<summary>❓ Verification inconclusive</summary>

**Removed Debug trait from ClientChannelInfo struct**

Removing the `Debug` trait from this struct is part of the channel refactoring. This change will prevent automatic generation of debug representations for this struct, which is consistent with similar changes in other structs like `ConsumerGroupInfo`.

However, you may need a custom `Debug` implementation if logging or debugging this struct is required elsewhere.


---

🏁 Script executed:

```shell
#!/bin/bash
# Verify if there are any remaining usages of debug formatting for ClientChannelInfo
# that might be broken by removing the Debug trait

rg -A 1 'ClientChannelInfo.*\{:?\}' --type rust
```

Length of output: 49

---



</details>

**ClientChannelInfo Debug Trait Removal – Manual Verification Advised**

- The `Debug` trait has been removed from `ClientChannelInfo` in line 22 of `rocketmq-broker/src/client/client_channel_info.rs` as part of the channel refactoring, aligning with similar changes (e.g., in `ConsumerGroupInfo`).
- An initial automated search using the pattern `'ClientChannelInfo.*\{:?\}'` produced no output, which suggests no direct debug formatting usages were detected. However, given the low-confidence result from this check, please perform thorough manual verification to ensure that no logging or debugging code paths depend on the auto-generated `Debug` implementation.
- If runtime debugging information is still needed for `ClientChannelInfo`, consider implementing a custom `Debug` trait.

</details>
<details>
<summary>rocketmq-broker/src/long_polling/long_polling_service/pull_request_hold_service.rs (1)</summary>

`237-240`: **Simplified logging by removing client_channel details**

This change streamlines logging by only including the request command and removing the client channel details. This is consistent with the overall effort to simplify channel-related logging across the codebase.

</details>
<details>
<summary>rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs (1)</summary>

`523-529`: **Enhanced channel validation logic in poll_remoting_commands.**

The code now correctly upgrades the channel and verifies its validity before proceeding. This strengthens error handling and prevents operations on invalid channels.

The combination of `upgrade()` with `is_some_and(|item| item.is_ok())` provides a more robust check than the previous `is_active()` method.

</details>
<details>
<summary>rocketmq-broker/src/client/consumer_group_info.rs (3)</summary>

`35-36`: **Removed Debug trait from ConsumerGroupInfo struct.**

Removing the `Debug` trait simplifies the struct's representation and prevents potentially large and complex debug outputs when logging instances of this struct.

This aligns with the overall channel refactoring approach in the PR, focusing on more concise and relevant information.

---

`133-136`: **Improved log message clarity by using remote_address instead of debug format.**

The log message now displays the channel's remote address directly instead of the debug representation of the entire channel object. This makes logs more readable and focused on the relevant connection information.

---

`175-177`: **Enhanced log formatting for new consumer connections.**

Similar to the previous log change, this update provides clearer information by displaying the remote address instead of the debug representation of the channel.

This provides more useful information for debugging connection issues.

</details>
<details>
<summary>rocketmq-remoting/src/runtime/connection_handler_context.rs (1)</summary>

`51-61`: **Significantly improved error handling in write method.**

The method now properly checks if the channel can be upgraded before attempting to send commands, and includes proper error handling.

This is a substantial improvement in error handling and makes the code more robust by:
1. Verifying the channel state before use
2. Properly handling and logging different error scenarios

</details>
<details>
<summary>rocketmq-broker/src/client/manager/producer_manager.rs (2)</summary>

`80-80`: **Marked unused parameter with underscore prefix.**

The parameter `client_channel_info` has been renamed to `_client_channel_info` to indicate it's unused within the method.

This follows Rust's naming convention for unused parameters.

---

`90-95`: **Simplified log message by removing client_channel_info debug output.**

The log statement has been updated to remove the debug output of the client_channel_info object, focusing solely on the essential group name information.

This change improves log clarity and aligns with the other logging improvements across the codebase.

</details>
<details>
<summary>rocketmq-broker/src/processor/pop_message_processor.rs (1)</summary>

`187-187`: **Changed parameter from mutable to immutable**

The `_process_request` method now takes an immutable `channel` parameter instead of a mutable one, which aligns with the new channel architecture that uses the `upgrade()` method instead of direct mutation.

</details>
<details>
<summary>rocketmq-remoting/src/clients/client.rs (7)</summary>

`29-29`: **Added import for new ChannelInner structure**

The addition of `ChannelInner` import supports the architectural changes made to the channel handling.

---

`74-74`: **Updated channel references to use inner structure**

All channel method calls now access the inner structure correctly via the tuple's first element. This ensures proper utilization of the new channel architecture.



Also applies to: 111-111, 118-118

---

`149-161`: **Restructured channel creation process**

The `connect` method now creates a `ChannelInner` instance first, then obtains a weak reference and creates a `Channel` with that reference. This change implements the separation of concerns between the channel interface and its implementation details.

---

`169-169`: **Updated channel assignment to use the new tuple structure**

The `channel` field is now initialized with the tuple containing both the inner structure and the interface.

---

`198-198`: **Updated send method to use inner structure**

The `send` method now accesses the connection through the inner structure. This aligns with the architectural changes.



Also applies to: 203-203

---

`324-334`: **Updated read method to use inner structure**

The `read` method now accesses the connection through the inner structure. This maintains consistency with the rest of the refactoring.

---

`343-347`: **Updated accessor methods to use inner structure**

The `connection` and `connection_mut` methods now delegate to the inner structure's methods. This provides a clean interface while implementing the new architecture.

</details>
<details>
<summary>rocketmq-remoting/src/remoting_server/server.rs (12)</summary>

`41-41`: **Added import for ChannelInner struct**

The addition of the `ChannelInner` import supports the architectural changes in the server implementation.

---

`63-63`: **Refactored ConnectionHandler to use channel inner structure**

The `ConnectionHandler` now uses a tuple of `(ArcMut<ChannelInner>, Channel)` instead of just `Channel`. This aligns with the client implementation and supports the new channel architecture.

---

`74-74`: **Updated Drop implementation to access channel through inner structure**

The `Drop` implementation now retrieves the remote address from the inner structure, maintaining consistency with the architectural changes.

---

`87-87`: **Updated hook methods to use ChannelInner parameter**

The `do_before_rpc_hooks` and `do_after_rpc_hooks` methods now accept a reference to `ChannelInner` instead of `Channel`, allowing them to work with the new architecture.



Also applies to: 100-100

---

`117-121`: **Updated handle method to access connection through inner structure**

The `handle` method now uses `channel_inner.0` to access the connection and check for received commands. This aligns with the architectural changes.

---

`141-141`: **Updated log statement to use inner structure for remote address**

Log statements now access the remote address through the inner structure. This maintains consistency with the architectural changes.

---

`151-151`: **Updated hook call to pass inner structure reference**

The call to `do_before_rpc_hooks` now passes a reference to the inner structure. This aligns with the updated method signature.

---

`161-161`: **Used channel from tuple for processor request**

The code correctly uses `channel_inner.1` for the `process_request` call, which requires a `Channel` instance rather than the inner structure.

---

`174-174`: **Updated hook call to pass inner structure reference**

The call to `do_after_rpc_hooks` now passes a reference to the inner structure. This aligns with the updated method signature.

---

`187-187`: **Updated send methods to use inner structure**

All calls to `send_command` now use the inner structure to access the connection. This maintains consistency with the architectural changes.



Also applies to: 219-219, 240-240

---

`317-330`: **Restructured channel creation in ConnectionListener**

The `run` method now creates a `ChannelInner` instance first, obtains a weak reference, and then creates a `Channel` with that reference. This implements the new channel architecture in the server component.

---

`336-336`: **Updated ConnectionHandler initialization to use new tuple structure**

The `channel_inner` field is now initialized with both the inner structure and the interface. This aligns with the updated struct definition.

</details>
<details>
<summary>rocketmq-broker/src/processor/default_pull_message_result_handler.rs (2)</summary>

`94-94`: **Changed channel parameter from mutable to immutable**

The `handle` method now takes an immutable `channel` parameter instead of a mutable one, aligning with the new channel architecture that uses the `upgrade()` method instead of direct mutation.

---

`196-206`: **Improved error handling with channel upgrade check**

The code now safely checks if the channel can be upgraded before attempting to use it. This prevents potential null pointer exceptions or failures when the channel is invalid.

</details>
<details>
<summary>rocketmq-remoting/src/net/channel.rs (16)</summary>

`26-28`: **Importing `CheetahString` and `WeakArcMut`.**

No immediate concerns here. The introduction of `CheetahString` presumably boosts performance over standard `String` in certain operations, and `WeakArcMut` indicates a design choice to hold a non-owning reference to `ChannelInner`.

---

`42-48`: **Switching to `WeakArcMut<ChannelInner>` and `CheetahString` fields.**

By storing the `ChannelInner` in a `WeakArcMut`, you allow upgrading to a strong reference only when needed. This helps avoid retain cycles but requires careful handling of `None` cases if the strong reference is dropped. Also note that you are deriving `Eq` and `PartialEq` on `Channel`, which, given the weak reference, might be tricky if the underlying strong reference is collected.  

Please confirm that all call sites handle a potential `None` return from upgrading the weak reference, avoiding panics or unwrapped `None` values.

---

`50-62`: **New constructor sets channel fields consistently.**

The constructor correctly initializes all fields, including `channel_id` with the provided `CheetahString`. This appears straightforward and correct, given the new architecture.

---

`65-67`: **Getter for `local_address`.**

This is a simple and clear getter returning an owned `SocketAddr`, matching the stored field.

---

`69-71`: **Getter for `remote_address`.**

Similarly straightforward. No concerns here.

---

`73-75`: **`upgrade()` method returning `Option<ArcMut<ChannelInner>>`.**

This method could return `None` if the `WeakArcMut` has been dropped. Ensure you handle that in all calling code to avoid unexpected errors.  

Would you like to verify that all usage points do proper `unwrap_or` or `match` handling for the `None` case?

---

`77-79`: **Getter for `channel_id` in `Channel`.**

No issues. Returning a reference to `CheetahString` is efficient.

---

`82-85`: **New fields added to `ChannelInner`.**

The transition of `local_address`, `remote_address`, and `channel_id` here is consistent with the new architecture, centralizing the true channel state in `ChannelInner`.

---

`127-137`: **Custom `PartialEq` for `ChannelInner`.**

Pointer equality on `connection` and `response_table` ensures that two `ChannelInner` objects are only equal if they share the exact same underlying objects, not just identical field data. Verify this is the intended behavior, as it’s stricter than typical field-based equality.  

Do you want to confirm or refine the partial equality approach to handle references more flexibly?

---

`140-140`: **`impl Eq for ChannelInner`.**

Given your `PartialEq` implementation, declaring `Eq` is appropriate if you have no additional constraints.

---

`142-149`: **Implementing `Hash` for `ChannelInner`.**

Similar to `PartialEq`, hashing pointer addresses ensures that objects are only considered matching if they literally share the same `Arc` pointers. This is valid if your use cases revolve around the actual identity of these fields rather than mere field-level data.

---

`152-160`: **`Debug` implementation.**

Provides a straightforward representation of essential fields. Looks good.

---

`162-170`: **`Display` implementation.**

Mirrors the `Debug` implementation but uses a more user-facing format. No issues.

---

`172-193`: **Constructor spawns `run_send` task for concurrency.**

This pattern is suitable for asynchronous message sending. If the spawned task encounters an IO error, it sets `connection.ok` to false and returns, effectively stopping future sends. Ensure that higher-level code properly detects and recovers from this situation.  

Would you like to confirm that the calling code verifies when the background task exits, or reinitializes the channel if needed?

---

`179-179`: **Using UUID to generate `channel_id`.**

Generating a unique ID on creation is consistent with establishing distinct channel identities.

---

`207-208`: **Setter for `channel_id` in `ChannelInner`.**

Accepting any type convertible into `CheetahString` enhances flexibility. No concerns here.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T15:22:22Z
user: login: rocketmq-rust-bot
body: LGTM
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-11T15:22:49Z

Review comments:
diff_hunk: @@ -39,15 +39,24 @@ impl ConnectionHandlerContextWrapper {
         }
     }
 
-    pub fn connection(&self) -> &Connection {
-        self.channel.connection_ref()
+    pub fn connection(&self) -> Option<&Connection> {
+        /*match self.channel.upgrade() {
+            None => None,
+            Some(channel) => Some(channel.connection_ref()),
+        }*/
+        unimplemented!("connection() is not implemented");
path: rocketmq-remoting/src/runtime/connection_handler_context.rs
user: login: Copilot
body: The connection() method is currently unimplemented, which will cause a panic if called. Consider providing an actual implementation or updating its documentation to clarify its intended usage.
```suggestion
        match self.channel.upgrade() {
            None => None,
            Some(channel) => channel.connection_ref(),
        }
```
created_at: 2025-04-11T15:19:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -761,14 +761,16 @@ where
                     Ok(Some(final_response))
                 } else {
                     //zero copy transfer
-                    if let Some(header_bytes) = final_response.encode_header_with_body_length(
-                        get_message_result.buffer_total_size() as usize,
-                    ) {
-                        channel.connection_mut().send_bytes(header_bytes).await?;
-                    }
-                    for select_result in get_message_result.message_mapped_list_mut() {
-                        if let Some(message) = select_result.bytes.take() {
-                            channel.connection_mut().send_bytes(message).await?;
+                    if let Some(mut channel) = channel.upgrade() {
path: rocketmq-broker/src/processor/pop_message_processor.rs
user: login: Copilot
body: The code silently ignores the case where channel.upgrade() fails. Consider adding an else branch to log or handle the failure case to avoid silent drops.
created_at: 2025-04-11T15:19:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -36,9 +36,14 @@ impl Broker2Client {
         request: RemotingCommand,
         timeout_millis: u64,
     ) -> Result<RemotingCommand> {
-        match channel.send_wait_response(request, timeout_millis).await {
-            Ok(value) => Ok(value),
-            Err(e) => Err(BrokerRemotingError(e)),
+        match channel.upgrade() {
+            None => {
+                unimplemented!("channel is closed");
path: rocketmq-broker/src/client/net/broker_to_client.rs
user: login: Copilot
body: Using unimplemented! when the channel upgrade fails may lead to unexpected panics. Consider returning a proper error instead of panicking when the channel is closed.
```suggestion
                return Err(BrokerRemotingError("channel is closed".into()));
```
created_at: 2025-04-11T15:19:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -61,9 +66,14 @@
                 return Err(BrokerCommonError(e));
             }
         }
-        match channel.send_one_way(request, 100).await {
-            Ok(_) => Ok(()),
-            Err(e) => Err(BrokerRemotingError(e)),
+        match channel.upgrade() {
+            None => {
+                unimplemented!("channel is closed");
+            }
+            Some(channel) => match channel.send_one_way(request, 100).await {
+                Ok(_) => Ok(()),
+                Err(e) => Err(BrokerRemotingError(e)),
+            },
         }
path: rocketmq-broker/src/client/net/broker_to_client.rs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Similar channel upgrade issue in transaction state check**

As with the previous method, the upgrade check is a good addition, but the `unimplemented!` macro should be replaced with proper error handling.


```diff
-        match channel.upgrade() {
-            None => {
-                unimplemented!("channel is closed");
-            }
-            Some(channel) => match channel.send_one_way(request, 100).await {
-                Ok(_) => Ok(()),
-                Err(e) => Err(BrokerRemotingError(e)),
-            },
-        }
+        let Some(upgraded_channel) = channel.upgrade() else {
+            return Err(BrokerRemotingError("Channel is closed or invalid".into()));
+        };
+        
+        match upgraded_channel.send_one_way(request, 100).await {
+            Ok(_) => Ok(()),
+            Err(e) => Err(BrokerRemotingError(e)),
+        }
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
        let Some(upgraded_channel) = channel.upgrade() else {
            return Err(BrokerRemotingError("Channel is closed or invalid".into()));
        };
        
        match upgraded_channel.send_one_way(request, 100).await {
            Ok(_) => Ok(()),
            Err(e) => Err(BrokerRemotingError(e)),
        }
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-11T15:22:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -36,9 +36,14 @@
         request: RemotingCommand,
         timeout_millis: u64,
     ) -> Result<RemotingCommand> {
-        match channel.send_wait_response(request, timeout_millis).await {
-            Ok(value) => Ok(value),
-            Err(e) => Err(BrokerRemotingError(e)),
+        match channel.upgrade() {
+            None => {
+                unimplemented!("channel is closed");
+            }
+            Some(mut channel) => match channel.send_wait_response(request, timeout_millis).await {
+                Ok(value) => Ok(value),
+                Err(e) => Err(BrokerRemotingError(e)),
+            },
         }
path: rocketmq-broker/src/client/net/broker_to_client.rs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Improved channel handling with upgrade check**

The added channel upgrade check enhances robustness by validating the channel before usage. However, using `unimplemented!` for a closed channel isn't ideal as it suggests missing functionality rather than an error condition.


Consider replacing with proper error handling:

```diff
-        match channel.upgrade() {
-            None => {
-                unimplemented!("channel is closed");
-            }
-            Some(mut channel) => match channel.send_wait_response(request, timeout_millis).await {
-                Ok(value) => Ok(value),
-                Err(e) => Err(BrokerRemotingError(e)),
-            },
-        }
+        let Some(mut upgraded_channel) = channel.upgrade() else {
+            return Err(BrokerRemotingError("Channel is closed or invalid".into()));
+        };
+        
+        match upgraded_channel.send_wait_response(request, timeout_millis).await {
+            Ok(value) => Ok(value),
+            Err(e) => Err(BrokerRemotingError(e)),
+        }
```

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-11T15:22:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -480,10 +480,11 @@
                     match response {
                         Ok(result) => {
                             if let Some(response) = result {
-                                let _ = pop_request
-                                    .get_channel()
-                                    .send_one_way(response.set_opaque(opaque), 1000)
-                                    .await;
+                                if let Some(channel) = pop_request.get_channel().upgrade() {
+                                    let _ = channel
+                                        .send_one_way(response.set_opaque(opaque), 1000)
+                                        .await;
+                                }
path: rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Improved channel safety with upgrade check before sending response.**

The code now properly checks if the channel can be upgraded before attempting to send the response. This enhances error handling and prevents potential issues with invalid channels.

However, you might want to add error logging when the upgrade fails:

```diff
if let Some(channel) = pop_request.get_channel().upgrade() {
    let _ = channel
        .send_one_way(response.set_opaque(opaque), 1000)
        .await;
+} else {
+    error!("Channel upgrade failed when sending response");
}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
                                if let Some(channel) = pop_request.get_channel().upgrade() {
                                    let _ = channel
                                        .send_one_way(response.set_opaque(opaque), 1000)
                                        .await;
                                } else {
                                    error!("Channel upgrade failed when sending response");
                                }
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-11T15:22:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -39,15 +39,24 @@
         }
     }
 
-    pub fn connection(&self) -> &Connection {
-        self.channel.connection_ref()
+    pub fn connection(&self) -> Option<&Connection> {
+        /*match self.channel.upgrade() {
+            None => None,
+            Some(channel) => Some(channel.connection_ref()),
+        }*/
+        unimplemented!("connection() is not implemented");
     }
path: rocketmq-remoting/src/runtime/connection_handler_context.rs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Method signature changed but implementation is unimplemented.**

The `connection()` method has been modified to return `Option<&Connection>` instead of `&Connection`, but the implementation is marked as unimplemented with commented-out code.

This is potentially dangerous if any code in the codebase still calls this method. Either:

1. Implement the method properly:
```diff
pub fn connection(&self) -> Option<&Connection> {
-    /*match self.channel.upgrade() {
-        None => None,
-        Some(channel) => Some(channel.connection_ref()),
-    }*/
-    unimplemented!("connection() is not implemented");
+    match self.channel.upgrade() {
+        None => None,
+        Some(channel) => Some(channel.connection_ref())
+    }
}
```

2. Or add a TODO comment explaining the transition plan:
```diff
pub fn connection(&self) -> Option<&Connection> {
    /*match self.channel.upgrade() {
        None => None,
        Some(channel) => Some(channel.connection_ref()),
    }*/
-    unimplemented!("connection() is not implemented");
+    // TODO: This method is being phased out in favor of directly using channel.upgrade()
+    // All callers should be updated before the next release
+    unimplemented!("connection() is not implemented");
}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

`````suggestion
    pub fn connection(&self) -> Option<&Connection> {
        match self.channel.upgrade() {
            None => None,
            Some(channel) => Some(channel.connection_ref())
        }
    }
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-11T15:22:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -761,14 +761,16 @@
                     Ok(Some(final_response))
                 } else {
                     //zero copy transfer
-                    if let Some(header_bytes) = final_response.encode_header_with_body_length(
-                        get_message_result.buffer_total_size() as usize,
-                    ) {
-                        channel.connection_mut().send_bytes(header_bytes).await?;
-                    }
-                    for select_result in get_message_result.message_mapped_list_mut() {
-                        if let Some(message) = select_result.bytes.take() {
-                            channel.connection_mut().send_bytes(message).await?;
+                    if let Some(mut channel) = channel.upgrade() {
+                        if let Some(header_bytes) = final_response.encode_header_with_body_length(
+                            get_message_result.buffer_total_size() as usize,
+                        ) {
+                            channel.connection_mut().send_bytes(header_bytes).await?;
+                        }
+                        for select_result in get_message_result.message_mapped_list_mut() {
+                            if let Some(message) = select_result.bytes.take() {
+                                channel.connection_mut().send_bytes(message).await?;
+                            }
                         }
path: rocketmq-broker/src/processor/pop_message_processor.rs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Improved error handling with channel upgrade check**

The code now safely checks if the channel can be upgraded before attempting to use it, preventing potential null pointer exceptions or failures when the channel is invalid. This is a robust improvement that ensures operations are only performed on valid channels.


This pattern should be consistently applied whenever channel operations are performed.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-11T15:22:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -52,7 +53,7 @@
 
 struct ClientInner {
     response_table: ArcMut<HashMap<i32, ResponseFuture>>,
-    channel: Channel,
+    channel: (ArcMut<ChannelInner>, Channel),
path: rocketmq-remoting/src/clients/client.rs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Refactored channel implementation with inner structure**

The `ClientInner` struct now uses a tuple containing `ArcMut<ChannelInner>` and `Channel` instead of a single `Channel`. This change supports a more organized management of connection state by separating the internal state (ChannelInner) from the interface (Channel).

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-11T15:22:21Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-11T15:18:14Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request refactors several components related to channel management and logging. Notably, it removes the `Debug` trait from certain structs, replaces mutable channel parameters with immutable ones, and introduces upgrade checks to validate channels before usage. The changes also reorganize the channel architecture by introducing a new internal structure (`ChannelInner`) and updating related methods and logging statements. Minor adjustments to log formatting in multiple modules are included, ensuring that only necessary details are output.

## Changes

| File(s) | Change Summary |
|---------|----------------|
| `rocketmq-broker/src/client/client_channel_info.rs`, `rocketmq-broker/src/client/consumer_group_info.rs` | Removed `Debug` from derive attributes; updated log formatting to use more precise channel identifiers. |
| `rocketmq-broker/src/client/manager/producer_manager.rs` | Renamed an unused parameter (added underscore) and simplified logging to output only essential group information. |
| `rocketmq-broker/src/client/net/broker_to_client.rs`, `rocketmq-broker/src/long_polling/long_polling_service/pop_long_polling_service.rs`, `rocketmq-broker/src/processor/default_pull_message_result_handler.rs`, `rocketmq-broker/src/processor/pop_message_processor.rs`, `rocketmq-remoting/src/runtime/connection_handler_context.rs` | Introduced channel upgrade checks before sending messages; modified parameter mutability; enhanced error handling when channel upgrade fails. |
| `rocketmq-client/src/implementation/client_remoting_processor.rs` | Added an `info!` log statement in `notify_consumer_ids_changed` to indicate broker notifications and prompt rebalancing. |
| `rocketmq-remoting/src/clients/client.rs`, `rocketmq-remoting/src/net/channel.rs`, `rocketmq-remoting/src/remoting_server/server.rs` | Refactored channel handling by introducing `ChannelInner`, updating field types (e.g., using `CheetahString`), and adjusting method signatures to utilize the new structure. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant Client
    participant Handler
    participant Channel
    participant UpgradedChannel

    Client->>Handler: Invoke send/request operation
    Handler->>Channel: Attempt to upgrade channel
    alt Upgrade Successful
        Channel-->>Handler: Return UpgradedChannel
        Handler->>UpgradedChannel: Send message/data
    else Upgrade Failed
        Handler-->>Handler: Handle error ("channel is closed")
    end
```

## Assessment against linked issues

| Objective                                                       | Addressed | Explanation                                                       |
|-----------------------------------------------------------------|-----------|-------------------------------------------------------------------|
| Prevent introduction of new bugs and update unit tests [#3091]   | ❓        | No explicit unit test updates; test module removal may affect coverage.  |
| Ensure the refactor does not negatively impact performance [#3091]| ✅        | Changes primarily involve refactoring and logging with no performance hit. |
| Document new architecture patterns and refactor [#3091]         | ✅        | New patterns (e.g., ChannelInner) are clearly defined via code changes.    |
| Test in different environments (staging/production) [#3091]       | ❓        | Environment-specific testing details are not evident in the diff.          |

## Poem
> Oh, I’m a rabbit with hops so free,  
> Coding fields where changes dance with glee.  
> I skipped through channels upgraded with care,  
> Debugs removed, leaving cleaner air.  
> In the refactored code, my joy does bloom—  
> Happy bytes and bugs meet their doom!  
> 🐰✨  


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpADK2VmgqyjcEj2wAbb5AokAI7Y0riQ4rjedJAARADaAJL29gCqAKKQZgDMAAwAnACMALqA3mSA8H82JABmaGL4fADCsJjk3oC8G4DVOzGQAO5oyIjYAszqNPRy4bCe2IiUkMwAHojM6Bj0qBhOApTRuXkATBqQCWFotLQBiLPISIOe2fkFADToN2vwDNTR8Fi4U5BKRAMCjwbjifAYI4eHgg5gueRVfAMGb8KqTVDcHx+ALBUIoZAEfzVWoEPh/TxNFokPxMZjcCHsXrqBC/f68fAiMQadz/QHA0HgrA/BjebCA9AwlhgyCIsn/GZzQlkQYBSbUSaeXAuUhhARUDAMWD4hQUAJibzyWa4F64WTcD5oXzyQkAAzhPxdRwAgud1PAIY6LS91JASHTmoh4AAvaQalB0+pag2efBo7w/ADWPyIccxviJuMQYUJ5KJ3i+6yuIXC+BltXg6a1NBwBDh4gYjG8+BV03pWDYFCI2e5BgA6ggonG+SCwf6sLR8LGMPgwuyJPAlJBENxRPAqh8ASQtQ3kCp8Hg44bMKRkHDNz84wEanU+PU4zQi9n5kfYIpkGHuC7WQ6GDMIECIWB0wg3ACX+EgFh3MRqDnGU3z+epzwg8JQi/Ql3QwY9WU8JhN2CR11HkVM4y9bhan+GwkQzI8AFkAEVIBsGZVwoDlRE0GA2SxAsQiLRhMEgbZ0AYBhpFmeg/h47AsNLNcN2iFIbAAGS4OJYFwXBuEQDgAHpjKHP4hg0WljMWZZjJ4hgmNwZhAjACguOMvNvGMvZ9iKAAKPSDKM0zzNgSzrNs5h7MYo8XLcjyvJ8/J9gAShHfRjHAKAyHoKi0DwQhSHIKgxgUVh2C4Xh+GEPjJFjCYSOUVR1C0HRMpMKA4FQVBxIKghiDIZQytpNgCK4Kgei3Jw4VcCT5CaqgWs0bRdDAQwstMAwHKc+K9XwJiKGMxAKAYYyRXgdhzvTdgAH0rwwVpbp+RENAoIyDBiL6DAsSAvQSQaSorabnDmqiHpvHliOaDBSBQDAJHwbwpFgzxmEUPcHUFVE4xdBoboIylHupBIMERF0t1wdyxAAcmQJQQSkdB9JBAQ8GkKF/hdAAREg2aICmqe0MD+gkkgyCJdGpHoKoeJWUsGfqyB0yLF4egQQ1IGXKaIQteGRTFWM8a7cgXReF0AAl+lgM3VnoF0rBccRHTSQJPQE3rvBoUqULQKoqj45Bfymn4i0wGTkCo43LsJmHWlJ8mxKwSTZTbMrZUPfmh1hrwKHpa4XlF8l5B6Bs/GXZWIVIPh+pYZDPideNALDRlSx5vmlMFqhWoEzxLjCKjSyLanTjWFAYO/dDaGQAJ8MgbADRh0haBefDCNw/5EDQNgZQXsQ53I207cpkfsACEdzEsL0veGucCVrBXRHLH2IUjtF4PpCgyrfTEBHTDt2B+mkEYKA9gqbYDEFueARAMDUDPr2WgFYuAujMHERWUh/K835i8fGDIXhW0QLAF4jsv7wBdoEVKRQKYPmHhAsI0d2BE3jmTfA1CsAuh2nFVy+1DrHVOtdGOuABF3Qek9F6+A3qIApoAJMJIAoLQZQeq/lcHkHwdbYhTsyHeFdpQthJ86FyPxoIphJMWF6I4bFZy3CeK8JOmdC6V0HEEXunHakz0WGSJdJ9b6BgIBgCMJwqxYAeGUD4fYgmQimAYEGAOW6RBFLcHca9d6HBvExB+lfAGxVhrRBibNSiaIIbAIMNCIpbxcYNFfk4SgABxBJCdWH6MgZgdYE82BTzeIjZGaMMb7k+IKe+U4O45nPAZC8qdqDiBzi0x8YZ8ASEdDjNuWDO7hG7mEWWLA4y0NpvTRRTNJms3ZogI49hEKYwbkGXGqD0EkEwcMnBJsSC6MgBGMWEsinyVrPI25yinm6ODO8fpG91RD3AZA0u+YK4m2rk3KIY1ixcxWQLNZwtOa9X9oHV5+AQ7RKTBHHGeMqkDjqeebgDSKafGTp4XgPx05viUFnL8mI87dg5kYUmuMYa0CiC4qk3h7pdlmLdEgUgCIU3ab+FecYuw5jYFcNAcMJkixkOLLAjpvbRE2SsGYG9PCMqUkSXg0h2DIQhEs/4ojqSQH8i6AA3hwAA/AAXxdKlGsEp0aqmHtoaCso+gUHoAEY1swCJmqwLau1rrUpqw1kabW89xDphjKjORs8VwkFumcC4sl/KpQlT+RQFrPAunERTQQnIwihxoGcYtcirXeDzQWqepz4AjGflch8bdsDcEQTQPlxNvDNqlTaf4srvwKqVfUNsrzRbbAlj2vt0RCRPiiJAoe29obXhIC8YN5YGB6szoa4NlxTXY0Hpa1xfhS5/HHjPOZzZs2XBOVDWYjAl6xlpbNBs8g/YB3XWO/ARBs4jLwJia0oZolnxBYizw4iKBthQiG9g3xbz1D7tSUVmBR70HpDQAiWi9YihIC4SgsaGyeEdIgWs6b1w51LCoBsFEPW0oIts8FVb1VHpzMqi+GS/o3xftEj1j8RQuHDW/UMCFEzRB/kMf+kGIiXUQCAhwHGoEwLgaqRdSC5E3P2Xc5FjyGQvJoepolUGSX1LMfDNNli9o2NCXY4RBFzrEsoHEhJSSJHvRkXphRjM7kqOeVQ2zOz6GVMs7U6zicHwWMclw4JjmjrOacZE9zFBPNku854tJICtqBIcwdJz/C0s2UwIq0J7JaAQI83CWB1dJGpK+uk36/1AY5PoHk+EOMylQzkQvAIQ4iweeq7Vigw6i1dq5lYHiNWZIUGYhV6u1C6TwrPShN5C8GZEAZPMXpWM74evUMgWiVB2mUFPGPWVIGxbNHXPUTmNLxMXb4C6NLA6xE2befOrAARYFsC+XIwVgjPtuLLYC2gh36PNCrVW5A0Kq5zAVPQG9LI4ySsUOi5ARTprAdCLBUF/xMe0DppXIcHYftqqgWtzG0QJi0cPUoHcawyAMEoqyDEL2jyUCOEYH0UPBSBlkKOzwN2vxhxoAitU3FRX+hmHrYUoolD0CUMebwp4BCjNxh9ht3mKZU4lhqnYtAnv8BBNnRZ475Vb1IORzWqkVfw2Vb7LXF4VJzfG2LL8g2SDDc1fQR0VcmS3rbrrq9+uXiG6wKNFDeULwzL3bUaIaPPXoYUAaJAYugMTtt5qWH/AMCK4NMr2MpZ4lkq1pu7H77t1Enm2X/4UgKBa8jEfC92fgNflGeB3oE40baDDT8Q9slAGLPg4h81Q2XBQ5h54CvPaZRyz7x8I0HvFBe9QNsH3GAhtIADyOAA8s3wMova+w1jMPEjzB0zkFxr7/3o3PcLcm+MeQjPplYAXijng3PvbH0jFpyqFkEPXFxzh7zwD4za0EwkxE15CfnEwGRxg/hkzyj4F/gU0AXEGKSgGYkLS62gVgVwHgXnl7V0xdF/hlC/13z933yfw3wW38gADJZhvAqgXgF9uAuAWCqYXhw9+VvNuCjFGEr0Gk+DcAFghCIRyB94IQrY1gogKBIsaAFhcB81bMHZn9KAlsGtKBzFCtrFisUtSsIlytdCjoxsFtbp6tKsKBPFIBZEKChgqD54aDH9MtLDKBmDWD2DIBODuDh4XgQcREI9xEhCIkTFvAxDGAJCpDiZZCMB5CeVKBlD4I1DzFZsGDtDls9CNCDCksjCwkXMhEbDq5PItDMtSjedfM8tfECt7NDDbETDBFjJyAhEQlMsCBgiCIms8s2sskhpSpckZoetwYP0VMSlL1t1yk24AAhZLfYYQ8VOFFuMNbGH4LpJmdGKHPpWAksOCU0N8blW/HMGZKJKmJGGULsHWNEMPQMbo3ACmGZd7KYRyW6Twzo/ULeBI26SXEgV/E5Y4ZOFcI0EnRAM/eoaBH4RZKHM0MIS5QZF4/lDQUNWgW6PodQW6S4PsWYJ4seJEwdFE3KW6BkdEtAWQA3NAJmX7I1fdFPZkCUY1dMEYWBOaS5D1Ak1oDQHteJM4O5fNI4BINETk6kbk7gXkpQJtIkYgigYTF0AAOQZFtlLCai1hxSk1EGOVWAGwwDbWbgRToBAAlVqB4hDzX2J1kkq1iAbWNBFDZVoBiEh2hxzD+CJy3UHSTmXF1GmDkkFOFIbTFIlP5IpgCBlLlPsBYH+IhIt2hL8CqD3iF0bHkAxFPQoGlnmjEl8EPWxLqiZlRMnilWQFtVRLJMxOxNfn+OPhdBLNJL6ApPdXNVLB5KoCdwDN7lDEOL4GOK/Azi11vXzPwB3CE3vXwmQD3g/WlXVh2A7J4nenQFVB6CoG4B3HWHYXmKMMqHRimSIDSE7M9EvgE29j2IfngLE2HOQOky/lk3QPkwPCwOU1U0VPQBgKQP2P1QQPPKohQKvLQK8D/jvII2wOQB6GnLvDg053pj3CqG5Ba3y38W2gaIKKaLOhhXeKRhOOMlQvpCzNhl+MoHXBkk8kHNuiwvQuzDwrTI+BIF6Ngv6I6yGK6xGLBkKXGP6zKVs3X3XCdx2LRG2L3GdH+G7PANuJm0HMqELEePP1aA4q5j6CYluh7TxPtmwoFXTW3PuhYHq2ngBLrQdkHM0irisDIthnsHwqotW31I2whD5wME5TbjkszUUoLMUDP2NQexRFhL4kzL8FdB1DB0bXUOj1pOT1RwZLQG8o5ObL5KlMbKmMJI9hxw/XhguIb1PHfVEAzA9WVBINdNgykutVQEGGklknjMbiiqd22FlEo30gAm3I9XzPCvLOiWovbMhMtxpEUE8FDTyqarfU8vNBLmZG12b34sPQbTJwWXTEFxFxX01iYB8HoCiFrUJDwzHz8FuBEhQBEvdOkr6ARxXFs3CpmBUEnD+JHHsDbQbBcE7SIjkRUqxIfXItGhaSkWculRVIhEFxQlyvSschuG2ruuIpxBEkkreXCsmo3Hyr8CCp0zGDN3ICmllQPH3HelOBqrpAnkJHKvzx2utRmXJBj1eIzH+rjGxvoBtNQAhvoF1RzlLUQBJIzCbRr1xzIBhgJVLB4jZiLHICuDrRtKpvDUlAjhkHkGypBBh3VF1nkCppeDJqhtPFVCiUjAZi1TfHjK/imHQIclkmHCMGP2UF8FFzfT4t2KQL1J4iZlLEoFnNnQUK/ACHLDKkJBtKqIRReDFpg34CHNgNI0Lz1iHNTlkywCpvlqgKvhfKOzfMPDPNgK/MvO/hvP/IAUAofN8UgCfON3PKjqUBjqQLjs/gTr/MwJTtjBAtVDApktQB4pgp8T8QCUQo6KKNIpwqIEwqrjQpboooIpIE8ixAeoktul/G8DRNmEopkhou+jouyQYpBnyV61YsmPdJvBkuIk6vhk2J6R2MO1fjgM71uzR2mxLS9P4usP6G9hJKLx+ErJJ10qsCxHEpBotiRloFMrHsrPC1OXOV2KdDP2t0tLhh+r2phDl3PEQD1ggP0i/D7PNJLX4MHSUtxmBtCA0ucDWEpNVSN0E2XVrClv1lL0QaCBBpQa0vdmhFv3z3VBu2XS5jgdaHQfeRj00rj34DwHdsxX3ikD1g/xzBDG1RlRzwgeZqSsAMAjp1TT/snU8AZzoAgUPW3nPDYyogn0FqodV2gznzVPEFNpQg73mDPrmG33AMvvIBHFKQhAuLjOuOPiRo7F0ZvtnkH1cM+ULlTSYFVHjINETOYyomPuAMPThBGxrjHngk1Lqo5sIbxCnKwB6GKy/24GNE/HzDpRJDN1wczsFp6lurAJzDV20A13t3jXVNwdXS8rbiQaLGIZaX3KMH42viPNfJPPfNzqO3ztQPNyLoAqU2KQzojp3uzo/NjvfnjuvI6eTq6eAtAr5Mrsgv9hrvSTqPgvyMbuc3ZGFvqGMiUBqB8FwHeL7pt0qwesGC9kHpaUUInta0yXouBm62YvP0hkXrudjEPrkV5i2a9jvt8DwMkcqCOdwCSMUIsvWzWJQg2KRi2IO2BT6cadtp5W7wBpFKHV/3Ox5z4GeZdGOOvvwLNwRYpjO03X/yAc+SXy2UMblTwBOs8FtWYAvAbS4EiLdWO1YHJb/kpYRbpavTdSEbrz/SxWDh1w5eNB/wPtupJxeDO3bB8GuuTNuvOLSJxnKrGqvRsrsrZACHcpuDW1WKbDnDP1VP6siHkB/1LGpa1BZfrQFcJHzLkA/DNO10wENfFJbOhgyvhpIBDk1YRQyYIi0LSsNAyo9Wxv5f5QphppzFLTTCPAcEjP8hNahvdQAF4obAynWm0CnnzrjkAM4VJuxIw1AkycZBB15pktY3Wob4Yw5kwZck4xZ545JUI+BUSvx9mbwuWL9nzvZXHzGeJLH1SJgPaJa8qKbI4i9DW629xx5q3JIirhbSq9YyaxWM0CNhdgGxU6rrb6h71HbsHa2vxwrlwMAwByqKWk3+dfREyrlSwbH62txcovwpg+S+BrXYwZlm2pHZAbWgq2c0BDJJWyphX0QxzHWpm/XHJ3aoNxaXSC9oGvbb4d7fbzjsxGRYquqIEZ2fBSCgy+alWErHnIM2bG8+5BAuIebJNjX/6urb2c5VnZIMz+3IP1QQxcHqO6BgKwrIAQ6Ay9aT9DaMcIXYDERkRh2m4LbD0hKRl4WG1cW/8yMtwv6HRG4+2WFTpd24nMOQPMrKr09mPZ8cxU9X3UVokRgrg5ww7DzYPhN+nmmd7Wmfz2mMDOmgEJjcD8CNMiCSDYa6BkF+hZADQXCMXvDqRfDY2/LX3DntmuAakWJyOfntnd0ImiwuBNyVxsxKlUHpVymdn72GYuAPnvAvm88H7QgLYSMGZV4aWr12X+VxDJDIBIsZDBR/mUjzG0iXhBgBAgQZxBRbo+00AuBHB2v+RZwIRuZqA0BWuhgOuBQ5wsse0NKyZoE+uJvBvBRSUe1It9wiAXgOis1fAcVfiZgWdaAuAtckZV5yPbp9xBMuAvRTpgBZj8AFhgBaAfPIB8vKsAAxBsb2PQPQMrsIXqkgRLx62GVLrSv7vR5cp65r1QrgaAQcj4ViEIEIJbSHkH6HiDW6bYbOW6cQNgawsuIyeeAANgABZ1Cu11k5Fcu3vSAYuvZGuJtr3243ncBqfovpBtmGf9CG7ksijqOrh1nNmCpjmvJrDzvLhtmTmFDqjXrHDvPfOqgsB/OWDAvweQvxeOevYIuovvnNeIMMugetyUvNKWk4uB6svKAcusQaeSBCuixiuH2+CKvaur1qu6XpC6o5DTmmuCIWvpoBvOvpuevFuA+pvhvRvxvQ+huMAZvEkokNuQ/Jvo/VvuB1voEtvksdvrj9vtxcpjv8BTvc8DnLvvZrvbv7vHvnusAbfPvBMfvweAfDfku0e0vwe4RUeiA5uVDOAYB4eGBEeSBkfv37Q0fffVCgisefgce21M120NcuBsBSfyffhKeHZrf2ffmuemfXnhfWf1/dfN/vfGe4slneeVntaBejohfJfRfQuJfjmMW7CajYKFn66Esglln+F+fqMLDiLQvv/HsKSPopc2nrXMmKBSR5hMVKTjEV6gNRJP/wv4/97Cl3cChvX2xb1IWFnaFi6HeKID+6INV/GaTRZGVuANvTIms2P4esrKkIdsl+h6zpN1iqaMTrpUk5It8WvOdsjizYGvZjQCaWiFcHpzS1HQ1YatCVxxgTATWx7J8DsGTBptMmUOfpIINmRSxFkujN0HgAphMRZAMTQNK2zhiBgcUmbNCGyEXbOw/ACrYSkG3gY1RK0RAkVvgRcY3sJYzzBGhni+oBgaQRNJngGWxpM1IAHKAGoG0KqocSqPgM/DfW06DI2ca9cJtuArKvISucwGZPmUY7N5SaQHVsth2hBuV5cGrSysC3NT6s9Y3VeaDa3mSKhiczLScDaTRza4/gqAQNupzNxXsM4jbDRhb0fbvtn2Y8MjpIxHKD5kAz8UgHO0XjbppUbMOHLwPVJfsf2W7UKvUNuquDGhRNNNtmjSrlhgIr4NEFvADhHxFOKoT2iqSvTGgQ6mnVUJMlqq4Raw+ZHrkfm47eBdWMA1muHBxr+AiO3NGjroxtLMD9h6jejoO2OENCMh9OaoOngVDkZJwVGa4XqXTB+MNGeLHgfwMjA5xpGUsfxlUIwwBx/s49GprU16ZYChkVnYTDZ0Lr2cxmjnVTHgSniuctMCCcgpQXl4dhFekAXAUiFkj4DQgzBWNj4XB60sXeVXGIjVzq6e9EiR/VIuP2EjIMmoQPCSpUiUAN94uPfJLtuVB4tJl+VPQcmQMQH1A/MThAQK8B85MisArI4WhyKLBciLwPIqGpV0HRu9auHvBIgz3FH69FRGlJQDKJBpyid08wC8Abw4jA8iAqotYOqL0qkDyO5A2SDqNqJ10EK7/eKGVmcwwitW4aYog9SN64UABT/D6LRRAGDEwBoMCAX1gMBegS2iNK+rOgwbqpzg27NuL41kBzcYkHmDcPTU+SED/2bcJYrgGVHZgIxl/QFsmMFA15yGyVH1tqVLQsIjS5OW7H8Wlw/UIGaVfTj8AUHIQB2EoDomTl8bb0lec6anGaBID1RpUuTJjBoyVrVI+AnBKtm8iJYzJ2QGNFTvGEBxkJmwAQAQI6BeHNCgM04psFq0TRMYU0VgrkmpUzRPpc06hZ4hl0HqJC7Cp42JJwUFi1hHcq9Mfpxn4ZypyORwJ8uQwmaqhaMIzE2pdGlT41/g5QqgPmCvZ2MXODjUOMlRSa4joC9TSOtCxzrPxBmUmAuiMzJGKYKRBgHpgxKhaEiWJedIZuxN/KcT7ypdSZveAgoAgoKczOCm/12iuQ1K2YIomlkQDFFzmtTAYkDDKg3NCxC9aAdMVgHvYIkyAijOvTBab0Lkx5CpBElJglQKY4WEgjMhOwwsTiLAgVocngATCWq0ILgfuGpD0AYaZBdOMvnCrIiiAk4PGAK2rQvCPU4VYgs3AzxFtTi7CG7gwGYh4BgAkReyZQD0AINwq0U4NnoM8AyEda34wDkulgiKQIIdQy1GvSnKqgw8MU08MVQEGm5/BtlW6hwgXgPUGAEgCmB4wSJn46yl4QEfeixFs5ogQVTOtu1qDC0dcDowUIQIUiYQYGMoeAKjVDBAsB4ANRKVEHNhpYrISrHILbFEG1pdGOQ0BvWlMliAFgx05ElEnq5zhSGCAU8LQCEBcRpcnsajESCqBroyozzZgVRAB5XZ6A67d6LGmnIfV4igoMnC6AOiOSmwKIDYOqStDscyEN0wRA9MJI5ArIS0kzojNMY0MlphAuLJ2NymM8gq+E7dsCBIyPohQeKOKVHBynEwJscg1GNEyXIrlDqaU06JlMkozIjWtYYfGYOjCvCuB+03yVzEiIcAOACNMmTjkDD0lQ8/wECmgEyrSDsRmob5Hrh+AOTC4MKM0vwwbjHwgJ6Ac4M+mkCFwehcVaSgkG5gjgBcfoDwRey5iolCBREktAEDOBkz2EnYyktSWpwecgc80mjjDOemxUapRoasoFw0D6zecAZU6WBwOGrjSwrgpyaqFQBK06CBEOdkmnFkdS/JT0kUQg3ewEyIQ1hDQW9SDhUlKMGuWsDSRDkeoSmAGbOR+juEG0HhvHDAbAWeGVswUp8VUF8OOHMD2xMsuyWzNtgGDS4OcDOOFS9QphBwmAQuXo10LS4vhFcrAGdTonh0+JBI0TIJJabCS2mcmJOlxKAqqYwEI8GkTKTpFjBkEfI+lmFnMwUyp5eRRCspNhiqSIk6ko6b5gcLmt+UXAfyOlIFnZTRCbM37vyMHTqjwshiSeQ5I/lxilJAYn+YIj/mmTn+tdeoigrchoLnMbRc6EqyAE5i/o2kzrLPVGIsVpibFGAXSi0ISgM5HGeBObFZkGzZqRoGYUcy+Cpp2QQ5ICsfDBIrtchesfoNRgPTAxU8HYgVh/U4HPz4FCac4gMIlAuhRwJGDMGAqynsK8pIZaoDIJkjlsa0eUNEEUPkBD0dOuYHiAIuUzYs9ZtAQWHaE8BBUiWfDF0NfOzDwTDEUwI8GgFgAeLYYeiaDkVOsHPEdFE2Gyn5IUXqZqZB2bdkrkNgSglaHGN8DfRdAKy5BupMWf+NckBTh64JPBmKEPTjikFWsqaRyXCXuxTK3HGubOiDlG5qxQOEJXQ3G6axRYLoLsA3CzSWzZItsDhA+mAk9KrgfS7GtPPxL2LbY6sVfJKC4qUY2pgyWIYhHEBMw8l08QlJUsiUzZNE5CPpa7D6UEIbY5sZFGMvtjcwkAgEckl3GFgrFPWSBe7FI2pxSwtUy+ZpdSC8WvKoiU8uLv9LqgaNXBOKEqIQlBB1p+FlAICti0qVNJTgDcisXen4A9BGGeKEeKkpc7pK3WkyuNPDD9DkQclE8VZWDMYA+ybWhU0yqzkZ4ZwXa5HQEqe3cGwIf62yI8P/hvoZwEWz0BxRoUhXBSl0oc4qtKHtbhAnFVbKlDWyiTN5AZBEb5E0HFhah/FVMTxWbg/BhBtiPgZxTuI+RSgogNALhnMnTJ8NSwKAzuaRO7lHCjJkYGBNZLznv4SA9QIgCvJjDsYh5lGMeL1W8lMZBFag5+WEsgVILbQO4Apf3IPQ5xuFv7X2GPFWpLtG45teZE2zmRzRXarcWANHNJpvoqI6szWfou1kvoam9E8zgstPJHzrOJ82zmfOLrjMr56mbNJ5zurOF4FkKk/p/IIX8IiFAZGos52pGVqju1a/UcyIRr+QE5FALgOoo1laLcAEC/lJTOgWdLHQ3SnNFcD66WIBcFAOLluUGWzrCeEZd/ouqd4CENw7LaVX4oCVEB3U60BwIF3MTRKb59avBV/NbqEKjwxC5Eq2te4ucO1yCSgsyKnUCoQJVwALmwWPV6Ao2m6y2eetkXqYr1ik/BemNvVNr71LaqRGnSpFSoLZKuN9c4WZFASZ1z6X9VUH/WAanIi6kDcGyhXIKINN6oos2pIXwa21SG19V2pcK+CVef63QABsPzR9gAI6sdYOgnX5SOVoGy9ewnyJka71kSSjV4mo1FpaNeolwvYuw24amCUq3xbKog6EbrB8C8DYliE0waRNj6qjc+vbWNLUN3arAL2s/WYbZI86oDRcGXUZozNc6vDUeC3UZ5I5GAd3rDJ1ZEg4hzVHHhSzL4ZSspBylHsAHgBZB9gLwH5jiRIDvc8A8CH7rhtMpsEVNzCJBWpoE0NqoN5G2DaJoQ0uczVbnbTCFKrVSbmRVofymyotFhArR9ivrnKthghjIVKWuzNesbVnQKNOm3Ue+u3lHhStG4crTezYLbrB0bKrgDCKBIEAIF+6pTdmD0B1bvVuRBrfFlI3NbWimWtrdGNwWLb0tzmG9V3Scz4UZezWSermJ0nDECx89WhQ83YrPNEJquKCjCDbQuAf0Fk7pD3Osnnp4Wwox0UfyRk3yXJE8cRUiCfHRBhFWNAufar3altfV3oj5ZTLOl4oxBl0tVqItHbRAPlr02BgK1WXGSPtDXL7cRqCpJ4ZI8wo0AlJ7RRS9Z78n6souoniQXQHG8JTxpmSFT6WJUktsLXUC8LSCVU2zAshBDXThFjUiWawKAZXSFcVqyacmFNwcpup3Maxf2NuUoQWV2OucFz3CEucE0oZEEKKgI6SwM0yG59MSxWCsr+1GgU6UYvh3+kOWradtFKzPwugFwmPUEQECxLcAGAg9AvsTTLn26/Y59POK7t/AHRXqwi+5Qw053AxCQYcvlX9IMU6zvF469+edJMWx74GmyktBi0IFbYyVu2O/LlotXwlxiUM84fmDKXJhESPhHGXQzqUPKJYBOlWTHLL3k6SoJu16ZkwNjigESHJPcfVEqZoNDpW8quY8Rtn2wMN36qRGbmBlohQZx8eCDJGj61zTwMKmkmcE+kjZQ5UEaJgyXTmltM51FKXRUi3maRc5c2jjLqyJU6MJOArWJVvXiVMyl2zYaHe/JRqqxj4BNQlfTMoxJ6K9obCUGmqj3ayOSDevQhCq3lb9Ypt+zbGqribcqW51QAGXGFcFG7352+w1afjGlGTW5pwLcAgCqAoS+WEckUW5K/CFUWFAQaVGiPow4oZ8C49PMGrmGHhctxs+/Q5NM51Nc1u9aOgWuJFFrSRt5ckZfLTrXyDEuW2kaHofl0ba1wBo/sABsBWAeN6moJJprOjbbR6zeY6HtqzHtaa16mJXV72l4UApDMhyAHaihruISoICunbNooDQLIiMaSABoDsOQBXU2W6kUIbvkiHCtHWgEPgAd1VVndfu93YgGw0DbWgQhV3rYbsMhjBNS2pQ2odUNpkZeGhozZ4e8PoZfDbugPYEetGQB5NFhl4HYY0D5onDSGlw+5wK2dqit84Lw97o8y+60jxNDI3yOyMCi8jERtLc32g2KGAxO2lLGofsKOEPDXu7A9UZd21GAjjG3wg0fCW5HwjXiF/jGMiObb+E7kAjGwDcxubK5j/LvmkU0lT08xuk8AWdovxQC4qy9NFtodFG6HnRo4bmbkSTHy7zUoLZ7fhMwF5rYGW8z2bbJLSLl1AmLFtJwJLkJFX8ZOUMmfF+CCqXFE5A3dKRBO7tf95S10GcYpi2p5Nbx91CuiPDQnP8ciVjYKGADIm1jGAfKakxjJ0qbl1AtNmYqkjC1qGSE5zbCdkGwqaSseX3vHggxey3qapKaFTuEzhULlMkCxXMCXHOkq2IYVGVWioHMmRwKrT4yCBoCv5f6QGA8DNKwZA5H9aNKXNKCxrAjUDHpL/bHLYLl7RSvggUscECFangh8y0qqBCFriw1llrXKJeBN5jwv9TZYEeTSvRk5JBZrf44OJNPpDMONQE8DangAaBqKjw/lLaSFR0AbD4kCGUXzhioBVG8MZcWEwLwmqPS2cyM0XLenBV2aqrEBiiCvY/UKTYc9qRjgxFOb8DtQ8rhlUVb8oycfxNNvNWHrKwxBK1UwVohnIbstq2p3aqLC9LsdyIkugwPrSNVhnDjeHOKVbU7IEGURotcDocLtnUh6z34k4YogCnjBHd1VdU2E2uH2nnqawApVMshEwqTaIBE8VvOlKa7Jq7JtEz8sgSuSF4tx5hpLhmDMH8RLx9g4gWPlsTT5idUtdxPE0EFNMrhkOYZuk1bzZNzGrIwiY5USGLj6PK48P1yJ9G0NiK5zZBZPXYm5wuJs47If9lwXkiShBC9cYmxraNonUSDIntrhXMRoTDcaP4DQBTQ9JGZRaCoDUArR2o60AwBRdGiYlmxD1dcG6zoC/EtQX8NaOReyiQA8gAADiJ4MABAVQfYHkAYC0B9giCWgAIByAFAAArCQByBE8qgAgEnopZIDSWGA0lrIET1oAk8cg2l7S1UGMviXNoUAXizs34uI6hLaJe0/oCAA=== -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=mxsm/rocketmq-rust&utm_content=3092):

- 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 generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: rocketmq-rust-bot
created_at: 2025-04-11T15:18:18Z
body: 
🔊@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💥.

author_association: COLLABORATOR
user: login: codecov[bot]
created_at: 2025-04-11T15:21:14Z
body: ## [Codecov](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) Report
Attention: Patch coverage is `0%` with `136 lines` in your changes missing coverage. Please review.
> Project coverage is 27.67%. Comparing base [(`abf247c`)](https://app.codecov.io/gh/mxsm/rocketmq-rust/commit/abf247ca943e60071c437b201cb7d84edfecba98?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) to head [(`986cbf2`)](https://app.codecov.io/gh/mxsm/rocketmq-rust/commit/986cbf29cd2dadb015e06fb4f2e8c836d4055f4f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm).
> Report is 1 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) | Patch % | Lines |
|---|---|---|
| [rocketmq-remoting/src/net/channel.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-remoting%2Fsrc%2Fnet%2Fchannel.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtcmVtb3Rpbmcvc3JjL25ldC9jaGFubmVsLnJz) | 0.00% | [28 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [rocketmq-remoting/src/remoting\_server/server.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-remoting%2Fsrc%2Fremoting_server%2Fserver.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtcmVtb3Rpbmcvc3JjL3JlbW90aW5nX3NlcnZlci9zZXJ2ZXIucnM=) | 0.00% | [22 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [rocketmq-remoting/src/clients/client.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-remoting%2Fsrc%2Fclients%2Fclient.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtcmVtb3Rpbmcvc3JjL2NsaWVudHMvY2xpZW50LnJz) | 0.00% | [21 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [...g/long\_polling\_service/pop\_long\_polling\_service.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-broker%2Fsrc%2Flong_polling%2Flong_polling_service%2Fpop_long_polling_service.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtYnJva2VyL3NyYy9sb25nX3BvbGxpbmcvbG9uZ19wb2xsaW5nX3NlcnZpY2UvcG9wX2xvbmdfcG9sbGluZ19zZXJ2aWNlLnJz) | 0.00% | [12 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [...remoting/src/runtime/connection\_handler\_context.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-remoting%2Fsrc%2Fruntime%2Fconnection_handler_context.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtcmVtb3Rpbmcvc3JjL3J1bnRpbWUvY29ubmVjdGlvbl9oYW5kbGVyX2NvbnRleHQucnM=) | 0.00% | [12 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [...c/processor/default\_pull\_message\_result\_handler.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-broker%2Fsrc%2Fprocessor%2Fdefault_pull_message_result_handler.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtYnJva2VyL3NyYy9wcm9jZXNzb3IvZGVmYXVsdF9wdWxsX21lc3NhZ2VfcmVzdWx0X2hhbmRsZXIucnM=) | 0.00% | [11 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [...etmq-broker/src/processor/pop\_message\_processor.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-broker%2Fsrc%2Fprocessor%2Fpop_message_processor.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtYnJva2VyL3NyYy9wcm9jZXNzb3IvcG9wX21lc3NhZ2VfcHJvY2Vzc29yLnJz) | 0.00% | [11 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [rocketmq-broker/src/client/net/broker\_to\_client.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-broker%2Fsrc%2Fclient%2Fnet%2Fbroker_to_client.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtYnJva2VyL3NyYy9jbGllbnQvbmV0L2Jyb2tlcl90b19jbGllbnQucnM=) | 0.00% | [10 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [rocketmq-broker/src/client/consumer\_group\_info.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-broker%2Fsrc%2Fclient%2Fconsumer_group_info.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtYnJva2VyL3NyYy9jbGllbnQvY29uc3VtZXJfZ3JvdXBfaW5mby5ycw==) | 0.00% | [4 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| [...etmq-broker/src/client/manager/producer\_manager.rs](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&filepath=rocketmq-broker%2Fsrc%2Fclient%2Fmanager%2Fproducer_manager.rs&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm#diff-cm9ja2V0bXEtYnJva2VyL3NyYy9jbGllbnQvbWFuYWdlci9wcm9kdWNlcl9tYW5hZ2VyLnJz) | 0.00% | [2 Missing :warning: ](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) |
| ... and [2 more](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm) | |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #3092      +/-   ##
==========================================
- Coverage   27.72%   27.67%   -0.05%     
==========================================
  Files         532      532              
  Lines       76870    76901      +31     
==========================================
- Hits        21311    21286      -25     
- Misses      55559    55615      +56     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/mxsm/rocketmq-rust/pull/3092?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=mxsm).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE