use cheetah_string::CheetahString;
use rocketmq_model::common::message::message_queue::MessageQueue;
use rocketmq_protocol::protocol::route::topic_route_data::TopicRouteData;
use crate::common::thread_local_index::ThreadLocalIndex;
use crate::producer::producer_impl::queue_filter::QueueFilter;
#[derive(Default, Clone)]
pub struct TopicPublishInfo {
pub order_topic: bool,
pub have_topic_router_info: bool,
pub message_queue_list: Vec<MessageQueue>,
pub send_which_queue: ThreadLocalIndex,
pub topic_route_data: Option<TopicRouteData>,
}
impl TopicPublishInfo {
pub fn new() -> Self {
TopicPublishInfo {
order_topic: false,
have_topic_router_info: false,
message_queue_list: vec![],
send_which_queue: ThreadLocalIndex::new(),
topic_route_data: None,
}
}
pub fn ok(&self) -> bool {
!self.message_queue_list.is_empty()
}
pub fn reset_index(&self) {
self.send_which_queue.reset();
}
#[inline]
pub fn select_one_message_queue_filters(&self, filters: &[&dyn QueueFilter]) -> Option<MessageQueue> {
self.select_one_message_queue_with_filters_inner(&self.message_queue_list, &self.send_which_queue, filters)
}
pub fn select_one_message_queue_by_broker(&self, last_broker_name: Option<&CheetahString>) -> Option<MessageQueue> {
if let Some(last_broker_name) = last_broker_name {
for _ in 0..self.message_queue_list.len() {
let mq = self.select_one_message_queue()?;
if mq.broker_name() != last_broker_name {
return Some(mq);
}
}
self.select_one_message_queue()
} else {
self.select_one_message_queue()
}
}
pub fn select_one_message_queue_with_filters_inner(
&self,
message_queue_list: &[MessageQueue],
send_queue: &ThreadLocalIndex,
filters: &[&dyn QueueFilter],
) -> Option<MessageQueue> {
if message_queue_list.is_empty() {
return None;
}
if !filters.is_empty() {
for _ in 0..message_queue_list.len() {
let index = (send_queue.increment_and_get() as usize) % message_queue_list.len();
let mq = &message_queue_list[index];
let mut filter_result = true;
for f in filters {
filter_result &= f.filter(mq);
}
if filter_result {
return Some(mq.clone());
}
}
return None;
}
let index = send_queue.increment_and_get() as usize % message_queue_list.len();
Some(message_queue_list[index].clone())
}
pub fn select_one_message_queue(&self) -> Option<MessageQueue> {
if self.message_queue_list.is_empty() {
return None;
}
let index = self.send_which_queue.increment_and_get() as usize;
let pos = index % self.message_queue_list.len();
self.message_queue_list.get(pos).cloned()
}
pub fn get_write_queue_nums_by_broker(&self, broker_name: &str) -> i32 {
let Some(topic_route_data) = &self.topic_route_data else {
return -1;
};
topic_route_data
.queue_datas
.iter()
.find(|queue_data| queue_data.broker_name().as_str() == broker_name)
.and_then(|queue_data| i32::try_from(queue_data.write_queue_nums()).ok())
.unwrap_or(-1)
}
}