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