-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ISSUE #1037]Optimize DefaultMQPushConsumer #1038
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,7 +55,6 @@ impl Validators { | |
), | ||
)); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -203,7 +203,9 @@ impl DefaultMQPushConsumerImpl { | |
self.consumer_config.unit_mode | ||
); | ||
*self.service_state = ServiceState::StartFailed; | ||
// check all config | ||
self.check_config()?; | ||
//copy_subscription is can be removed | ||
self.copy_subscription().await?; | ||
if self.consumer_config.message_model() == MessageModel::Clustering { | ||
self.client_config.change_instance_name_to_pid(); | ||
|
@@ -474,20 +476,6 @@ impl DefaultMQPushConsumerImpl { | |
)); | ||
} | ||
|
||
/* if !util_all::parse_date(self.consumer_config.consume_timestamp.as_str(), DATE_FORMAT) | ||
.is_ok() | ||
{ | ||
return Err(MQClientError::MQClientException( | ||
-1, | ||
format!( | ||
"consumeTimestamp is invalid, the valid format is {}, but received {}{}", | ||
DATE_FORMAT, | ||
self.consumer_config.consume_timestamp, | ||
FAQUrl::suggest_todo(FAQUrl::CLIENT_PARAMETER_CHECK_URL) | ||
), | ||
)); | ||
}*/ | ||
|
||
if self | ||
.consumer_config | ||
.allocate_message_queue_strategy | ||
|
@@ -502,16 +490,6 @@ impl DefaultMQPushConsumerImpl { | |
)); | ||
} | ||
|
||
/* if self.consumer_config.subscription.is_empty() { | ||
return Err(MQClientError::MQClientErr( | ||
-1, | ||
format!( | ||
"subscription is null{}", | ||
FAQUrl::suggest_todo(FAQUrl::CLIENT_PARAMETER_CHECK_URL) | ||
), | ||
)); | ||
}*/ | ||
|
||
if self.consumer_config.message_listener.is_none() { | ||
return Err(MQClientError::MQClientErr( | ||
-1, | ||
|
@@ -528,14 +506,14 @@ impl DefaultMQPushConsumerImpl { | |
.as_ref() | ||
.unwrap() | ||
.message_listener_orderly | ||
.is_some() | ||
.is_none() | ||
&& self | ||
.consumer_config | ||
.message_listener | ||
.as_ref() | ||
.unwrap() | ||
.message_listener_concurrently | ||
.is_some() | ||
.is_none() | ||
{ | ||
return Err(MQClientError::MQClientErr( | ||
-1, | ||
|
@@ -701,7 +679,18 @@ impl DefaultMQPushConsumerImpl { | |
async fn copy_subscription(&mut self) -> Result<()> { | ||
let sub = self.consumer_config.subscription(); | ||
if !sub.is_empty() { | ||
unimplemented!() | ||
for (topic, sub_expression) in sub.as_ref() { | ||
let subscription_data = FilterAPI::build_subscription_data(topic, sub_expression) | ||
.map_err(|e| { | ||
MQClientError::MQClientErr( | ||
-1, | ||
format!("buildSubscriptionData exception, {}", e), | ||
) | ||
})?; | ||
self.rebalance_impl | ||
.put_subscription_data(topic, subscription_data) | ||
.await; | ||
} | ||
Comment on lines
+682
to
+693
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Simplify error handling for improved readability The error handling within the For example: let subscription_data = FilterAPI::build_subscription_data(topic, sub_expression)
.map_err(|e| MQClientError::MQClientErr(-1, format!("buildSubscriptionData exception, {}", e)))?; |
||
} | ||
if self.message_listener.is_none() { | ||
self.message_listener = self.consumer_config.message_listener.clone(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,86 +14,79 @@ | |
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
use rocketmq_common::common::message::message_enum::MessageRequestMode; | ||
use rocketmq_common::ArcRefCellWrapper; | ||
use tracing::info; | ||
use tracing::warn; | ||
|
||
use crate::consumer::consumer_impl::message_request::MessageRequest; | ||
use crate::consumer::consumer_impl::pop_request::PopRequest; | ||
use crate::consumer::consumer_impl::pull_request::PullRequest; | ||
use crate::factory::mq_client_instance::MQClientInstance; | ||
|
||
#[derive(Clone)] | ||
pub struct PullMessageService { | ||
pop_tx: Option<tokio::sync::mpsc::Sender<PopRequest>>, | ||
pull_tx: Option<tokio::sync::mpsc::Sender<PullRequest>>, | ||
tx: Option<tokio::sync::mpsc::Sender<Box<dyn MessageRequest + Send + 'static>>>, | ||
} | ||
|
||
impl PullMessageService { | ||
pub fn new() -> Self { | ||
PullMessageService { | ||
pop_tx: None, | ||
pull_tx: None, | ||
} | ||
PullMessageService { tx: None } | ||
} | ||
pub async fn start(&mut self, instance: ArcRefCellWrapper<MQClientInstance>) { | ||
let (pop_tx, mut pop_rx) = tokio::sync::mpsc::channel(1024 * 4); | ||
let (pull_tx, mut pull_rx) = tokio::sync::mpsc::channel(1024 * 4); | ||
self.pop_tx = Some(pop_tx); | ||
self.pull_tx = Some(pull_tx); | ||
//let instance_wrapper = ArcRefCellWrapper::new(instance); | ||
let instance_wrapper_clone = instance.clone(); | ||
tokio::spawn(async move { | ||
info!( | ||
">>>>>>>>>>>>>>>>>>>>>>>PullMessageService [PopRequest] \ | ||
started<<<<<<<<<<<<<<<<<<<<<<<<<<<<" | ||
); | ||
while let Some(request) = pop_rx.recv().await { | ||
if let Some(mut consumer) = | ||
instance.select_consumer(request.get_consumer_group()).await | ||
{ | ||
consumer.pop_message(request).await; | ||
} else { | ||
warn!( | ||
"No matched consumer for the PopRequest {}, drop it", | ||
request | ||
) | ||
} | ||
} | ||
}); | ||
pub async fn start(&mut self, mut instance: ArcRefCellWrapper<MQClientInstance>) { | ||
let (tx, mut rx) = | ||
tokio::sync::mpsc::channel::<Box<dyn MessageRequest + Send + 'static>>(1024 * 4); | ||
self.tx = Some(tx); | ||
tokio::spawn(async move { | ||
info!( | ||
">>>>>>>>>>>>>>>>>>>>>>>PullMessageService [PullRequest] \ | ||
started<<<<<<<<<<<<<<<<<<<<<<<<<<<<" | ||
); | ||
while let Some(request) = pull_rx.recv().await { | ||
if let Some(mut consumer) = instance_wrapper_clone | ||
.select_consumer(request.get_consumer_group()) | ||
.await | ||
{ | ||
consumer.pull_message(request).await; | ||
info!(">>>>>>>>>>>>>>>>>>>>>>>PullMessageService started<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); | ||
while let Some(request) = rx.recv().await { | ||
if request.get_message_request_mode() == MessageRequestMode::Pull { | ||
let pull_request = | ||
unsafe { *Box::from_raw(Box::into_raw(request) as *mut PullRequest) }; | ||
PullMessageService::pull_message(pull_request, instance.as_mut()).await; | ||
} else { | ||
warn!( | ||
"No matched consumer for the PullRequest {},drop it", | ||
request | ||
) | ||
let pop_request = | ||
unsafe { *Box::from_raw(Box::into_raw(request) as *mut PopRequest) }; | ||
PullMessageService::pop_message(pop_request, instance.as_mut()).await; | ||
Comment on lines
+42
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Avoid unsafe downcasting to prevent undefined behavior The use of Consider implementing safe downcasting by extending the Apply these changes to enable safe downcasting:
This approach eliminates the need for |
||
} | ||
} | ||
}); | ||
} | ||
|
||
async fn pull_message(request: PullRequest, instance: &mut MQClientInstance) { | ||
if let Some(mut consumer) = instance.select_consumer(request.get_consumer_group()).await { | ||
consumer.pull_message(request).await; | ||
} else { | ||
warn!( | ||
"No matched consumer for the PullRequest {},drop it", | ||
request | ||
) | ||
} | ||
} | ||
|
||
async fn pop_message(request: PopRequest, instance: &mut MQClientInstance) { | ||
if let Some(mut consumer) = instance.select_consumer(request.get_consumer_group()).await { | ||
consumer.pop_message(request).await; | ||
} else { | ||
warn!( | ||
"No matched consumer for the PopRequest {}, drop it", | ||
request | ||
) | ||
} | ||
} | ||
|
||
pub fn execute_pull_request_later(&self, pull_request: PullRequest, time_delay: u64) { | ||
let this = self.clone(); | ||
tokio::spawn(async move { | ||
tokio::time::sleep(tokio::time::Duration::from_millis(time_delay)).await; | ||
if let Err(e) = this.pull_tx.as_ref().unwrap().send(pull_request).await { | ||
if let Err(e) = this.tx.as_ref().unwrap().send(Box::new(pull_request)).await { | ||
warn!("Failed to send pull request to pull_tx, error: {:?}", e); | ||
} | ||
Comment on lines
+82
to
84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outdated channel name in error messages for pull requests In Update the error messages to reflect the current channel name to avoid confusion. Apply this diff to update the error messages: if let Err(e) = self.tx.as_ref().unwrap().send(Box::new(pull_request)).await {
- warn!("Failed to send pull request to pull_tx, error: {:?}", e);
+ warn!("Failed to send pull request to tx, error: {:?}", e);
} Ensure all mentions of Also applies to: 89-91 |
||
}); | ||
} | ||
|
||
pub async fn execute_pull_request_immediately(&self, pull_request: PullRequest) { | ||
if let Err(e) = self.pull_tx.as_ref().unwrap().send(pull_request).await { | ||
if let Err(e) = self.tx.as_ref().unwrap().send(Box::new(pull_request)).await { | ||
warn!("Failed to send pull request to pull_tx, error: {:?}", e); | ||
} | ||
} | ||
|
@@ -102,14 +95,14 @@ | |
let this = self.clone(); | ||
tokio::spawn(async move { | ||
tokio::time::sleep(tokio::time::Duration::from_millis(time_delay)).await; | ||
if let Err(e) = this.pop_tx.as_ref().unwrap().send(pop_request).await { | ||
if let Err(e) = this.tx.as_ref().unwrap().send(Box::new(pop_request)).await { | ||
warn!("Failed to send pull request to pull_tx, error: {:?}", e); | ||
} | ||
Comment on lines
+98
to
100
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect error messages for pop requests In Update the error messages to accurately reflect the operation and current channel name. Apply this diff to correct the error messages: if let Err(e) = this.tx.as_ref().unwrap().send(Box::new(pop_request)).await {
- warn!("Failed to send pull request to pull_tx, error: {:?}", e);
+ warn!("Failed to send pop request to tx, error: {:?}", e);
} Repeat the change for both methods to maintain consistency. Also applies to: 105-107 |
||
}); | ||
} | ||
|
||
pub async fn execute_pop_pull_request_immediately(&self, pop_request: PopRequest) { | ||
if let Err(e) = self.pop_tx.as_ref().unwrap().send(pop_request).await { | ||
if let Err(e) = self.tx.as_ref().unwrap().send(Box::new(pop_request)).await { | ||
warn!("Failed to send pull request to pull_tx, error: {:?}", e); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -282,12 +282,16 @@ impl MQClientInstance { | |||||||||||||||||||||||||||||||||||
if self.client_config.namesrv_addr.is_none() { | ||||||||||||||||||||||||||||||||||||
self.mq_client_api_impl | ||||||||||||||||||||||||||||||||||||
.as_mut() | ||||||||||||||||||||||||||||||||||||
.unwrap() | ||||||||||||||||||||||||||||||||||||
.expect("mq_client_api_impl is None") | ||||||||||||||||||||||||||||||||||||
.fetch_name_server_addr() | ||||||||||||||||||||||||||||||||||||
.await; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
// Start request-response channel | ||||||||||||||||||||||||||||||||||||
self.mq_client_api_impl.as_mut().unwrap().start().await; | ||||||||||||||||||||||||||||||||||||
self.mq_client_api_impl | ||||||||||||||||||||||||||||||||||||
.as_mut() | ||||||||||||||||||||||||||||||||||||
.expect("mq_client_api_impl is None") | ||||||||||||||||||||||||||||||||||||
.start() | ||||||||||||||||||||||||||||||||||||
.await; | ||||||||||||||||||||||||||||||||||||
Comment on lines
+285
to
+294
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor repeated In the Consider assigning the unwrapped + let mq_client_api_impl = self.mq_client_api_impl.as_mut().expect("mq_client_api_impl is None");
if self.client_config.namesrv_addr.is_none() {
- self.mq_client_api_impl
- .as_mut()
- .expect("mq_client_api_impl is None")
- .fetch_name_server_addr()
- .await;
+ mq_client_api_impl.fetch_name_server_addr().await;
}
- self.mq_client_api_impl
- .as_mut()
- .expect("mq_client_api_impl is None")
- .start()
- .await;
+ mq_client_api_impl.start().await; This change reduces code repetition and enhances readability. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
// Start various schedule tasks | ||||||||||||||||||||||||||||||||||||
self.start_scheduled_task(this.clone()); | ||||||||||||||||||||||||||||||||||||
// Start pull service | ||||||||||||||||||||||||||||||||||||
|
@@ -337,6 +341,7 @@ impl MQClientInstance { | |||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
fn start_scheduled_task(&mut self, this: ArcRefCellWrapper<Self>) { | ||||||||||||||||||||||||||||||||||||
if self.client_config.namesrv_addr.is_none() { | ||||||||||||||||||||||||||||||||||||
// Fetch name server address | ||||||||||||||||||||||||||||||||||||
let mut mq_client_api_impl = self.mq_client_api_impl.as_ref().unwrap().clone(); | ||||||||||||||||||||||||||||||||||||
self.instance_runtime.get_handle().spawn(async move { | ||||||||||||||||||||||||||||||||||||
info!("ScheduledTask fetchNameServerAddr started"); | ||||||||||||||||||||||||||||||||||||
|
@@ -352,6 +357,7 @@ impl MQClientInstance { | |||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// Update topic route info from name server | ||||||||||||||||||||||||||||||||||||
let mut client_instance = this.clone(); | ||||||||||||||||||||||||||||||||||||
let poll_name_server_interval = self.client_config.poll_name_server_interval; | ||||||||||||||||||||||||||||||||||||
self.instance_runtime.get_handle().spawn(async move { | ||||||||||||||||||||||||||||||||||||
|
@@ -370,6 +376,7 @@ impl MQClientInstance { | |||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// Clean offline broker and send heartbeat to all broker | ||||||||||||||||||||||||||||||||||||
let mut client_instance = this.clone(); | ||||||||||||||||||||||||||||||||||||
let heartbeat_broker_interval = self.client_config.heartbeat_broker_interval; | ||||||||||||||||||||||||||||||||||||
self.instance_runtime.get_handle().spawn(async move { | ||||||||||||||||||||||||||||||||||||
|
@@ -389,6 +396,7 @@ impl MQClientInstance { | |||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
// Persist all consumer offset | ||||||||||||||||||||||||||||||||||||
let mut client_instance = this; | ||||||||||||||||||||||||||||||||||||
let persist_consumer_offset_interval = | ||||||||||||||||||||||||||||||||||||
self.client_config.persist_consumer_offset_interval as u64; | ||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Simplify conditional checks to improve readability
The conditional check uses multiple
unwrap()
calls onmessage_listener
, which can be simplified for better readability and to avoid potential panics. Consider using pattern matching orif let
constructs to handle theOption
safely.For example: