1use std::cmp::Ordering;
16use std::collections::{BTreeMap, HashSet};
17use std::fmt::{Debug, Display};
18use std::ops::Bound;
19use std::sync::{Arc, Mutex};
20use std::time::{Duration, Instant};
21
22use api::v1::meta::mailbox_message::Payload;
23use api::v1::meta::{
24 HeartbeatRequest, HeartbeatResponse, MailboxMessage, PROTOCOL_VERSION, RegionLease,
25 ResponseHeader, Role,
26};
27use check_leader_handler::CheckLeaderHandler;
28use collect_cluster_info_handler::{
29 CollectDatanodeClusterInfoHandler, CollectFlownodeClusterInfoHandler,
30 CollectFrontendClusterInfoHandler,
31};
32use collect_leader_region_handler::CollectLeaderRegionHandler;
33use collect_stats_handler::CollectStatsHandler;
34use common_base::Plugins;
35use common_meta::datanode::Stat;
36use common_meta::instruction::InstructionReply;
37use common_meta::sequence::Sequence;
38use common_telemetry::{debug, info, warn};
39use dashmap::DashMap;
40use extract_stat_handler::ExtractStatHandler;
41use failure_handler::RegionFailureHandler;
42use filter_inactive_region_stats::FilterInactiveRegionStatsHandler;
43use futures::future::join_all;
44use keep_lease_handler::{DatanodeKeepLeaseHandler, FlownodeKeepLeaseHandler};
45use mailbox_handler::MailboxHandler;
46use on_leader_start_handler::OnLeaderStartHandler;
47use publish_heartbeat_handler::PublishHeartbeatHandler;
48use region_lease_handler::RegionLeaseHandler;
49use remap_flow_peer_handler::RemapFlowPeerHandler;
50use response_header_handler::ResponseHeaderHandler;
51use snafu::{OptionExt, ResultExt};
52use store_api::storage::RegionId;
53use tokio::sync::mpsc::Sender;
54use tokio::sync::{Notify, RwLock, oneshot, watch};
55
56use crate::error::{self, DeserializeFromJsonSnafu, Result, UnexpectedInstructionReplySnafu};
57use crate::handler::collect_topic_stats_handler::CollectTopicStatsHandler;
58use crate::handler::flow_state_handler::FlowStateHandler;
59use crate::handler::persist_stats_handler::PersistStatsHandler;
60use crate::metasrv::Context;
61use crate::metrics::{METRIC_META_HANDLER_EXECUTE, METRIC_META_HEARTBEAT_CONNECTION_NUM};
62use crate::pubsub::PublisherRef;
63use crate::service::mailbox::{
64 BroadcastChannel, Channel, Mailbox, MailboxReceiver, MailboxRef, MessageId,
65};
66
67pub mod check_leader_handler;
68pub mod collect_cluster_info_handler;
69pub mod collect_leader_region_handler;
70pub mod collect_stats_handler;
71pub mod collect_topic_stats_handler;
72pub mod extract_stat_handler;
73pub mod failure_handler;
74pub mod filter_inactive_region_stats;
75pub mod flow_state_handler;
76pub mod keep_lease_handler;
77pub mod mailbox_handler;
78pub mod on_leader_start_handler;
79pub mod persist_stats_handler;
80pub mod publish_heartbeat_handler;
81pub mod region_lease_handler;
82pub mod remap_flow_peer_handler;
83pub mod response_header_handler;
84
85#[cfg(test)]
86pub mod test_utils;
87
88#[async_trait::async_trait]
89pub trait HeartbeatHandler: Send + Sync {
90 fn is_acceptable(&self, role: Role) -> bool;
91
92 fn name(&self) -> &'static str {
93 let type_name = std::any::type_name::<Self>();
94 type_name.split("::").last().unwrap_or(type_name)
96 }
97
98 async fn handle(
99 &self,
100 req: &HeartbeatRequest,
101 ctx: &mut Context,
102 acc: &mut HeartbeatAccumulator,
103 ) -> Result<HandleControl>;
104}
105
106#[derive(PartialEq, Debug)]
110pub enum HandleControl {
111 Continue,
112 Done,
113}
114
115#[derive(Debug, Default)]
116pub struct HeartbeatAccumulator {
117 pub header: Option<ResponseHeader>,
118 mailbox_message: Option<MailboxMessage>,
119 pub stat: Option<Stat>,
120 pub inactive_region_ids: HashSet<RegionId>,
121 pub region_lease: Option<RegionLease>,
122}
123
124impl HeartbeatAccumulator {
125 pub(crate) fn take_mailbox_message(&mut self) -> Option<MailboxMessage> {
126 self.mailbox_message.take()
127 }
128
129 pub fn set_mailbox_message(&mut self, message: MailboxMessage) {
130 let _ = self.mailbox_message.insert(message);
131 }
132}
133
134#[derive(Copy, Clone)]
135pub struct PusherId {
136 pub role: Role,
137 pub id: u64,
138}
139
140impl PartialEq for PusherId {
141 fn eq(&self, other: &Self) -> bool {
142 self.role as i32 == other.role as i32 && self.id == other.id
143 }
144}
145
146impl Eq for PusherId {}
147
148impl PartialOrd for PusherId {
149 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
150 Some(self.cmp(other))
151 }
152}
153
154impl Ord for PusherId {
155 fn cmp(&self, other: &Self) -> Ordering {
156 (self.role as i32, self.id).cmp(&(other.role as i32, other.id))
157 }
158}
159
160impl Debug for PusherId {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 write!(f, "{:?}-{}", self.role, self.id)
163 }
164}
165
166impl Display for PusherId {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 write!(f, "{:?}-{}", self.role, self.id)
169 }
170}
171
172impl PusherId {
173 pub fn new(role: Role, id: u64) -> Self {
174 Self { role, id }
175 }
176
177 fn role_range(role: Role) -> (Bound<Self>, Bound<Self>) {
178 (
179 Bound::Included(Self::new(role, u64::MIN)),
180 Bound::Included(Self::new(role, u64::MAX)),
181 )
182 }
183}
184
185pub type DeregisterSignalReceiver = watch::Receiver<bool>;
187
188pub struct Pusher {
190 sender: Sender<std::result::Result<HeartbeatResponse, tonic::Status>>,
191 deregister_signal_sender: watch::Sender<bool>,
195 deregister_signal_receiver: DeregisterSignalReceiver,
196
197 res_header: ResponseHeader,
198}
199
200impl Drop for Pusher {
201 fn drop(&mut self) {
202 let _ = self.deregister_signal_sender.send(true);
205 }
206}
207
208impl Pusher {
209 pub fn new(sender: Sender<std::result::Result<HeartbeatResponse, tonic::Status>>) -> Self {
210 let res_header = ResponseHeader {
211 protocol_version: PROTOCOL_VERSION,
212 ..Default::default()
213 };
214 let (deregister_signal_sender, deregister_signal_receiver) = watch::channel(false);
215 Self {
216 sender,
217 deregister_signal_sender,
218 deregister_signal_receiver,
219 res_header,
220 }
221 }
222
223 #[inline]
224 pub async fn push(&self, res: HeartbeatResponse) -> Result<()> {
225 self.sender.send(Ok(res)).await.map_err(|e| {
226 error::PushMessageSnafu {
227 err_msg: e.to_string(),
228 }
229 .build()
230 })
231 }
232
233 #[inline]
234 pub fn header(&self) -> ResponseHeader {
235 self.res_header.clone()
236 }
237}
238
239#[derive(Clone, Default)]
241pub struct Pushers(Arc<RwLock<BTreeMap<PusherId, Pusher>>>);
242
243impl Pushers {
244 async fn push(
245 &self,
246 pusher_id: PusherId,
247 mailbox_message: MailboxMessage,
248 ) -> Result<DeregisterSignalReceiver> {
249 let pushers = self.0.read().await;
250 let pusher = pushers
251 .get(&pusher_id)
252 .with_context(|| error::PusherNotFoundSnafu {
253 pusher_id: pusher_id.to_string(),
254 })?;
255
256 pusher
257 .push(HeartbeatResponse {
258 header: Some(pusher.header()),
259 mailbox_message: Some(mailbox_message),
260 ..Default::default()
261 })
262 .await?;
263
264 Ok(pusher.deregister_signal_receiver.clone())
265 }
266
267 async fn broadcast(&self, role: Role, mailbox_message: &MailboxMessage) -> Result<()> {
268 let pushers = self.0.read().await;
269 let pushers = pushers
270 .range(PusherId::role_range(role))
271 .map(|(_, value)| value)
272 .collect::<Vec<_>>();
273 let mut results = Vec::with_capacity(pushers.len());
274
275 for pusher in pushers {
276 let mut mailbox_message = mailbox_message.clone();
277 mailbox_message.id = 0; results.push(pusher.push(HeartbeatResponse {
280 header: Some(pusher.header()),
281 mailbox_message: Some(mailbox_message),
282 ..Default::default()
283 }))
284 }
285
286 let _ = join_all(results)
288 .await
289 .into_iter()
290 .collect::<Result<Vec<_>>>()?;
291
292 Ok(())
293 }
294
295 pub(crate) async fn insert(&self, pusher_id: PusherId, pusher: Pusher) -> Option<Pusher> {
296 self.0.write().await.insert(pusher_id, pusher)
297 }
298
299 async fn remove(&self, pusher_id: PusherId) -> Option<Pusher> {
300 self.0.write().await.remove(&pusher_id)
301 }
302}
303
304#[derive(Clone)]
305pub struct NameCachedHandler {
306 name: &'static str,
307 handler: Arc<dyn HeartbeatHandler>,
308}
309
310impl NameCachedHandler {
311 fn new(handler: impl HeartbeatHandler + 'static) -> Self {
312 let name = handler.name();
313 let handler = Arc::new(handler);
314 Self { name, handler }
315 }
316}
317
318pub type HeartbeatHandlerGroupRef = Arc<HeartbeatHandlerGroup>;
319
320#[derive(Default, Clone)]
322pub struct HeartbeatHandlerGroup {
323 handlers: Vec<NameCachedHandler>,
324 pushers: Pushers,
325}
326
327impl HeartbeatHandlerGroup {
328 pub async fn register_pusher(&self, pusher_id: PusherId, pusher: Pusher) {
330 METRIC_META_HEARTBEAT_CONNECTION_NUM.inc();
331 info!("Pusher register: {}", pusher_id);
332 let _ = self.pushers.insert(pusher_id, pusher).await;
333 }
334
335 pub async fn deregister_push(&self, pusher_id: PusherId) {
337 if self.pushers.remove(pusher_id).await.is_some() {
338 info!("Pusher unregister: {}", pusher_id);
339 METRIC_META_HEARTBEAT_CONNECTION_NUM.dec();
340 }
341 }
342
343 #[cfg(test)]
344 pub async fn contains_pusher(&self, pusher_id: &PusherId) -> bool {
346 let pushers = self.pushers.0.read().await;
347 pushers.contains_key(pusher_id)
348 }
349
350 pub fn pushers(&self) -> Pushers {
352 self.pushers.clone()
353 }
354
355 pub async fn handle(
357 &self,
358 req: HeartbeatRequest,
359 mut ctx: Context,
360 ) -> Result<HeartbeatResponse> {
361 let mut acc = HeartbeatAccumulator::default();
362 let role = req
363 .header
364 .as_ref()
365 .and_then(|h| Role::try_from(h.role).ok())
366 .context(error::InvalidArgumentsSnafu {
367 err_msg: format!("invalid role: {:?}", req.header),
368 })?;
369
370 let is_handshake = ctx.is_handshake;
371
372 for NameCachedHandler { name, handler } in self.handlers.iter() {
373 if !handler.is_acceptable(role) {
374 continue;
375 }
376
377 let _timer = METRIC_META_HANDLER_EXECUTE
378 .with_label_values(&[*name])
379 .start_timer();
380
381 if handler.handle(&req, &mut ctx, &mut acc).await? == HandleControl::Done {
382 break;
383 }
384 }
385 let header = std::mem::take(&mut acc.header);
386 let mailbox_message = acc.take_mailbox_message();
387
388 let heartbeat_config = if is_handshake {
390 let config = ctx.heartbeat_options_for(role).into();
391
392 info!(
393 "Handshake with {:?} node, sending config: {:?}",
394 role, config
395 );
396
397 Some(config)
398 } else {
399 None
400 };
401
402 let res = HeartbeatResponse {
403 header,
404 region_lease: acc.region_lease,
405 mailbox_message,
406 heartbeat_config,
407 };
408 Ok(res)
409 }
410}
411
412pub struct HeartbeatMailbox {
413 pushers: Pushers,
414 sequence: Sequence,
415 senders: DashMap<MessageId, oneshot::Sender<Result<MailboxMessage>>>,
416 timeouts: DashMap<MessageId, Instant>,
417 timeout_notify: Notify,
418}
419
420impl HeartbeatMailbox {
421 pub fn json_reply(msg: &MailboxMessage) -> Result<InstructionReply> {
422 let Payload::Json(payload) =
423 msg.payload
424 .as_ref()
425 .with_context(|| UnexpectedInstructionReplySnafu {
426 mailbox_message: msg.to_string(),
427 reason: format!("empty payload, msg: {msg:?}"),
428 })?;
429 serde_json::from_str(payload).context(DeserializeFromJsonSnafu { input: payload })
430 }
431
432 #[cfg(test)]
434 pub(crate) fn json_instruction(
435 msg: &MailboxMessage,
436 ) -> Result<common_meta::instruction::Instruction> {
437 let Payload::Json(payload) =
438 msg.payload
439 .as_ref()
440 .with_context(|| UnexpectedInstructionReplySnafu {
441 mailbox_message: msg.to_string(),
442 reason: format!("empty payload, msg: {msg:?}"),
443 })?;
444 serde_json::from_str(payload).context(DeserializeFromJsonSnafu { input: payload })
445 }
446
447 pub fn create(pushers: Pushers, sequence: Sequence) -> MailboxRef {
448 let mailbox = Arc::new(Self::new(pushers, sequence));
449
450 let timeout_checker = mailbox.clone();
451 let _handle = common_runtime::spawn_global(async move {
452 timeout_checker.check_timeout_bg(10).await;
453 });
454
455 mailbox
456 }
457
458 fn new(pushers: Pushers, sequence: Sequence) -> Self {
459 Self {
460 pushers,
461 sequence,
462 senders: DashMap::default(),
463 timeouts: DashMap::default(),
464 timeout_notify: Notify::new(),
465 }
466 }
467
468 async fn check_timeout_bg(&self, interval_millis: u64) {
469 let mut interval = tokio::time::interval(Duration::from_millis(interval_millis));
470
471 loop {
472 let _ = interval.tick().await;
473
474 if self.timeouts.is_empty() {
475 self.timeout_notify.notified().await;
476 }
477
478 let now = Instant::now();
479 let timeout_ids = self
480 .timeouts
481 .iter()
482 .filter_map(|entry| {
483 let (id, deadline) = entry.pair();
484 if deadline < &now { Some(*id) } else { None }
485 })
486 .collect::<Vec<_>>();
487
488 for id in timeout_ids {
489 let _ = self
490 .on_recv(id, Err(error::MailboxTimeoutSnafu { id }.build()))
491 .await;
492 }
493 }
494 }
495
496 #[inline]
497 async fn next_message_id(&self) -> Result<u64> {
498 loop {
501 let next = self
502 .sequence
503 .next()
504 .await
505 .context(error::NextSequenceSnafu)?;
506 if next > 0 {
507 return Ok(next);
508 }
509 }
510 }
511}
512
513#[async_trait::async_trait]
514impl Mailbox for HeartbeatMailbox {
515 async fn send(
516 &self,
517 ch: &Channel,
518 mut msg: MailboxMessage,
519 timeout: Duration,
520 ) -> Result<MailboxReceiver> {
521 let message_id = self.next_message_id().await?;
522 msg.id = message_id;
523
524 let pusher_id = ch.pusher_id();
525 debug!("Sending mailbox message {msg:?} to {pusher_id}");
526
527 let (tx, rx) = oneshot::channel();
528 let _ = self.senders.insert(message_id, tx);
529 let deadline = Instant::now() + timeout;
530 self.timeouts.insert(message_id, deadline);
531 self.timeout_notify.notify_one();
532 let deregister_signal_receiver = self.pushers.push(pusher_id, msg).await?;
533
534 Ok(MailboxReceiver::new(
535 message_id,
536 rx,
537 deregister_signal_receiver,
538 *ch,
539 ))
540 }
541
542 async fn send_oneway(&self, ch: &Channel, mut msg: MailboxMessage) -> Result<()> {
543 let message_id = 0; msg.id = message_id;
545
546 let pusher_id = ch.pusher_id();
547 debug!("Sending mailbox message {msg:?} to {pusher_id}");
548
549 self.pushers.push(pusher_id, msg).await?;
550
551 Ok(())
552 }
553
554 async fn broadcast(&self, ch: &BroadcastChannel, msg: &MailboxMessage) -> Result<()> {
555 self.pushers.broadcast(ch.role(), msg).await
556 }
557
558 async fn on_recv(&self, id: MessageId, maybe_msg: Result<MailboxMessage>) -> Result<()> {
559 debug!("Received mailbox message {maybe_msg:?}");
560
561 let _ = self.timeouts.remove(&id);
562
563 if let Some((_, tx)) = self.senders.remove(&id) {
564 tx.send(maybe_msg)
565 .map_err(|_| error::MailboxClosedSnafu { id }.build())?;
566 } else if let Ok(finally_msg) = maybe_msg {
567 warn!("The response arrived too late: {finally_msg:?}");
568 }
569
570 Ok(())
571 }
572}
573
574pub struct HeartbeatHandlerGroupBuilder {
576 region_failure_handler: Option<RegionFailureHandler>,
578
579 region_lease_handler: Option<RegionLeaseHandler>,
581
582 flush_stats_factor: Option<usize>,
586 flow_state_handler: Option<FlowStateHandler>,
588
589 persist_stats_handler: Option<PersistStatsHandler>,
591
592 plugins: Option<Plugins>,
594
595 pushers: Pushers,
597
598 handlers: Vec<NameCachedHandler>,
600}
601
602impl HeartbeatHandlerGroupBuilder {
603 pub fn new(pushers: Pushers) -> Self {
604 Self {
605 region_failure_handler: None,
606 region_lease_handler: None,
607 flush_stats_factor: None,
608 flow_state_handler: None,
609 persist_stats_handler: None,
610 plugins: None,
611 pushers,
612 handlers: vec![],
613 }
614 }
615
616 pub fn with_flow_state_handler(mut self, handler: Option<FlowStateHandler>) -> Self {
617 self.flow_state_handler = handler;
618 self
619 }
620
621 pub fn with_region_lease_handler(mut self, handler: Option<RegionLeaseHandler>) -> Self {
622 self.region_lease_handler = handler;
623 self
624 }
625
626 pub fn with_region_failure_handler(mut self, handler: Option<RegionFailureHandler>) -> Self {
628 self.region_failure_handler = handler;
629 self
630 }
631
632 pub fn with_flush_stats_factor(mut self, flush_stats_factor: Option<usize>) -> Self {
634 self.flush_stats_factor = flush_stats_factor;
635 self
636 }
637
638 pub fn with_persist_stats_handler(mut self, handler: Option<PersistStatsHandler>) -> Self {
639 self.persist_stats_handler = handler;
640 self
641 }
642
643 pub fn with_plugins(mut self, plugins: Option<Plugins>) -> Self {
645 self.plugins = plugins;
646 self
647 }
648
649 pub fn add_default_handlers(mut self) -> Self {
651 let publish_heartbeat_handler = if let Some(plugins) = self.plugins.as_ref() {
653 plugins
654 .get::<PublisherRef>()
655 .map(|publish| PublishHeartbeatHandler::new(publish.clone()))
656 } else {
657 None
658 };
659
660 self.add_handler_last(ResponseHeaderHandler);
661 self.add_handler_last(DatanodeKeepLeaseHandler);
665 self.add_handler_last(FlownodeKeepLeaseHandler);
666 self.add_handler_last(CheckLeaderHandler);
667 self.add_handler_last(OnLeaderStartHandler);
668 self.add_handler_last(ExtractStatHandler);
669 self.add_handler_last(CollectDatanodeClusterInfoHandler);
670 self.add_handler_last(CollectFrontendClusterInfoHandler);
671 self.add_handler_last(CollectFlownodeClusterInfoHandler);
672 self.add_handler_last(MailboxHandler);
673 if let Some(region_lease_handler) = self.region_lease_handler.take() {
674 self.add_handler_last(region_lease_handler);
675 }
676 self.add_handler_last(FilterInactiveRegionStatsHandler);
677 if let Some(region_failure_handler) = self.region_failure_handler.take() {
678 self.add_handler_last(region_failure_handler);
679 }
680 if let Some(publish_heartbeat_handler) = publish_heartbeat_handler {
681 self.add_handler_last(publish_heartbeat_handler);
682 }
683 self.add_handler_last(CollectLeaderRegionHandler);
684 self.add_handler_last(CollectTopicStatsHandler);
685 if let Some(persist_stats_handler) = self.persist_stats_handler.take() {
688 self.add_handler_last(persist_stats_handler);
689 }
690 self.add_handler_last(CollectStatsHandler::new(self.flush_stats_factor));
691 self.add_handler_last(RemapFlowPeerHandler::default());
692
693 if let Some(flow_state_handler) = self.flow_state_handler.take() {
694 self.add_handler_last(flow_state_handler);
695 }
696
697 self
698 }
699
700 pub fn build(mut self) -> Result<HeartbeatHandlerGroup> {
704 if let Some(customizer) = self
705 .plugins
706 .as_ref()
707 .and_then(|plugins| plugins.get::<HeartbeatHandlerGroupBuilderCustomizerRef>())
708 {
709 debug!("Customizing the heartbeat handler group builder");
710 customizer.customize(&mut self)?;
711 }
712
713 Ok(HeartbeatHandlerGroup {
714 handlers: self.handlers,
715 pushers: self.pushers,
716 })
717 }
718
719 fn add_handler_after_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
720 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
721 self.handlers.insert(pos + 1, handler);
722 return Ok(());
723 }
724
725 error::HandlerNotFoundSnafu { name: target }.fail()
726 }
727
728 pub fn add_handler_after(
730 &mut self,
731 target: &'static str,
732 handler: impl HeartbeatHandler + 'static,
733 ) -> Result<()> {
734 self.add_handler_after_inner(target, NameCachedHandler::new(handler))
735 }
736
737 fn add_handler_before_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
738 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
739 self.handlers.insert(pos, handler);
740 return Ok(());
741 }
742
743 error::HandlerNotFoundSnafu { name: target }.fail()
744 }
745
746 pub fn add_handler_before(
748 &mut self,
749 target: &'static str,
750 handler: impl HeartbeatHandler + 'static,
751 ) -> Result<()> {
752 self.add_handler_before_inner(target, NameCachedHandler::new(handler))
753 }
754
755 fn replace_handler_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
756 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
757 self.handlers[pos] = handler;
758 return Ok(());
759 }
760
761 error::HandlerNotFoundSnafu { name: target }.fail()
762 }
763
764 pub fn replace_handler(
766 &mut self,
767 target: &'static str,
768 handler: impl HeartbeatHandler + 'static,
769 ) -> Result<()> {
770 self.replace_handler_inner(target, NameCachedHandler::new(handler))
771 }
772
773 fn add_handler_last_inner(&mut self, handler: NameCachedHandler) {
774 self.handlers.push(handler);
775 }
776
777 fn add_handler_last(&mut self, handler: impl HeartbeatHandler + 'static) {
778 self.add_handler_last_inner(NameCachedHandler::new(handler));
779 }
780}
781
782pub type HeartbeatHandlerGroupBuilderCustomizerRef =
783 Arc<dyn HeartbeatHandlerGroupBuilderCustomizer>;
784
785pub enum CustomizeHeartbeatGroupAction {
786 AddHandlerAfter {
787 target: String,
788 handler: NameCachedHandler,
789 },
790 AddHandlerBefore {
791 target: String,
792 handler: NameCachedHandler,
793 },
794 ReplaceHandler {
795 target: String,
796 handler: NameCachedHandler,
797 },
798 AddHandlerLast {
799 handler: NameCachedHandler,
800 },
801}
802
803impl CustomizeHeartbeatGroupAction {
804 pub fn new_add_handler_after(
805 target: &'static str,
806 handler: impl HeartbeatHandler + 'static,
807 ) -> Self {
808 Self::AddHandlerAfter {
809 target: target.to_string(),
810 handler: NameCachedHandler::new(handler),
811 }
812 }
813
814 pub fn new_add_handler_before(
815 target: &'static str,
816 handler: impl HeartbeatHandler + 'static,
817 ) -> Self {
818 Self::AddHandlerBefore {
819 target: target.to_string(),
820 handler: NameCachedHandler::new(handler),
821 }
822 }
823
824 pub fn new_replace_handler(
825 target: &'static str,
826 handler: impl HeartbeatHandler + 'static,
827 ) -> Self {
828 Self::ReplaceHandler {
829 target: target.to_string(),
830 handler: NameCachedHandler::new(handler),
831 }
832 }
833
834 pub fn new_add_handler_last(handler: impl HeartbeatHandler + 'static) -> Self {
835 Self::AddHandlerLast {
836 handler: NameCachedHandler::new(handler),
837 }
838 }
839}
840
841pub trait HeartbeatHandlerGroupBuilderCustomizer: Send + Sync {
843 fn customize(&self, builder: &mut HeartbeatHandlerGroupBuilder) -> Result<()>;
844
845 fn add_action(&self, action: CustomizeHeartbeatGroupAction);
846}
847
848#[derive(Default)]
849pub struct DefaultHeartbeatHandlerGroupBuilderCustomizer {
850 actions: Mutex<Vec<CustomizeHeartbeatGroupAction>>,
851}
852
853impl HeartbeatHandlerGroupBuilderCustomizer for DefaultHeartbeatHandlerGroupBuilderCustomizer {
854 fn customize(&self, builder: &mut HeartbeatHandlerGroupBuilder) -> Result<()> {
855 info!("Customizing the heartbeat handler group builder");
856 let mut actions = self.actions.lock().unwrap();
857 for action in actions.drain(..) {
858 match action {
859 CustomizeHeartbeatGroupAction::AddHandlerAfter { target, handler } => {
860 builder.add_handler_after_inner(&target, handler)?;
861 }
862 CustomizeHeartbeatGroupAction::AddHandlerBefore { target, handler } => {
863 builder.add_handler_before_inner(&target, handler)?;
864 }
865 CustomizeHeartbeatGroupAction::ReplaceHandler { target, handler } => {
866 builder.replace_handler_inner(&target, handler)?;
867 }
868 CustomizeHeartbeatGroupAction::AddHandlerLast { handler } => {
869 builder.add_handler_last_inner(handler);
870 }
871 }
872 }
873 Ok(())
874 }
875
876 fn add_action(&self, action: CustomizeHeartbeatGroupAction) {
877 self.actions.lock().unwrap().push(action);
878 }
879}
880
881#[cfg(test)]
882mod tests {
883
884 use std::assert_matches;
885 use std::collections::BTreeMap;
886 use std::sync::Arc;
887 use std::time::Duration;
888
889 use api::v1::meta::{MailboxMessage, Role};
890 use common_meta::kv_backend::memory::MemoryKvBackend;
891 use common_meta::sequence::SequenceBuilder;
892 use tokio::sync::mpsc;
893
894 use super::{HeartbeatHandlerGroupBuilder, PusherId, Pushers};
895 use crate::error;
896 use crate::handler::collect_stats_handler::CollectStatsHandler;
897 use crate::handler::response_header_handler::ResponseHeaderHandler;
898 use crate::handler::{HeartbeatHandlerGroup, HeartbeatMailbox, Pusher};
899 use crate::service::mailbox::{Channel, MailboxReceiver, MailboxRef};
900
901 #[tokio::test]
902 async fn test_mailbox() {
903 let (mailbox, receiver) = push_msg_via_mailbox().await;
904 let id = receiver.message_id();
905
906 let resp_msg = MailboxMessage {
907 id,
908 subject: "resp-test".to_string(),
909 timestamp_millis: 456,
910 ..Default::default()
911 };
912
913 mailbox.on_recv(id, Ok(resp_msg)).await.unwrap();
914
915 let recv_msg = receiver.await.unwrap();
916 assert_eq!(recv_msg.id, id);
917 assert_eq!(recv_msg.timestamp_millis, 456);
918 assert_eq!(recv_msg.subject, "resp-test".to_string());
919 }
920
921 #[tokio::test]
922 async fn test_mailbox_timeout() {
923 let (_, receiver) = push_msg_via_mailbox().await;
924 let res = receiver.await;
925 assert!(res.is_err());
926 }
927
928 async fn push_msg_via_mailbox() -> (MailboxRef, MailboxReceiver) {
929 let datanode_id = 12;
930 let (pusher_tx, mut pusher_rx) = mpsc::channel(16);
931 let pusher_id = PusherId::new(Role::Datanode, datanode_id);
932 let pusher: Pusher = Pusher::new(pusher_tx);
933 let handler_group = HeartbeatHandlerGroup::default();
934 handler_group.register_pusher(pusher_id, pusher).await;
935
936 let kv_backend = Arc::new(MemoryKvBackend::new());
937 let seq = SequenceBuilder::new("test_seq", kv_backend).build();
938 let mailbox = HeartbeatMailbox::create(handler_group.pushers(), seq);
939
940 let msg = MailboxMessage {
941 id: 0,
942 subject: "req-test".to_string(),
943 timestamp_millis: 123,
944 ..Default::default()
945 };
946 let ch = Channel::Datanode(datanode_id);
947
948 let receiver = mailbox
949 .send(&ch, msg, Duration::from_secs(1))
950 .await
951 .unwrap();
952
953 let recv_obj = pusher_rx.recv().await.unwrap().unwrap();
954 let message = recv_obj.mailbox_message.unwrap();
955 assert_eq!(message.timestamp_millis, 123);
956 assert_eq!(message.subject, "req-test".to_string());
957
958 (mailbox, receiver)
959 }
960
961 #[test]
962 fn test_pusher_id_role_range() {
963 let mut pushers = BTreeMap::new();
964 pushers.insert(PusherId::new(Role::Datanode, u64::MAX), "datanode");
965 pushers.insert(PusherId::new(Role::Frontend, u64::MIN), "frontend-min");
966 pushers.insert(PusherId::new(Role::Frontend, u64::MAX), "frontend-max");
967 pushers.insert(PusherId::new(Role::Flownode, u64::MIN), "flownode");
968
969 let frontend_pushers = pushers
970 .range(PusherId::role_range(Role::Frontend))
971 .map(|(_, value)| *value)
972 .collect::<Vec<_>>();
973
974 assert_eq!(frontend_pushers, vec!["frontend-min", "frontend-max"]);
975 }
976
977 #[tokio::test]
978 async fn test_pushers_broadcast_by_role() {
979 let pushers = Pushers::default();
980 let (datanode_tx, mut datanode_rx) = mpsc::channel(1);
981 let (frontend_tx, mut frontend_rx) = mpsc::channel(1);
982 let (flownode_tx, mut flownode_rx) = mpsc::channel(1);
983
984 pushers
985 .insert(
986 PusherId::new(Role::Datanode, u64::MAX),
987 Pusher::new(datanode_tx),
988 )
989 .await;
990 pushers
991 .insert(PusherId::new(Role::Frontend, 1), Pusher::new(frontend_tx))
992 .await;
993 pushers
994 .insert(
995 PusherId::new(Role::Flownode, u64::MIN),
996 Pusher::new(flownode_tx),
997 )
998 .await;
999
1000 let msg = MailboxMessage {
1001 id: 42,
1002 subject: "broadcast-test".to_string(),
1003 timestamp_millis: 123,
1004 ..Default::default()
1005 };
1006
1007 pushers.broadcast(Role::Frontend, &msg).await.unwrap();
1008
1009 let received = frontend_rx.recv().await.unwrap().unwrap();
1010 let mailbox_message = received.mailbox_message.unwrap();
1011 assert_eq!(mailbox_message.id, 0);
1012 assert_eq!(mailbox_message.subject, "broadcast-test");
1013 assert!(datanode_rx.try_recv().is_err());
1014 assert!(flownode_rx.try_recv().is_err());
1015 }
1016
1017 #[test]
1018 fn test_handler_group_builder() {
1019 let group = HeartbeatHandlerGroupBuilder::new(Pushers::default())
1020 .add_default_handlers()
1021 .build()
1022 .unwrap();
1023
1024 let handlers = group.handlers;
1025 let names = [
1026 "ResponseHeaderHandler",
1027 "DatanodeKeepLeaseHandler",
1028 "FlownodeKeepLeaseHandler",
1029 "CheckLeaderHandler",
1030 "OnLeaderStartHandler",
1031 "ExtractStatHandler",
1032 "CollectDatanodeClusterInfoHandler",
1033 "CollectFrontendClusterInfoHandler",
1034 "CollectFlownodeClusterInfoHandler",
1035 "MailboxHandler",
1036 "FilterInactiveRegionStatsHandler",
1037 "CollectLeaderRegionHandler",
1038 "CollectTopicStatsHandler",
1039 "CollectStatsHandler",
1040 "RemapFlowPeerHandler",
1041 ];
1042 assert_eq!(names.len(), handlers.len());
1043 for (handler, name) in handlers.iter().zip(names) {
1044 assert_eq!(handler.name, name);
1045 }
1046 }
1047
1048 #[test]
1049 fn test_handler_group_builder_add_before() {
1050 let mut builder =
1051 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1052 builder
1053 .add_handler_before(
1054 "FilterInactiveRegionStatsHandler",
1055 CollectStatsHandler::default(),
1056 )
1057 .unwrap();
1058
1059 let group = builder.build().unwrap();
1060 let handlers = group.handlers;
1061 let names = [
1062 "ResponseHeaderHandler",
1063 "DatanodeKeepLeaseHandler",
1064 "FlownodeKeepLeaseHandler",
1065 "CheckLeaderHandler",
1066 "OnLeaderStartHandler",
1067 "ExtractStatHandler",
1068 "CollectDatanodeClusterInfoHandler",
1069 "CollectFrontendClusterInfoHandler",
1070 "CollectFlownodeClusterInfoHandler",
1071 "MailboxHandler",
1072 "CollectStatsHandler",
1073 "FilterInactiveRegionStatsHandler",
1074 "CollectLeaderRegionHandler",
1075 "CollectTopicStatsHandler",
1076 "CollectStatsHandler",
1077 "RemapFlowPeerHandler",
1078 ];
1079 assert_eq!(names.len(), handlers.len());
1080 for (handler, name) in handlers.iter().zip(names) {
1081 assert_eq!(handler.name, name);
1082 }
1083 }
1084
1085 #[test]
1086 fn test_handler_group_builder_add_before_first() {
1087 let mut builder =
1088 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1089 builder
1090 .add_handler_before("ResponseHeaderHandler", CollectStatsHandler::default())
1091 .unwrap();
1092
1093 let group = builder.build().unwrap();
1094 let handlers = group.handlers;
1095 let names = [
1096 "CollectStatsHandler",
1097 "ResponseHeaderHandler",
1098 "DatanodeKeepLeaseHandler",
1099 "FlownodeKeepLeaseHandler",
1100 "CheckLeaderHandler",
1101 "OnLeaderStartHandler",
1102 "ExtractStatHandler",
1103 "CollectDatanodeClusterInfoHandler",
1104 "CollectFrontendClusterInfoHandler",
1105 "CollectFlownodeClusterInfoHandler",
1106 "MailboxHandler",
1107 "FilterInactiveRegionStatsHandler",
1108 "CollectLeaderRegionHandler",
1109 "CollectTopicStatsHandler",
1110 "CollectStatsHandler",
1111 "RemapFlowPeerHandler",
1112 ];
1113 assert_eq!(names.len(), handlers.len());
1114 for (handler, name) in handlers.iter().zip(names) {
1115 assert_eq!(handler.name, name);
1116 }
1117 }
1118
1119 #[test]
1120 fn test_handler_group_builder_add_after() {
1121 let mut builder =
1122 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1123 builder
1124 .add_handler_after("MailboxHandler", CollectStatsHandler::default())
1125 .unwrap();
1126
1127 let group = builder.build().unwrap();
1128 let handlers = group.handlers;
1129 let names = [
1130 "ResponseHeaderHandler",
1131 "DatanodeKeepLeaseHandler",
1132 "FlownodeKeepLeaseHandler",
1133 "CheckLeaderHandler",
1134 "OnLeaderStartHandler",
1135 "ExtractStatHandler",
1136 "CollectDatanodeClusterInfoHandler",
1137 "CollectFrontendClusterInfoHandler",
1138 "CollectFlownodeClusterInfoHandler",
1139 "MailboxHandler",
1140 "CollectStatsHandler",
1141 "FilterInactiveRegionStatsHandler",
1142 "CollectLeaderRegionHandler",
1143 "CollectTopicStatsHandler",
1144 "CollectStatsHandler",
1145 "RemapFlowPeerHandler",
1146 ];
1147 assert_eq!(names.len(), handlers.len());
1148 for (handler, name) in handlers.iter().zip(names) {
1149 assert_eq!(handler.name, name);
1150 }
1151 }
1152
1153 #[test]
1154 fn test_handler_group_builder_add_after_last() {
1155 let mut builder =
1156 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1157 builder
1158 .add_handler_after("CollectStatsHandler", ResponseHeaderHandler)
1159 .unwrap();
1160
1161 let group = builder.build().unwrap();
1162 let handlers = group.handlers;
1163 let names = [
1164 "ResponseHeaderHandler",
1165 "DatanodeKeepLeaseHandler",
1166 "FlownodeKeepLeaseHandler",
1167 "CheckLeaderHandler",
1168 "OnLeaderStartHandler",
1169 "ExtractStatHandler",
1170 "CollectDatanodeClusterInfoHandler",
1171 "CollectFrontendClusterInfoHandler",
1172 "CollectFlownodeClusterInfoHandler",
1173 "MailboxHandler",
1174 "FilterInactiveRegionStatsHandler",
1175 "CollectLeaderRegionHandler",
1176 "CollectTopicStatsHandler",
1177 "CollectStatsHandler",
1178 "ResponseHeaderHandler",
1179 "RemapFlowPeerHandler",
1180 ];
1181 assert_eq!(names.len(), handlers.len());
1182 for (handler, name) in handlers.iter().zip(names) {
1183 assert_eq!(handler.name, name);
1184 }
1185 }
1186
1187 #[test]
1188 fn test_handler_group_builder_replace() {
1189 let mut builder =
1190 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1191 builder
1192 .replace_handler("MailboxHandler", CollectStatsHandler::default())
1193 .unwrap();
1194
1195 let group = builder.build().unwrap();
1196 let handlers = group.handlers;
1197 let names = [
1198 "ResponseHeaderHandler",
1199 "DatanodeKeepLeaseHandler",
1200 "FlownodeKeepLeaseHandler",
1201 "CheckLeaderHandler",
1202 "OnLeaderStartHandler",
1203 "ExtractStatHandler",
1204 "CollectDatanodeClusterInfoHandler",
1205 "CollectFrontendClusterInfoHandler",
1206 "CollectFlownodeClusterInfoHandler",
1207 "CollectStatsHandler",
1208 "FilterInactiveRegionStatsHandler",
1209 "CollectLeaderRegionHandler",
1210 "CollectTopicStatsHandler",
1211 "CollectStatsHandler",
1212 "RemapFlowPeerHandler",
1213 ];
1214
1215 assert_eq!(names.len(), handlers.len());
1216 for (handler, name) in handlers.iter().zip(names) {
1217 assert_eq!(handler.name, name);
1218 }
1219 }
1220
1221 #[test]
1222 fn test_handler_group_builder_replace_last() {
1223 let mut builder =
1224 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1225 builder
1226 .replace_handler("CollectStatsHandler", ResponseHeaderHandler)
1227 .unwrap();
1228
1229 let group = builder.build().unwrap();
1230 let handlers = group.handlers;
1231 let names = [
1232 "ResponseHeaderHandler",
1233 "DatanodeKeepLeaseHandler",
1234 "FlownodeKeepLeaseHandler",
1235 "CheckLeaderHandler",
1236 "OnLeaderStartHandler",
1237 "ExtractStatHandler",
1238 "CollectDatanodeClusterInfoHandler",
1239 "CollectFrontendClusterInfoHandler",
1240 "CollectFlownodeClusterInfoHandler",
1241 "MailboxHandler",
1242 "FilterInactiveRegionStatsHandler",
1243 "CollectLeaderRegionHandler",
1244 "CollectTopicStatsHandler",
1245 "ResponseHeaderHandler",
1246 "RemapFlowPeerHandler",
1247 ];
1248
1249 assert_eq!(names.len(), handlers.len());
1250 for (handler, name) in handlers.iter().zip(names) {
1251 assert_eq!(handler.name, name);
1252 }
1253 }
1254
1255 #[test]
1256 fn test_handler_group_builder_replace_first() {
1257 let mut builder =
1258 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1259 builder
1260 .replace_handler("ResponseHeaderHandler", CollectStatsHandler::default())
1261 .unwrap();
1262
1263 let group = builder.build().unwrap();
1264 let handlers = group.handlers;
1265 let names = [
1266 "CollectStatsHandler",
1267 "DatanodeKeepLeaseHandler",
1268 "FlownodeKeepLeaseHandler",
1269 "CheckLeaderHandler",
1270 "OnLeaderStartHandler",
1271 "ExtractStatHandler",
1272 "CollectDatanodeClusterInfoHandler",
1273 "CollectFrontendClusterInfoHandler",
1274 "CollectFlownodeClusterInfoHandler",
1275 "MailboxHandler",
1276 "FilterInactiveRegionStatsHandler",
1277 "CollectLeaderRegionHandler",
1278 "CollectTopicStatsHandler",
1279 "CollectStatsHandler",
1280 "RemapFlowPeerHandler",
1281 ];
1282 assert_eq!(names.len(), handlers.len());
1283 for (handler, name) in handlers.iter().zip(names) {
1284 assert_eq!(handler.name, name);
1285 }
1286 }
1287
1288 #[test]
1289 fn test_handler_group_builder_handler_not_found() {
1290 let mut builder =
1291 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1292 let err = builder
1293 .add_handler_before("NotExists", CollectStatsHandler::default())
1294 .unwrap_err();
1295 assert_matches!(err, error::Error::HandlerNotFound { .. });
1296
1297 let err = builder
1298 .add_handler_after("NotExists", CollectStatsHandler::default())
1299 .unwrap_err();
1300 assert_matches!(err, error::Error::HandlerNotFound { .. });
1301
1302 let err = builder
1303 .replace_handler("NotExists", CollectStatsHandler::default())
1304 .unwrap_err();
1305 assert_matches!(err, error::Error::HandlerNotFound { .. });
1306 }
1307
1308 #[tokio::test]
1309 async fn test_pusher_drop() {
1310 let (tx, _rx) = mpsc::channel(1);
1311 let pusher = Pusher::new(tx);
1312 let mut deregister_signal_tx = pusher.deregister_signal_receiver.clone();
1313
1314 drop(pusher);
1315 deregister_signal_tx.changed().await.unwrap();
1316 }
1317}