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 HeartbeatConfig, HeartbeatRequest, HeartbeatResponse, MailboxMessage, PROTOCOL_VERSION,
25 RegionLease, 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 mut config: HeartbeatConfig = ctx.heartbeat_options_for(role).into();
391 config.gc_enabled = ctx.gc_enabled;
392
393 info!(
394 "Handshake with {:?} node, sending config: {:?}",
395 role, config
396 );
397
398 Some(config)
399 } else {
400 None
401 };
402
403 let res = HeartbeatResponse {
404 header,
405 region_lease: acc.region_lease,
406 mailbox_message,
407 heartbeat_config,
408 };
409 Ok(res)
410 }
411}
412
413pub struct HeartbeatMailbox {
414 pushers: Pushers,
415 sequence: Sequence,
416 senders: DashMap<MessageId, oneshot::Sender<Result<MailboxMessage>>>,
417 timeouts: DashMap<MessageId, Instant>,
418 timeout_notify: Notify,
419}
420
421impl HeartbeatMailbox {
422 pub fn json_reply(msg: &MailboxMessage) -> Result<InstructionReply> {
423 let Payload::Json(payload) =
424 msg.payload
425 .as_ref()
426 .with_context(|| UnexpectedInstructionReplySnafu {
427 mailbox_message: msg.to_string(),
428 reason: format!("empty payload, msg: {msg:?}"),
429 })?;
430 serde_json::from_str(payload).context(DeserializeFromJsonSnafu { input: payload })
431 }
432
433 #[cfg(test)]
435 pub(crate) fn json_instruction(
436 msg: &MailboxMessage,
437 ) -> Result<common_meta::instruction::Instruction> {
438 let Payload::Json(payload) =
439 msg.payload
440 .as_ref()
441 .with_context(|| UnexpectedInstructionReplySnafu {
442 mailbox_message: msg.to_string(),
443 reason: format!("empty payload, msg: {msg:?}"),
444 })?;
445 serde_json::from_str(payload).context(DeserializeFromJsonSnafu { input: payload })
446 }
447
448 pub fn create(pushers: Pushers, sequence: Sequence) -> MailboxRef {
449 let mailbox = Arc::new(Self::new(pushers, sequence));
450
451 let timeout_checker = mailbox.clone();
452 let _handle = common_runtime::spawn_global(async move {
453 timeout_checker.check_timeout_bg(10).await;
454 });
455
456 mailbox
457 }
458
459 fn new(pushers: Pushers, sequence: Sequence) -> Self {
460 Self {
461 pushers,
462 sequence,
463 senders: DashMap::default(),
464 timeouts: DashMap::default(),
465 timeout_notify: Notify::new(),
466 }
467 }
468
469 async fn check_timeout_bg(&self, interval_millis: u64) {
470 let mut interval = tokio::time::interval(Duration::from_millis(interval_millis));
471
472 loop {
473 let _ = interval.tick().await;
474
475 if self.timeouts.is_empty() {
476 self.timeout_notify.notified().await;
477 }
478
479 let now = Instant::now();
480 let timeout_ids = self
481 .timeouts
482 .iter()
483 .filter_map(|entry| {
484 let (id, deadline) = entry.pair();
485 if deadline < &now { Some(*id) } else { None }
486 })
487 .collect::<Vec<_>>();
488
489 for id in timeout_ids {
490 let _ = self
491 .on_recv(id, Err(error::MailboxTimeoutSnafu { id }.build()))
492 .await;
493 }
494 }
495 }
496
497 #[inline]
498 async fn next_message_id(&self) -> Result<u64> {
499 loop {
502 let next = self
503 .sequence
504 .next()
505 .await
506 .context(error::NextSequenceSnafu)?;
507 if next > 0 {
508 return Ok(next);
509 }
510 }
511 }
512}
513
514#[async_trait::async_trait]
515impl Mailbox for HeartbeatMailbox {
516 async fn send(
517 &self,
518 ch: &Channel,
519 mut msg: MailboxMessage,
520 timeout: Duration,
521 ) -> Result<MailboxReceiver> {
522 let message_id = self.next_message_id().await?;
523 msg.id = message_id;
524
525 let pusher_id = ch.pusher_id();
526 debug!("Sending mailbox message {msg:?} to {pusher_id}");
527
528 let (tx, rx) = oneshot::channel();
529 let _ = self.senders.insert(message_id, tx);
530 let deadline = Instant::now() + timeout;
531 self.timeouts.insert(message_id, deadline);
532 self.timeout_notify.notify_one();
533 let deregister_signal_receiver = self.pushers.push(pusher_id, msg).await?;
534
535 Ok(MailboxReceiver::new(
536 message_id,
537 rx,
538 deregister_signal_receiver,
539 *ch,
540 ))
541 }
542
543 async fn send_oneway(&self, ch: &Channel, mut msg: MailboxMessage) -> Result<()> {
544 let message_id = 0; msg.id = message_id;
546
547 let pusher_id = ch.pusher_id();
548 debug!("Sending mailbox message {msg:?} to {pusher_id}");
549
550 self.pushers.push(pusher_id, msg).await?;
551
552 Ok(())
553 }
554
555 async fn broadcast(&self, ch: &BroadcastChannel, msg: &MailboxMessage) -> Result<()> {
556 self.pushers.broadcast(ch.role(), msg).await
557 }
558
559 async fn on_recv(&self, id: MessageId, maybe_msg: Result<MailboxMessage>) -> Result<()> {
560 debug!("Received mailbox message {maybe_msg:?}");
561
562 let _ = self.timeouts.remove(&id);
563
564 if let Some((_, tx)) = self.senders.remove(&id) {
565 tx.send(maybe_msg)
566 .map_err(|_| error::MailboxClosedSnafu { id }.build())?;
567 } else if let Ok(finally_msg) = maybe_msg {
568 warn!("The response arrived too late: {finally_msg:?}");
569 }
570
571 Ok(())
572 }
573}
574
575pub struct HeartbeatHandlerGroupBuilder {
577 region_failure_handler: Option<RegionFailureHandler>,
579
580 region_lease_handler: Option<RegionLeaseHandler>,
582
583 flush_stats_factor: Option<usize>,
587 flow_state_handler: Option<FlowStateHandler>,
589
590 persist_stats_handler: Option<PersistStatsHandler>,
592
593 plugins: Option<Plugins>,
595
596 pushers: Pushers,
598
599 handlers: Vec<NameCachedHandler>,
601}
602
603impl HeartbeatHandlerGroupBuilder {
604 pub fn new(pushers: Pushers) -> Self {
605 Self {
606 region_failure_handler: None,
607 region_lease_handler: None,
608 flush_stats_factor: None,
609 flow_state_handler: None,
610 persist_stats_handler: None,
611 plugins: None,
612 pushers,
613 handlers: vec![],
614 }
615 }
616
617 pub fn with_flow_state_handler(mut self, handler: Option<FlowStateHandler>) -> Self {
618 self.flow_state_handler = handler;
619 self
620 }
621
622 pub fn with_region_lease_handler(mut self, handler: Option<RegionLeaseHandler>) -> Self {
623 self.region_lease_handler = handler;
624 self
625 }
626
627 pub fn with_region_failure_handler(mut self, handler: Option<RegionFailureHandler>) -> Self {
629 self.region_failure_handler = handler;
630 self
631 }
632
633 pub fn with_flush_stats_factor(mut self, flush_stats_factor: Option<usize>) -> Self {
635 self.flush_stats_factor = flush_stats_factor;
636 self
637 }
638
639 pub fn with_persist_stats_handler(mut self, handler: Option<PersistStatsHandler>) -> Self {
640 self.persist_stats_handler = handler;
641 self
642 }
643
644 pub fn with_plugins(mut self, plugins: Option<Plugins>) -> Self {
646 self.plugins = plugins;
647 self
648 }
649
650 pub fn add_default_handlers(mut self) -> Self {
652 let publish_heartbeat_handler = if let Some(plugins) = self.plugins.as_ref() {
654 plugins
655 .get::<PublisherRef>()
656 .map(|publish| PublishHeartbeatHandler::new(publish.clone()))
657 } else {
658 None
659 };
660
661 self.add_handler_last(ResponseHeaderHandler);
662 self.add_handler_last(DatanodeKeepLeaseHandler);
666 self.add_handler_last(FlownodeKeepLeaseHandler);
667 self.add_handler_last(CheckLeaderHandler);
668 self.add_handler_last(OnLeaderStartHandler);
669 self.add_handler_last(ExtractStatHandler);
670 self.add_handler_last(CollectDatanodeClusterInfoHandler);
671 self.add_handler_last(CollectFrontendClusterInfoHandler);
672 self.add_handler_last(CollectFlownodeClusterInfoHandler);
673 self.add_handler_last(MailboxHandler);
674 if let Some(region_lease_handler) = self.region_lease_handler.take() {
675 self.add_handler_last(region_lease_handler);
676 }
677 self.add_handler_last(FilterInactiveRegionStatsHandler);
678 if let Some(region_failure_handler) = self.region_failure_handler.take() {
679 self.add_handler_last(region_failure_handler);
680 }
681 if let Some(publish_heartbeat_handler) = publish_heartbeat_handler {
682 self.add_handler_last(publish_heartbeat_handler);
683 }
684 self.add_handler_last(CollectLeaderRegionHandler);
685 self.add_handler_last(CollectTopicStatsHandler);
686 if let Some(persist_stats_handler) = self.persist_stats_handler.take() {
689 self.add_handler_last(persist_stats_handler);
690 }
691 self.add_handler_last(CollectStatsHandler::new(self.flush_stats_factor));
692 self.add_handler_last(RemapFlowPeerHandler::default());
693
694 if let Some(flow_state_handler) = self.flow_state_handler.take() {
695 self.add_handler_last(flow_state_handler);
696 }
697
698 self
699 }
700
701 pub fn build(mut self) -> Result<HeartbeatHandlerGroup> {
705 if let Some(customizer) = self
706 .plugins
707 .as_ref()
708 .and_then(|plugins| plugins.get::<HeartbeatHandlerGroupBuilderCustomizerRef>())
709 {
710 debug!("Customizing the heartbeat handler group builder");
711 customizer.customize(&mut self)?;
712 }
713
714 Ok(HeartbeatHandlerGroup {
715 handlers: self.handlers,
716 pushers: self.pushers,
717 })
718 }
719
720 fn add_handler_after_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
721 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
722 self.handlers.insert(pos + 1, handler);
723 return Ok(());
724 }
725
726 error::HandlerNotFoundSnafu { name: target }.fail()
727 }
728
729 pub fn add_handler_after(
731 &mut self,
732 target: &'static str,
733 handler: impl HeartbeatHandler + 'static,
734 ) -> Result<()> {
735 self.add_handler_after_inner(target, NameCachedHandler::new(handler))
736 }
737
738 fn add_handler_before_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
739 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
740 self.handlers.insert(pos, handler);
741 return Ok(());
742 }
743
744 error::HandlerNotFoundSnafu { name: target }.fail()
745 }
746
747 pub fn add_handler_before(
749 &mut self,
750 target: &'static str,
751 handler: impl HeartbeatHandler + 'static,
752 ) -> Result<()> {
753 self.add_handler_before_inner(target, NameCachedHandler::new(handler))
754 }
755
756 fn replace_handler_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
757 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
758 self.handlers[pos] = handler;
759 return Ok(());
760 }
761
762 error::HandlerNotFoundSnafu { name: target }.fail()
763 }
764
765 pub fn replace_handler(
767 &mut self,
768 target: &'static str,
769 handler: impl HeartbeatHandler + 'static,
770 ) -> Result<()> {
771 self.replace_handler_inner(target, NameCachedHandler::new(handler))
772 }
773
774 fn add_handler_last_inner(&mut self, handler: NameCachedHandler) {
775 self.handlers.push(handler);
776 }
777
778 fn add_handler_last(&mut self, handler: impl HeartbeatHandler + 'static) {
779 self.add_handler_last_inner(NameCachedHandler::new(handler));
780 }
781}
782
783pub type HeartbeatHandlerGroupBuilderCustomizerRef =
784 Arc<dyn HeartbeatHandlerGroupBuilderCustomizer>;
785
786pub enum CustomizeHeartbeatGroupAction {
787 AddHandlerAfter {
788 target: String,
789 handler: NameCachedHandler,
790 },
791 AddHandlerBefore {
792 target: String,
793 handler: NameCachedHandler,
794 },
795 ReplaceHandler {
796 target: String,
797 handler: NameCachedHandler,
798 },
799 AddHandlerLast {
800 handler: NameCachedHandler,
801 },
802}
803
804impl CustomizeHeartbeatGroupAction {
805 pub fn new_add_handler_after(
806 target: &'static str,
807 handler: impl HeartbeatHandler + 'static,
808 ) -> Self {
809 Self::AddHandlerAfter {
810 target: target.to_string(),
811 handler: NameCachedHandler::new(handler),
812 }
813 }
814
815 pub fn new_add_handler_before(
816 target: &'static str,
817 handler: impl HeartbeatHandler + 'static,
818 ) -> Self {
819 Self::AddHandlerBefore {
820 target: target.to_string(),
821 handler: NameCachedHandler::new(handler),
822 }
823 }
824
825 pub fn new_replace_handler(
826 target: &'static str,
827 handler: impl HeartbeatHandler + 'static,
828 ) -> Self {
829 Self::ReplaceHandler {
830 target: target.to_string(),
831 handler: NameCachedHandler::new(handler),
832 }
833 }
834
835 pub fn new_add_handler_last(handler: impl HeartbeatHandler + 'static) -> Self {
836 Self::AddHandlerLast {
837 handler: NameCachedHandler::new(handler),
838 }
839 }
840}
841
842pub trait HeartbeatHandlerGroupBuilderCustomizer: Send + Sync {
844 fn customize(&self, builder: &mut HeartbeatHandlerGroupBuilder) -> Result<()>;
845
846 fn add_action(&self, action: CustomizeHeartbeatGroupAction);
847}
848
849#[derive(Default)]
850pub struct DefaultHeartbeatHandlerGroupBuilderCustomizer {
851 actions: Mutex<Vec<CustomizeHeartbeatGroupAction>>,
852}
853
854impl HeartbeatHandlerGroupBuilderCustomizer for DefaultHeartbeatHandlerGroupBuilderCustomizer {
855 fn customize(&self, builder: &mut HeartbeatHandlerGroupBuilder) -> Result<()> {
856 info!("Customizing the heartbeat handler group builder");
857 let mut actions = self.actions.lock().unwrap();
858 for action in actions.drain(..) {
859 match action {
860 CustomizeHeartbeatGroupAction::AddHandlerAfter { target, handler } => {
861 builder.add_handler_after_inner(&target, handler)?;
862 }
863 CustomizeHeartbeatGroupAction::AddHandlerBefore { target, handler } => {
864 builder.add_handler_before_inner(&target, handler)?;
865 }
866 CustomizeHeartbeatGroupAction::ReplaceHandler { target, handler } => {
867 builder.replace_handler_inner(&target, handler)?;
868 }
869 CustomizeHeartbeatGroupAction::AddHandlerLast { handler } => {
870 builder.add_handler_last_inner(handler);
871 }
872 }
873 }
874 Ok(())
875 }
876
877 fn add_action(&self, action: CustomizeHeartbeatGroupAction) {
878 self.actions.lock().unwrap().push(action);
879 }
880}
881
882#[cfg(test)]
883mod tests {
884
885 use std::assert_matches;
886 use std::collections::BTreeMap;
887 use std::sync::Arc;
888 use std::time::Duration;
889
890 use api::v1::meta::{MailboxMessage, Role};
891 use common_meta::kv_backend::memory::MemoryKvBackend;
892 use common_meta::sequence::SequenceBuilder;
893 use tokio::sync::mpsc;
894
895 use super::{HeartbeatHandlerGroupBuilder, PusherId, Pushers};
896 use crate::error;
897 use crate::handler::collect_stats_handler::CollectStatsHandler;
898 use crate::handler::response_header_handler::ResponseHeaderHandler;
899 use crate::handler::{HeartbeatHandlerGroup, HeartbeatMailbox, Pusher};
900 use crate::service::mailbox::{Channel, MailboxReceiver, MailboxRef};
901
902 #[tokio::test]
903 async fn test_mailbox() {
904 let (mailbox, receiver) = push_msg_via_mailbox().await;
905 let id = receiver.message_id();
906
907 let resp_msg = MailboxMessage {
908 id,
909 subject: "resp-test".to_string(),
910 timestamp_millis: 456,
911 ..Default::default()
912 };
913
914 mailbox.on_recv(id, Ok(resp_msg)).await.unwrap();
915
916 let recv_msg = receiver.await.unwrap();
917 assert_eq!(recv_msg.id, id);
918 assert_eq!(recv_msg.timestamp_millis, 456);
919 assert_eq!(recv_msg.subject, "resp-test".to_string());
920 }
921
922 #[tokio::test]
923 async fn test_mailbox_timeout() {
924 let (_, receiver) = push_msg_via_mailbox().await;
925 let res = receiver.await;
926 assert!(res.is_err());
927 }
928
929 async fn push_msg_via_mailbox() -> (MailboxRef, MailboxReceiver) {
930 let datanode_id = 12;
931 let (pusher_tx, mut pusher_rx) = mpsc::channel(16);
932 let pusher_id = PusherId::new(Role::Datanode, datanode_id);
933 let pusher: Pusher = Pusher::new(pusher_tx);
934 let handler_group = HeartbeatHandlerGroup::default();
935 handler_group.register_pusher(pusher_id, pusher).await;
936
937 let kv_backend = Arc::new(MemoryKvBackend::new());
938 let seq = SequenceBuilder::new("test_seq", kv_backend).build();
939 let mailbox = HeartbeatMailbox::create(handler_group.pushers(), seq);
940
941 let msg = MailboxMessage {
942 id: 0,
943 subject: "req-test".to_string(),
944 timestamp_millis: 123,
945 ..Default::default()
946 };
947 let ch = Channel::Datanode(datanode_id);
948
949 let receiver = mailbox
950 .send(&ch, msg, Duration::from_secs(1))
951 .await
952 .unwrap();
953
954 let recv_obj = pusher_rx.recv().await.unwrap().unwrap();
955 let message = recv_obj.mailbox_message.unwrap();
956 assert_eq!(message.timestamp_millis, 123);
957 assert_eq!(message.subject, "req-test".to_string());
958
959 (mailbox, receiver)
960 }
961
962 #[test]
963 fn test_pusher_id_role_range() {
964 let mut pushers = BTreeMap::new();
965 pushers.insert(PusherId::new(Role::Datanode, u64::MAX), "datanode");
966 pushers.insert(PusherId::new(Role::Frontend, u64::MIN), "frontend-min");
967 pushers.insert(PusherId::new(Role::Frontend, u64::MAX), "frontend-max");
968 pushers.insert(PusherId::new(Role::Flownode, u64::MIN), "flownode");
969
970 let frontend_pushers = pushers
971 .range(PusherId::role_range(Role::Frontend))
972 .map(|(_, value)| *value)
973 .collect::<Vec<_>>();
974
975 assert_eq!(frontend_pushers, vec!["frontend-min", "frontend-max"]);
976 }
977
978 #[tokio::test]
979 async fn test_pushers_broadcast_by_role() {
980 let pushers = Pushers::default();
981 let (datanode_tx, mut datanode_rx) = mpsc::channel(1);
982 let (frontend_tx, mut frontend_rx) = mpsc::channel(1);
983 let (flownode_tx, mut flownode_rx) = mpsc::channel(1);
984
985 pushers
986 .insert(
987 PusherId::new(Role::Datanode, u64::MAX),
988 Pusher::new(datanode_tx),
989 )
990 .await;
991 pushers
992 .insert(PusherId::new(Role::Frontend, 1), Pusher::new(frontend_tx))
993 .await;
994 pushers
995 .insert(
996 PusherId::new(Role::Flownode, u64::MIN),
997 Pusher::new(flownode_tx),
998 )
999 .await;
1000
1001 let msg = MailboxMessage {
1002 id: 42,
1003 subject: "broadcast-test".to_string(),
1004 timestamp_millis: 123,
1005 ..Default::default()
1006 };
1007
1008 pushers.broadcast(Role::Frontend, &msg).await.unwrap();
1009
1010 let received = frontend_rx.recv().await.unwrap().unwrap();
1011 let mailbox_message = received.mailbox_message.unwrap();
1012 assert_eq!(mailbox_message.id, 0);
1013 assert_eq!(mailbox_message.subject, "broadcast-test");
1014 assert!(datanode_rx.try_recv().is_err());
1015 assert!(flownode_rx.try_recv().is_err());
1016 }
1017
1018 #[test]
1019 fn test_handler_group_builder() {
1020 let group = HeartbeatHandlerGroupBuilder::new(Pushers::default())
1021 .add_default_handlers()
1022 .build()
1023 .unwrap();
1024
1025 let handlers = group.handlers;
1026 let names = [
1027 "ResponseHeaderHandler",
1028 "DatanodeKeepLeaseHandler",
1029 "FlownodeKeepLeaseHandler",
1030 "CheckLeaderHandler",
1031 "OnLeaderStartHandler",
1032 "ExtractStatHandler",
1033 "CollectDatanodeClusterInfoHandler",
1034 "CollectFrontendClusterInfoHandler",
1035 "CollectFlownodeClusterInfoHandler",
1036 "MailboxHandler",
1037 "FilterInactiveRegionStatsHandler",
1038 "CollectLeaderRegionHandler",
1039 "CollectTopicStatsHandler",
1040 "CollectStatsHandler",
1041 "RemapFlowPeerHandler",
1042 ];
1043 assert_eq!(names.len(), handlers.len());
1044 for (handler, name) in handlers.iter().zip(names) {
1045 assert_eq!(handler.name, name);
1046 }
1047 }
1048
1049 #[test]
1050 fn test_handler_group_builder_add_before() {
1051 let mut builder =
1052 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1053 builder
1054 .add_handler_before(
1055 "FilterInactiveRegionStatsHandler",
1056 CollectStatsHandler::default(),
1057 )
1058 .unwrap();
1059
1060 let group = builder.build().unwrap();
1061 let handlers = group.handlers;
1062 let names = [
1063 "ResponseHeaderHandler",
1064 "DatanodeKeepLeaseHandler",
1065 "FlownodeKeepLeaseHandler",
1066 "CheckLeaderHandler",
1067 "OnLeaderStartHandler",
1068 "ExtractStatHandler",
1069 "CollectDatanodeClusterInfoHandler",
1070 "CollectFrontendClusterInfoHandler",
1071 "CollectFlownodeClusterInfoHandler",
1072 "MailboxHandler",
1073 "CollectStatsHandler",
1074 "FilterInactiveRegionStatsHandler",
1075 "CollectLeaderRegionHandler",
1076 "CollectTopicStatsHandler",
1077 "CollectStatsHandler",
1078 "RemapFlowPeerHandler",
1079 ];
1080 assert_eq!(names.len(), handlers.len());
1081 for (handler, name) in handlers.iter().zip(names) {
1082 assert_eq!(handler.name, name);
1083 }
1084 }
1085
1086 #[test]
1087 fn test_handler_group_builder_add_before_first() {
1088 let mut builder =
1089 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1090 builder
1091 .add_handler_before("ResponseHeaderHandler", CollectStatsHandler::default())
1092 .unwrap();
1093
1094 let group = builder.build().unwrap();
1095 let handlers = group.handlers;
1096 let names = [
1097 "CollectStatsHandler",
1098 "ResponseHeaderHandler",
1099 "DatanodeKeepLeaseHandler",
1100 "FlownodeKeepLeaseHandler",
1101 "CheckLeaderHandler",
1102 "OnLeaderStartHandler",
1103 "ExtractStatHandler",
1104 "CollectDatanodeClusterInfoHandler",
1105 "CollectFrontendClusterInfoHandler",
1106 "CollectFlownodeClusterInfoHandler",
1107 "MailboxHandler",
1108 "FilterInactiveRegionStatsHandler",
1109 "CollectLeaderRegionHandler",
1110 "CollectTopicStatsHandler",
1111 "CollectStatsHandler",
1112 "RemapFlowPeerHandler",
1113 ];
1114 assert_eq!(names.len(), handlers.len());
1115 for (handler, name) in handlers.iter().zip(names) {
1116 assert_eq!(handler.name, name);
1117 }
1118 }
1119
1120 #[test]
1121 fn test_handler_group_builder_add_after() {
1122 let mut builder =
1123 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1124 builder
1125 .add_handler_after("MailboxHandler", CollectStatsHandler::default())
1126 .unwrap();
1127
1128 let group = builder.build().unwrap();
1129 let handlers = group.handlers;
1130 let names = [
1131 "ResponseHeaderHandler",
1132 "DatanodeKeepLeaseHandler",
1133 "FlownodeKeepLeaseHandler",
1134 "CheckLeaderHandler",
1135 "OnLeaderStartHandler",
1136 "ExtractStatHandler",
1137 "CollectDatanodeClusterInfoHandler",
1138 "CollectFrontendClusterInfoHandler",
1139 "CollectFlownodeClusterInfoHandler",
1140 "MailboxHandler",
1141 "CollectStatsHandler",
1142 "FilterInactiveRegionStatsHandler",
1143 "CollectLeaderRegionHandler",
1144 "CollectTopicStatsHandler",
1145 "CollectStatsHandler",
1146 "RemapFlowPeerHandler",
1147 ];
1148 assert_eq!(names.len(), handlers.len());
1149 for (handler, name) in handlers.iter().zip(names) {
1150 assert_eq!(handler.name, name);
1151 }
1152 }
1153
1154 #[test]
1155 fn test_handler_group_builder_add_after_last() {
1156 let mut builder =
1157 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1158 builder
1159 .add_handler_after("CollectStatsHandler", ResponseHeaderHandler)
1160 .unwrap();
1161
1162 let group = builder.build().unwrap();
1163 let handlers = group.handlers;
1164 let names = [
1165 "ResponseHeaderHandler",
1166 "DatanodeKeepLeaseHandler",
1167 "FlownodeKeepLeaseHandler",
1168 "CheckLeaderHandler",
1169 "OnLeaderStartHandler",
1170 "ExtractStatHandler",
1171 "CollectDatanodeClusterInfoHandler",
1172 "CollectFrontendClusterInfoHandler",
1173 "CollectFlownodeClusterInfoHandler",
1174 "MailboxHandler",
1175 "FilterInactiveRegionStatsHandler",
1176 "CollectLeaderRegionHandler",
1177 "CollectTopicStatsHandler",
1178 "CollectStatsHandler",
1179 "ResponseHeaderHandler",
1180 "RemapFlowPeerHandler",
1181 ];
1182 assert_eq!(names.len(), handlers.len());
1183 for (handler, name) in handlers.iter().zip(names) {
1184 assert_eq!(handler.name, name);
1185 }
1186 }
1187
1188 #[test]
1189 fn test_handler_group_builder_replace() {
1190 let mut builder =
1191 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1192 builder
1193 .replace_handler("MailboxHandler", CollectStatsHandler::default())
1194 .unwrap();
1195
1196 let group = builder.build().unwrap();
1197 let handlers = group.handlers;
1198 let names = [
1199 "ResponseHeaderHandler",
1200 "DatanodeKeepLeaseHandler",
1201 "FlownodeKeepLeaseHandler",
1202 "CheckLeaderHandler",
1203 "OnLeaderStartHandler",
1204 "ExtractStatHandler",
1205 "CollectDatanodeClusterInfoHandler",
1206 "CollectFrontendClusterInfoHandler",
1207 "CollectFlownodeClusterInfoHandler",
1208 "CollectStatsHandler",
1209 "FilterInactiveRegionStatsHandler",
1210 "CollectLeaderRegionHandler",
1211 "CollectTopicStatsHandler",
1212 "CollectStatsHandler",
1213 "RemapFlowPeerHandler",
1214 ];
1215
1216 assert_eq!(names.len(), handlers.len());
1217 for (handler, name) in handlers.iter().zip(names) {
1218 assert_eq!(handler.name, name);
1219 }
1220 }
1221
1222 #[test]
1223 fn test_handler_group_builder_replace_last() {
1224 let mut builder =
1225 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1226 builder
1227 .replace_handler("CollectStatsHandler", ResponseHeaderHandler)
1228 .unwrap();
1229
1230 let group = builder.build().unwrap();
1231 let handlers = group.handlers;
1232 let names = [
1233 "ResponseHeaderHandler",
1234 "DatanodeKeepLeaseHandler",
1235 "FlownodeKeepLeaseHandler",
1236 "CheckLeaderHandler",
1237 "OnLeaderStartHandler",
1238 "ExtractStatHandler",
1239 "CollectDatanodeClusterInfoHandler",
1240 "CollectFrontendClusterInfoHandler",
1241 "CollectFlownodeClusterInfoHandler",
1242 "MailboxHandler",
1243 "FilterInactiveRegionStatsHandler",
1244 "CollectLeaderRegionHandler",
1245 "CollectTopicStatsHandler",
1246 "ResponseHeaderHandler",
1247 "RemapFlowPeerHandler",
1248 ];
1249
1250 assert_eq!(names.len(), handlers.len());
1251 for (handler, name) in handlers.iter().zip(names) {
1252 assert_eq!(handler.name, name);
1253 }
1254 }
1255
1256 #[test]
1257 fn test_handler_group_builder_replace_first() {
1258 let mut builder =
1259 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1260 builder
1261 .replace_handler("ResponseHeaderHandler", CollectStatsHandler::default())
1262 .unwrap();
1263
1264 let group = builder.build().unwrap();
1265 let handlers = group.handlers;
1266 let names = [
1267 "CollectStatsHandler",
1268 "DatanodeKeepLeaseHandler",
1269 "FlownodeKeepLeaseHandler",
1270 "CheckLeaderHandler",
1271 "OnLeaderStartHandler",
1272 "ExtractStatHandler",
1273 "CollectDatanodeClusterInfoHandler",
1274 "CollectFrontendClusterInfoHandler",
1275 "CollectFlownodeClusterInfoHandler",
1276 "MailboxHandler",
1277 "FilterInactiveRegionStatsHandler",
1278 "CollectLeaderRegionHandler",
1279 "CollectTopicStatsHandler",
1280 "CollectStatsHandler",
1281 "RemapFlowPeerHandler",
1282 ];
1283 assert_eq!(names.len(), handlers.len());
1284 for (handler, name) in handlers.iter().zip(names) {
1285 assert_eq!(handler.name, name);
1286 }
1287 }
1288
1289 #[test]
1290 fn test_handler_group_builder_handler_not_found() {
1291 let mut builder =
1292 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1293 let err = builder
1294 .add_handler_before("NotExists", CollectStatsHandler::default())
1295 .unwrap_err();
1296 assert_matches!(err, error::Error::HandlerNotFound { .. });
1297
1298 let err = builder
1299 .add_handler_after("NotExists", CollectStatsHandler::default())
1300 .unwrap_err();
1301 assert_matches!(err, error::Error::HandlerNotFound { .. });
1302
1303 let err = builder
1304 .replace_handler("NotExists", CollectStatsHandler::default())
1305 .unwrap_err();
1306 assert_matches!(err, error::Error::HandlerNotFound { .. });
1307 }
1308
1309 #[tokio::test]
1310 async fn test_pusher_drop() {
1311 let (tx, _rx) = mpsc::channel(1);
1312 let pusher = Pusher::new(tx);
1313 let mut deregister_signal_tx = pusher.deregister_signal_receiver.clone();
1314
1315 drop(pusher);
1316 deregister_signal_tx.changed().await.unwrap();
1317 }
1318}