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, OwnedMutexGuard, 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;
84mod utils;
85
86#[cfg(test)]
87pub mod test_utils;
88
89#[async_trait::async_trait]
90pub trait HeartbeatHandler: Send + Sync {
91 fn is_acceptable(&self, role: Role) -> bool;
92
93 fn name(&self) -> &'static str {
94 let type_name = std::any::type_name::<Self>();
95 type_name.split("::").last().unwrap_or(type_name)
97 }
98
99 async fn handle(
100 &self,
101 req: &HeartbeatRequest,
102 ctx: &mut Context,
103 acc: &mut HeartbeatAccumulator,
104 ) -> Result<HandleControl>;
105}
106
107#[derive(PartialEq, Debug)]
111pub enum HandleControl {
112 Continue,
113 Done,
114}
115
116#[derive(Debug, Default)]
117pub struct HeartbeatAccumulator {
118 pub header: Option<ResponseHeader>,
119 mailbox_message: Option<MailboxMessage>,
120 pub stat: Option<Stat>,
121 pub inactive_region_ids: HashSet<RegionId>,
122 pub region_lease: Option<RegionLease>,
123 pub extensions: HashMap<String, Vec<u8>>,
125}
126
127impl HeartbeatAccumulator {
128 pub(crate) fn take_mailbox_message(&mut self) -> Option<MailboxMessage> {
129 self.mailbox_message.take()
130 }
131
132 pub fn set_mailbox_message(&mut self, message: MailboxMessage) {
133 let _ = self.mailbox_message.insert(message);
134 }
135}
136
137#[derive(Copy, Clone)]
138pub struct PusherId {
139 pub role: Role,
140 pub id: u64,
141}
142
143impl PartialEq for PusherId {
144 fn eq(&self, other: &Self) -> bool {
145 self.role as i32 == other.role as i32 && self.id == other.id
146 }
147}
148
149impl Eq for PusherId {}
150
151impl PartialOrd for PusherId {
152 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
153 Some(self.cmp(other))
154 }
155}
156
157impl Ord for PusherId {
158 fn cmp(&self, other: &Self) -> Ordering {
159 (self.role as i32, self.id).cmp(&(other.role as i32, other.id))
160 }
161}
162
163impl Debug for PusherId {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 write!(f, "{:?}-{}", self.role, self.id)
166 }
167}
168
169impl Display for PusherId {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 write!(f, "{:?}-{}", self.role, self.id)
172 }
173}
174
175impl PusherId {
176 pub fn new(role: Role, id: u64) -> Self {
177 Self { role, id }
178 }
179
180 fn role_range(role: Role) -> (Bound<Self>, Bound<Self>) {
181 (
182 Bound::Included(Self::new(role, u64::MIN)),
183 Bound::Included(Self::new(role, u64::MAX)),
184 )
185 }
186}
187
188pub type DeregisterSignalReceiver = watch::Receiver<bool>;
190
191pub struct Pusher {
193 sender: Sender<std::result::Result<HeartbeatResponse, tonic::Status>>,
194 deregister_signal_sender: watch::Sender<bool>,
198 deregister_signal_receiver: DeregisterSignalReceiver,
199
200 res_header: ResponseHeader,
201 node_epoch: u64,
203}
204
205impl Drop for Pusher {
206 fn drop(&mut self) {
207 let _ = self.deregister_signal_sender.send(true);
210 }
211}
212
213impl Pusher {
214 pub fn new(sender: Sender<std::result::Result<HeartbeatResponse, tonic::Status>>) -> Self {
215 let res_header = ResponseHeader {
216 protocol_version: PROTOCOL_VERSION,
217 ..Default::default()
218 };
219 let (deregister_signal_sender, deregister_signal_receiver) = watch::channel(false);
220 Self {
221 sender,
222 deregister_signal_sender,
223 deregister_signal_receiver,
224 res_header,
225 node_epoch: 0,
226 }
227 }
228
229 pub(crate) fn with_node_epoch(mut self, node_epoch: u64) -> Self {
230 self.node_epoch = node_epoch;
231 self
232 }
233
234 #[inline]
235 pub fn header(&self) -> ResponseHeader {
236 self.res_header.clone()
237 }
238}
239
240struct PusherHandle {
244 sender: Sender<std::result::Result<HeartbeatResponse, tonic::Status>>,
245 res_header: ResponseHeader,
246 deregister_signal_receiver: DeregisterSignalReceiver,
247}
248
249impl PusherHandle {
250 fn from_pusher(pusher: &Pusher) -> Self {
252 Self {
253 sender: pusher.sender.clone(),
254 res_header: pusher.header(),
255 deregister_signal_receiver: pusher.deregister_signal_receiver.clone(),
256 }
257 }
258
259 async fn push(self, mailbox_message: MailboxMessage) -> Result<()> {
261 self.sender
262 .send(Ok(HeartbeatResponse {
263 header: Some(self.res_header),
264 mailbox_message: Some(mailbox_message),
265 ..Default::default()
266 }))
267 .await
268 .map_err(|e| {
269 error::PushMessageSnafu {
270 err_msg: e.to_string(),
271 }
272 .build()
273 })
274 }
275
276 #[inline]
277 fn deregister_signal_receiver(&self) -> DeregisterSignalReceiver {
278 self.deregister_signal_receiver.clone()
279 }
280}
281
282#[derive(Clone, Default)]
284pub struct Pushers(Arc<RwLock<BTreeMap<PusherId, Pusher>>>);
285
286impl Pushers {
287 async fn push(
288 &self,
289 pusher_id: PusherId,
290 mailbox_message: MailboxMessage,
291 ) -> Result<DeregisterSignalReceiver> {
292 let handle = {
295 let pushers = self.0.read().await;
296 let pusher = pushers
297 .get(&pusher_id)
298 .with_context(|| error::PusherNotFoundSnafu {
299 pusher_id: pusher_id.to_string(),
300 })?;
301 PusherHandle::from_pusher(pusher)
302 };
303
304 let deregister_signal_receiver = handle.deregister_signal_receiver();
305 handle.push(mailbox_message).await?;
306
307 Ok(deregister_signal_receiver)
308 }
309
310 async fn broadcast(&self, role: Role, mailbox_message: &MailboxMessage) -> Result<()> {
311 let targets = {
314 let pushers = self.0.read().await;
315 pushers
316 .range(PusherId::role_range(role))
317 .map(|(_, pusher)| PusherHandle::from_pusher(pusher))
318 .collect::<Vec<_>>()
319 };
320
321 let mut results = Vec::with_capacity(targets.len());
322 for handle in targets {
323 let mut mailbox_message = mailbox_message.clone();
324 mailbox_message.id = 0; results.push(handle.push(mailbox_message));
327 }
328
329 let _ = join_all(results)
331 .await
332 .into_iter()
333 .collect::<Result<Vec<_>>>()?;
334
335 Ok(())
336 }
337
338 pub(crate) async fn insert(&self, pusher_id: PusherId, pusher: Pusher) -> Option<bool> {
343 let mut pushers = self.0.write().await;
344 match pushers.get_mut(&pusher_id) {
345 None => {
346 pushers.insert(pusher_id, pusher);
347 return Some(true);
348 }
349 Some(current) if current.node_epoch > pusher.node_epoch => return None,
350 Some(current) if current.sender.same_channel(&pusher.sender) => {
351 current.node_epoch = pusher.node_epoch;
352 }
353 Some(current) => *current = pusher,
354 }
355 Some(false)
356 }
357
358 async fn remove(
361 &self,
362 pusher_id: PusherId,
363 sender: &Sender<std::result::Result<HeartbeatResponse, tonic::Status>>,
364 ) -> bool {
365 let mut pushers = self.0.write().await;
366 let own = pushers
367 .get(&pusher_id)
368 .is_some_and(|pusher| pusher.sender.same_channel(sender));
369 own && pushers.remove(&pusher_id).is_some()
370 }
371}
372
373#[derive(Clone)]
374pub struct NameCachedHandler {
375 name: &'static str,
376 handler: Arc<dyn HeartbeatHandler>,
377}
378
379impl NameCachedHandler {
380 fn new(handler: impl HeartbeatHandler + 'static) -> Self {
381 let name = handler.name();
382 let handler = Arc::new(handler);
383 Self { name, handler }
384 }
385}
386
387pub type HeartbeatHandlerGroupRef = Arc<HeartbeatHandlerGroup>;
388
389#[derive(Default, Clone)]
391pub struct HeartbeatHandlerGroup {
392 handlers: Vec<NameCachedHandler>,
393 pushers: Pushers,
394 datanode_locks: DashMap<u64, Arc<tokio::sync::Mutex<()>>>,
396}
397
398impl HeartbeatHandlerGroup {
399 pub async fn register_pusher(&self, pusher_id: PusherId, pusher: Pusher) {
402 let Some(vacant) = self.pushers.insert(pusher_id, pusher).await else {
403 return;
404 };
405 info!("Pusher register: {}", pusher_id);
406 if vacant {
407 METRIC_META_HEARTBEAT_CONNECTION_NUM.inc();
408 }
409 }
410
411 pub async fn deregister_push(
414 &self,
415 pusher_id: PusherId,
416 sender: &Sender<std::result::Result<HeartbeatResponse, tonic::Status>>,
417 ) {
418 if self.pushers.remove(pusher_id, sender).await {
419 info!("Pusher unregister: {}", pusher_id);
420 METRIC_META_HEARTBEAT_CONNECTION_NUM.dec();
421 }
422 }
423
424 pub(crate) async fn lock_datanode(&self, node_id: u64) -> OwnedMutexGuard<()> {
427 let lock = self.datanode_locks.entry(node_id).or_default().clone();
428 lock.lock_owned().await
429 }
430
431 #[cfg(test)]
432 pub async fn contains_pusher(&self, pusher_id: &PusherId) -> bool {
434 let pushers = self.pushers.0.read().await;
435 pushers.contains_key(pusher_id)
436 }
437
438 pub fn pushers(&self) -> Pushers {
440 self.pushers.clone()
441 }
442
443 pub async fn handle(
445 &self,
446 req: HeartbeatRequest,
447 mut ctx: Context,
448 ) -> Result<HeartbeatResponse> {
449 let mut acc = HeartbeatAccumulator::default();
450 let role = req
451 .header
452 .as_ref()
453 .and_then(|h| Role::try_from(h.role).ok())
454 .context(error::InvalidArgumentsSnafu {
455 err_msg: format!("invalid role: {:?}", req.header),
456 })?;
457
458 let is_handshake = ctx.is_handshake;
459
460 for NameCachedHandler { name, handler } in self.handlers.iter() {
461 if !handler.is_acceptable(role) {
462 continue;
463 }
464
465 let _timer = METRIC_META_HANDLER_EXECUTE
466 .with_label_values(&[*name])
467 .start_timer();
468
469 if handler.handle(&req, &mut ctx, &mut acc).await? == HandleControl::Done {
470 break;
471 }
472 }
473 let header = std::mem::take(&mut acc.header);
474 let mailbox_message = acc.take_mailbox_message();
475
476 let heartbeat_config = if is_handshake {
478 let mut config: HeartbeatConfig = ctx.heartbeat_options_for(role).into();
479 config.gc_enabled = ctx.gc_enabled;
480
481 info!(
482 "Handshake with {:?} node, sending config: {:?}",
483 role, config
484 );
485
486 Some(config)
487 } else {
488 None
489 };
490
491 let res = HeartbeatResponse {
492 header,
493 region_lease: acc.region_lease,
494 mailbox_message,
495 heartbeat_config,
496 extensions: std::mem::take(&mut acc.extensions),
497 };
498 Ok(res)
499 }
500}
501
502pub struct HeartbeatMailbox {
503 pushers: Pushers,
504 sequence: Sequence,
505 senders: DashMap<MessageId, oneshot::Sender<Result<MailboxMessage>>>,
506 timeouts: DashMap<MessageId, Instant>,
507 timeout_notify: Notify,
508}
509
510impl HeartbeatMailbox {
511 pub fn json_reply(msg: &MailboxMessage) -> Result<InstructionReply> {
512 let Payload::Json(payload) =
513 msg.payload
514 .as_ref()
515 .with_context(|| UnexpectedInstructionReplySnafu {
516 mailbox_message: msg.to_string(),
517 reason: "empty JSON payload".to_string(),
518 })?;
519 serde_json::from_str(payload).context(DeserializeFromJsonSnafu {
520 input_len: payload.len(),
521 })
522 }
523
524 #[cfg(test)]
526 pub(crate) fn json_instruction(
527 msg: &MailboxMessage,
528 ) -> Result<common_meta::instruction::Instruction> {
529 let Payload::Json(payload) =
530 msg.payload
531 .as_ref()
532 .with_context(|| UnexpectedInstructionReplySnafu {
533 mailbox_message: msg.to_string(),
534 reason: "empty JSON payload".to_string(),
535 })?;
536 serde_json::from_str(payload).context(DeserializeFromJsonSnafu {
537 input_len: payload.len(),
538 })
539 }
540
541 pub fn create(pushers: Pushers, sequence: Sequence) -> MailboxRef {
542 let mailbox = Arc::new(Self::new(pushers, sequence));
543
544 let timeout_checker = mailbox.clone();
545 let _handle = common_runtime::spawn_global(async move {
546 timeout_checker.check_timeout_bg(10).await;
547 });
548
549 mailbox
550 }
551
552 fn new(pushers: Pushers, sequence: Sequence) -> Self {
553 Self {
554 pushers,
555 sequence,
556 senders: DashMap::default(),
557 timeouts: DashMap::default(),
558 timeout_notify: Notify::new(),
559 }
560 }
561
562 async fn check_timeout_bg(&self, interval_millis: u64) {
563 let mut interval = tokio::time::interval(Duration::from_millis(interval_millis));
564
565 loop {
566 let _ = interval.tick().await;
567
568 if self.timeouts.is_empty() {
569 self.timeout_notify.notified().await;
570 }
571
572 let now = Instant::now();
573 let timeout_ids = self
574 .timeouts
575 .iter()
576 .filter_map(|entry| {
577 let (id, deadline) = entry.pair();
578 if deadline < &now { Some(*id) } else { None }
579 })
580 .collect::<Vec<_>>();
581
582 for id in timeout_ids {
583 let _ = self
584 .on_recv(id, Err(error::MailboxTimeoutSnafu { id }.build()))
585 .await;
586 }
587 }
588 }
589
590 #[inline]
591 async fn next_message_id(&self) -> Result<u64> {
592 loop {
595 let next = self
596 .sequence
597 .next()
598 .await
599 .context(error::NextSequenceSnafu)?;
600 if next > 0 {
601 return Ok(next);
602 }
603 }
604 }
605}
606
607#[async_trait::async_trait]
608impl Mailbox for HeartbeatMailbox {
609 async fn send(
610 &self,
611 ch: &Channel,
612 mut msg: MailboxMessage,
613 timeout: Duration,
614 ) -> Result<MailboxReceiver> {
615 let message_id = self.next_message_id().await?;
616 msg.id = message_id;
617
618 let pusher_id = ch.pusher_id();
619 let payload_len = msg
620 .payload
621 .as_ref()
622 .map(|Payload::Json(payload)| payload.len())
623 .unwrap_or_default();
624 debug!(message_id, payload_len, %pusher_id, "Sending mailbox message");
625
626 let (tx, rx) = oneshot::channel();
627 let _ = self.senders.insert(message_id, tx);
628 let deadline = Instant::now() + timeout;
629 self.timeouts.insert(message_id, deadline);
630 self.timeout_notify.notify_one();
631 let deregister_signal_receiver = self.pushers.push(pusher_id, msg).await?;
632
633 Ok(MailboxReceiver::new(
634 message_id,
635 rx,
636 deregister_signal_receiver,
637 *ch,
638 ))
639 }
640
641 async fn send_oneway(&self, ch: &Channel, mut msg: MailboxMessage) -> Result<()> {
642 let message_id = 0; msg.id = message_id;
644
645 let pusher_id = ch.pusher_id();
646 let payload_len = msg
647 .payload
648 .as_ref()
649 .map(|Payload::Json(payload)| payload.len())
650 .unwrap_or_default();
651 debug!(message_id, payload_len, %pusher_id, "Sending one-way mailbox message");
652
653 self.pushers.push(pusher_id, msg).await?;
654
655 Ok(())
656 }
657
658 async fn broadcast(&self, ch: &BroadcastChannel, msg: &MailboxMessage) -> Result<()> {
659 self.pushers.broadcast(ch.role(), msg).await
660 }
661
662 async fn on_recv(&self, id: MessageId, maybe_msg: Result<MailboxMessage>) -> Result<()> {
663 let payload_len = maybe_msg
664 .as_ref()
665 .ok()
666 .and_then(|msg| msg.payload.as_ref())
667 .map(|Payload::Json(payload)| payload.len())
668 .unwrap_or_default();
669 debug!(
670 message_id = id,
671 payload_len,
672 success = maybe_msg.is_ok(),
673 "Received mailbox message"
674 );
675
676 let _ = self.timeouts.remove(&id);
677
678 if let Some((_, tx)) = self.senders.remove(&id) {
679 tx.send(maybe_msg)
680 .map_err(|_| error::MailboxClosedSnafu { id }.build())?;
681 } else if let Ok(finally_msg) = maybe_msg {
682 let payload_len = finally_msg
683 .payload
684 .as_ref()
685 .map(|Payload::Json(payload)| payload.len())
686 .unwrap_or_default();
687 warn!(
688 message_id = id,
689 payload_len, "The mailbox response arrived too late"
690 );
691 }
692
693 Ok(())
694 }
695}
696
697pub struct HeartbeatHandlerGroupBuilder {
699 region_failure_handler: Option<RegionFailureHandler>,
701
702 region_lease_handler: Option<RegionLeaseHandler>,
704
705 flush_stats_factor: Option<usize>,
709 flow_state_handler: Option<FlowStateHandler>,
711
712 persist_stats_handler: Option<PersistStatsHandler>,
714
715 plugins: Option<Plugins>,
717
718 pushers: Pushers,
720
721 handlers: Vec<NameCachedHandler>,
723}
724
725impl HeartbeatHandlerGroupBuilder {
726 pub fn new(pushers: Pushers) -> Self {
727 Self {
728 region_failure_handler: None,
729 region_lease_handler: None,
730 flush_stats_factor: None,
731 flow_state_handler: None,
732 persist_stats_handler: None,
733 plugins: None,
734 pushers,
735 handlers: vec![],
736 }
737 }
738
739 pub fn with_flow_state_handler(mut self, handler: Option<FlowStateHandler>) -> Self {
740 self.flow_state_handler = handler;
741 self
742 }
743
744 pub fn with_region_lease_handler(mut self, handler: Option<RegionLeaseHandler>) -> Self {
745 self.region_lease_handler = handler;
746 self
747 }
748
749 pub fn with_region_failure_handler(mut self, handler: Option<RegionFailureHandler>) -> Self {
751 self.region_failure_handler = handler;
752 self
753 }
754
755 pub fn with_flush_stats_factor(mut self, flush_stats_factor: Option<usize>) -> Self {
757 self.flush_stats_factor = flush_stats_factor;
758 self
759 }
760
761 pub fn with_persist_stats_handler(mut self, handler: Option<PersistStatsHandler>) -> Self {
762 self.persist_stats_handler = handler;
763 self
764 }
765
766 pub fn with_plugins(mut self, plugins: Option<Plugins>) -> Self {
768 self.plugins = plugins;
769 self
770 }
771
772 pub fn add_default_handlers(mut self) -> Self {
774 let publish_heartbeat_handler = if let Some(plugins) = self.plugins.as_ref() {
776 plugins
777 .get::<PublisherRef>()
778 .map(|publish| PublishHeartbeatHandler::new(publish.clone()))
779 } else {
780 None
781 };
782
783 self.add_handler_last(ResponseHeaderHandler);
784 self.add_handler_last(DatanodeKeepLeaseHandler);
788 self.add_handler_last(FlownodeKeepLeaseHandler);
789 self.add_handler_last(CheckLeaderHandler);
790 self.add_handler_last(OnLeaderStartHandler);
791 self.add_handler_last(ExtractStatHandler);
792 self.add_handler_last(CollectDatanodeClusterInfoHandler);
793 self.add_handler_last(CollectFrontendClusterInfoHandler);
794 self.add_handler_last(CollectFlownodeClusterInfoHandler);
795 self.add_handler_last(MailboxHandler);
796 if let Some(region_lease_handler) = self.region_lease_handler.take() {
797 self.add_handler_last(region_lease_handler);
798 }
799 self.add_handler_last(FilterInactiveRegionStatsHandler);
800 if let Some(region_failure_handler) = self.region_failure_handler.take() {
801 self.add_handler_last(region_failure_handler);
802 }
803 if let Some(publish_heartbeat_handler) = publish_heartbeat_handler {
804 self.add_handler_last(publish_heartbeat_handler);
805 }
806 self.add_handler_last(CollectLeaderRegionHandler);
807 self.add_handler_last(CollectTopicStatsHandler);
808 if let Some(persist_stats_handler) = self.persist_stats_handler.take() {
811 self.add_handler_last(persist_stats_handler);
812 }
813 self.add_handler_last(CollectStatsHandler::new(self.flush_stats_factor));
814 self.add_handler_last(RemapFlowPeerHandler::default());
815
816 if let Some(flow_state_handler) = self.flow_state_handler.take() {
817 self.add_handler_last(flow_state_handler);
818 }
819
820 self
821 }
822
823 pub fn build(mut self) -> Result<HeartbeatHandlerGroup> {
827 if let Some(customizer) = self
828 .plugins
829 .as_ref()
830 .and_then(|plugins| plugins.get::<HeartbeatHandlerGroupBuilderCustomizerRef>())
831 {
832 debug!("Customizing the heartbeat handler group builder");
833 customizer.customize(&mut self)?;
834 }
835
836 Ok(HeartbeatHandlerGroup {
837 handlers: self.handlers,
838 pushers: self.pushers,
839 datanode_locks: DashMap::new(),
840 })
841 }
842
843 fn add_handler_after_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
844 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
845 self.handlers.insert(pos + 1, handler);
846 return Ok(());
847 }
848
849 error::HandlerNotFoundSnafu { name: target }.fail()
850 }
851
852 pub fn add_handler_after(
854 &mut self,
855 target: &'static str,
856 handler: impl HeartbeatHandler + 'static,
857 ) -> Result<()> {
858 self.add_handler_after_inner(target, NameCachedHandler::new(handler))
859 }
860
861 fn add_handler_before_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
862 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
863 self.handlers.insert(pos, handler);
864 return Ok(());
865 }
866
867 error::HandlerNotFoundSnafu { name: target }.fail()
868 }
869
870 pub fn add_handler_before(
872 &mut self,
873 target: &'static str,
874 handler: impl HeartbeatHandler + 'static,
875 ) -> Result<()> {
876 self.add_handler_before_inner(target, NameCachedHandler::new(handler))
877 }
878
879 fn replace_handler_inner(&mut self, target: &str, handler: NameCachedHandler) -> Result<()> {
880 if let Some(pos) = self.handlers.iter().position(|x| x.name == target) {
881 self.handlers[pos] = handler;
882 return Ok(());
883 }
884
885 error::HandlerNotFoundSnafu { name: target }.fail()
886 }
887
888 pub fn replace_handler(
890 &mut self,
891 target: &'static str,
892 handler: impl HeartbeatHandler + 'static,
893 ) -> Result<()> {
894 self.replace_handler_inner(target, NameCachedHandler::new(handler))
895 }
896
897 fn add_handler_last_inner(&mut self, handler: NameCachedHandler) {
898 self.handlers.push(handler);
899 }
900
901 fn add_handler_last(&mut self, handler: impl HeartbeatHandler + 'static) {
902 self.add_handler_last_inner(NameCachedHandler::new(handler));
903 }
904}
905
906pub type HeartbeatHandlerGroupBuilderCustomizerRef =
907 Arc<dyn HeartbeatHandlerGroupBuilderCustomizer>;
908
909pub enum CustomizeHeartbeatGroupAction {
910 AddHandlerAfter {
911 target: String,
912 handler: NameCachedHandler,
913 },
914 AddHandlerBefore {
915 target: String,
916 handler: NameCachedHandler,
917 },
918 ReplaceHandler {
919 target: String,
920 handler: NameCachedHandler,
921 },
922 AddHandlerLast {
923 handler: NameCachedHandler,
924 },
925}
926
927impl CustomizeHeartbeatGroupAction {
928 pub fn new_add_handler_after(
929 target: &'static str,
930 handler: impl HeartbeatHandler + 'static,
931 ) -> Self {
932 Self::AddHandlerAfter {
933 target: target.to_string(),
934 handler: NameCachedHandler::new(handler),
935 }
936 }
937
938 pub fn new_add_handler_before(
939 target: &'static str,
940 handler: impl HeartbeatHandler + 'static,
941 ) -> Self {
942 Self::AddHandlerBefore {
943 target: target.to_string(),
944 handler: NameCachedHandler::new(handler),
945 }
946 }
947
948 pub fn new_replace_handler(
949 target: &'static str,
950 handler: impl HeartbeatHandler + 'static,
951 ) -> Self {
952 Self::ReplaceHandler {
953 target: target.to_string(),
954 handler: NameCachedHandler::new(handler),
955 }
956 }
957
958 pub fn new_add_handler_last(handler: impl HeartbeatHandler + 'static) -> Self {
959 Self::AddHandlerLast {
960 handler: NameCachedHandler::new(handler),
961 }
962 }
963}
964
965pub trait HeartbeatHandlerGroupBuilderCustomizer: Send + Sync {
967 fn customize(&self, builder: &mut HeartbeatHandlerGroupBuilder) -> Result<()>;
968
969 fn add_action(&self, action: CustomizeHeartbeatGroupAction);
970}
971
972#[derive(Default)]
973pub struct DefaultHeartbeatHandlerGroupBuilderCustomizer {
974 actions: Mutex<Vec<CustomizeHeartbeatGroupAction>>,
975}
976
977impl HeartbeatHandlerGroupBuilderCustomizer for DefaultHeartbeatHandlerGroupBuilderCustomizer {
978 fn customize(&self, builder: &mut HeartbeatHandlerGroupBuilder) -> Result<()> {
979 info!("Customizing the heartbeat handler group builder");
980 let mut actions = self.actions.lock().unwrap();
981 for action in actions.drain(..) {
982 match action {
983 CustomizeHeartbeatGroupAction::AddHandlerAfter { target, handler } => {
984 builder.add_handler_after_inner(&target, handler)?;
985 }
986 CustomizeHeartbeatGroupAction::AddHandlerBefore { target, handler } => {
987 builder.add_handler_before_inner(&target, handler)?;
988 }
989 CustomizeHeartbeatGroupAction::ReplaceHandler { target, handler } => {
990 builder.replace_handler_inner(&target, handler)?;
991 }
992 CustomizeHeartbeatGroupAction::AddHandlerLast { handler } => {
993 builder.add_handler_last_inner(handler);
994 }
995 }
996 }
997 Ok(())
998 }
999
1000 fn add_action(&self, action: CustomizeHeartbeatGroupAction) {
1001 self.actions.lock().unwrap().push(action);
1002 }
1003}
1004
1005#[cfg(test)]
1006mod tests {
1007
1008 use std::assert_matches;
1009 use std::collections::BTreeMap;
1010 use std::sync::Arc;
1011 use std::time::Duration;
1012
1013 use api::v1::meta::{HeartbeatRequest, HeartbeatResponse, MailboxMessage, RequestHeader, Role};
1014 use common_meta::kv_backend::memory::MemoryKvBackend;
1015 use common_meta::sequence::SequenceBuilder;
1016 use futures::future::poll_immediate;
1017 use tokio::sync::mpsc;
1018
1019 use super::{
1020 HandleControl, HeartbeatAccumulator, HeartbeatHandler, HeartbeatHandlerGroupBuilder,
1021 PusherHandle, PusherId, Pushers,
1022 };
1023 use crate::error;
1024 use crate::handler::collect_stats_handler::CollectStatsHandler;
1025 use crate::handler::response_header_handler::ResponseHeaderHandler;
1026 use crate::handler::test_utils::TestEnv;
1027 use crate::handler::{HeartbeatHandlerGroup, HeartbeatMailbox, Pusher};
1028 use crate::metasrv::Context;
1029 use crate::service::mailbox::{Channel, MailboxReceiver, MailboxRef};
1030
1031 #[tokio::test]
1032 async fn test_mailbox() {
1033 let (mailbox, receiver) = push_msg_via_mailbox().await;
1034 let id = receiver.message_id();
1035
1036 let resp_msg = MailboxMessage {
1037 id,
1038 subject: "resp-test".to_string(),
1039 timestamp_millis: 456,
1040 ..Default::default()
1041 };
1042
1043 mailbox.on_recv(id, Ok(resp_msg)).await.unwrap();
1044
1045 let recv_msg = receiver.await.unwrap();
1046 assert_eq!(recv_msg.id, id);
1047 assert_eq!(recv_msg.timestamp_millis, 456);
1048 assert_eq!(recv_msg.subject, "resp-test".to_string());
1049 }
1050
1051 #[tokio::test]
1052 async fn test_mailbox_timeout() {
1053 let (_, receiver) = push_msg_via_mailbox().await;
1054 let res = receiver.await;
1055 assert!(res.is_err());
1056 }
1057
1058 async fn push_msg_via_mailbox() -> (MailboxRef, MailboxReceiver) {
1059 let datanode_id = 12;
1060 let (pusher_tx, mut pusher_rx) = mpsc::channel(16);
1061 let pusher_id = PusherId::new(Role::Datanode, datanode_id);
1062 let pusher: Pusher = Pusher::new(pusher_tx);
1063 let handler_group = HeartbeatHandlerGroup::default();
1064 handler_group.register_pusher(pusher_id, pusher).await;
1065
1066 let kv_backend = Arc::new(MemoryKvBackend::new());
1067 let seq = SequenceBuilder::new("test_seq", kv_backend).build();
1068 let mailbox = HeartbeatMailbox::create(handler_group.pushers(), seq);
1069
1070 let msg = MailboxMessage {
1071 id: 0,
1072 subject: "req-test".to_string(),
1073 timestamp_millis: 123,
1074 ..Default::default()
1075 };
1076 let ch = Channel::Datanode(datanode_id);
1077
1078 let receiver = mailbox
1079 .send(&ch, msg, Duration::from_secs(1))
1080 .await
1081 .unwrap();
1082
1083 let recv_obj = pusher_rx.recv().await.unwrap().unwrap();
1084 let message = recv_obj.mailbox_message.unwrap();
1085 assert_eq!(message.timestamp_millis, 123);
1086 assert_eq!(message.subject, "req-test".to_string());
1087
1088 (mailbox, receiver)
1089 }
1090
1091 #[test]
1092 fn test_pusher_id_role_range() {
1093 let mut pushers = BTreeMap::new();
1094 pushers.insert(PusherId::new(Role::Datanode, u64::MAX), "datanode");
1095 pushers.insert(PusherId::new(Role::Frontend, u64::MIN), "frontend-min");
1096 pushers.insert(PusherId::new(Role::Frontend, u64::MAX), "frontend-max");
1097 pushers.insert(PusherId::new(Role::Flownode, u64::MIN), "flownode");
1098
1099 let frontend_pushers = pushers
1100 .range(PusherId::role_range(Role::Frontend))
1101 .map(|(_, value)| *value)
1102 .collect::<Vec<_>>();
1103
1104 assert_eq!(frontend_pushers, vec!["frontend-min", "frontend-max"]);
1105 }
1106
1107 #[tokio::test]
1108 async fn test_pushers_broadcast_by_role() {
1109 let pushers = Pushers::default();
1110 let (datanode_tx, mut datanode_rx) = mpsc::channel(1);
1111 let (frontend_tx, mut frontend_rx) = mpsc::channel(1);
1112 let (flownode_tx, mut flownode_rx) = mpsc::channel(1);
1113
1114 pushers
1115 .insert(
1116 PusherId::new(Role::Datanode, u64::MAX),
1117 Pusher::new(datanode_tx),
1118 )
1119 .await;
1120 pushers
1121 .insert(PusherId::new(Role::Frontend, 1), Pusher::new(frontend_tx))
1122 .await;
1123 pushers
1124 .insert(
1125 PusherId::new(Role::Flownode, u64::MIN),
1126 Pusher::new(flownode_tx),
1127 )
1128 .await;
1129
1130 let msg = MailboxMessage {
1131 id: 42,
1132 subject: "broadcast-test".to_string(),
1133 timestamp_millis: 123,
1134 ..Default::default()
1135 };
1136
1137 pushers.broadcast(Role::Frontend, &msg).await.unwrap();
1138
1139 let received = frontend_rx.recv().await.unwrap().unwrap();
1140 let mailbox_message = received.mailbox_message.unwrap();
1141 assert_eq!(mailbox_message.id, 0);
1142 assert_eq!(mailbox_message.subject, "broadcast-test");
1143 assert!(datanode_rx.try_recv().is_err());
1144 assert!(flownode_rx.try_recv().is_err());
1145 }
1146
1147 #[test]
1148 fn test_handler_group_builder() {
1149 let group = HeartbeatHandlerGroupBuilder::new(Pushers::default())
1150 .add_default_handlers()
1151 .build()
1152 .unwrap();
1153
1154 let handlers = group.handlers;
1155 let names = [
1156 "ResponseHeaderHandler",
1157 "DatanodeKeepLeaseHandler",
1158 "FlownodeKeepLeaseHandler",
1159 "CheckLeaderHandler",
1160 "OnLeaderStartHandler",
1161 "ExtractStatHandler",
1162 "CollectDatanodeClusterInfoHandler",
1163 "CollectFrontendClusterInfoHandler",
1164 "CollectFlownodeClusterInfoHandler",
1165 "MailboxHandler",
1166 "FilterInactiveRegionStatsHandler",
1167 "CollectLeaderRegionHandler",
1168 "CollectTopicStatsHandler",
1169 "CollectStatsHandler",
1170 "RemapFlowPeerHandler",
1171 ];
1172 assert_eq!(names.len(), handlers.len());
1173 for (handler, name) in handlers.iter().zip(names) {
1174 assert_eq!(handler.name, name);
1175 }
1176 }
1177
1178 #[test]
1179 fn test_handler_group_builder_add_before() {
1180 let mut builder =
1181 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1182 builder
1183 .add_handler_before(
1184 "FilterInactiveRegionStatsHandler",
1185 CollectStatsHandler::default(),
1186 )
1187 .unwrap();
1188
1189 let group = builder.build().unwrap();
1190 let handlers = group.handlers;
1191 let names = [
1192 "ResponseHeaderHandler",
1193 "DatanodeKeepLeaseHandler",
1194 "FlownodeKeepLeaseHandler",
1195 "CheckLeaderHandler",
1196 "OnLeaderStartHandler",
1197 "ExtractStatHandler",
1198 "CollectDatanodeClusterInfoHandler",
1199 "CollectFrontendClusterInfoHandler",
1200 "CollectFlownodeClusterInfoHandler",
1201 "MailboxHandler",
1202 "CollectStatsHandler",
1203 "FilterInactiveRegionStatsHandler",
1204 "CollectLeaderRegionHandler",
1205 "CollectTopicStatsHandler",
1206 "CollectStatsHandler",
1207 "RemapFlowPeerHandler",
1208 ];
1209 assert_eq!(names.len(), handlers.len());
1210 for (handler, name) in handlers.iter().zip(names) {
1211 assert_eq!(handler.name, name);
1212 }
1213 }
1214
1215 #[test]
1216 fn test_handler_group_builder_add_before_first() {
1217 let mut builder =
1218 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1219 builder
1220 .add_handler_before("ResponseHeaderHandler", CollectStatsHandler::default())
1221 .unwrap();
1222
1223 let group = builder.build().unwrap();
1224 let handlers = group.handlers;
1225 let names = [
1226 "CollectStatsHandler",
1227 "ResponseHeaderHandler",
1228 "DatanodeKeepLeaseHandler",
1229 "FlownodeKeepLeaseHandler",
1230 "CheckLeaderHandler",
1231 "OnLeaderStartHandler",
1232 "ExtractStatHandler",
1233 "CollectDatanodeClusterInfoHandler",
1234 "CollectFrontendClusterInfoHandler",
1235 "CollectFlownodeClusterInfoHandler",
1236 "MailboxHandler",
1237 "FilterInactiveRegionStatsHandler",
1238 "CollectLeaderRegionHandler",
1239 "CollectTopicStatsHandler",
1240 "CollectStatsHandler",
1241 "RemapFlowPeerHandler",
1242 ];
1243 assert_eq!(names.len(), handlers.len());
1244 for (handler, name) in handlers.iter().zip(names) {
1245 assert_eq!(handler.name, name);
1246 }
1247 }
1248
1249 #[test]
1250 fn test_handler_group_builder_add_after() {
1251 let mut builder =
1252 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1253 builder
1254 .add_handler_after("MailboxHandler", CollectStatsHandler::default())
1255 .unwrap();
1256
1257 let group = builder.build().unwrap();
1258 let handlers = group.handlers;
1259 let names = [
1260 "ResponseHeaderHandler",
1261 "DatanodeKeepLeaseHandler",
1262 "FlownodeKeepLeaseHandler",
1263 "CheckLeaderHandler",
1264 "OnLeaderStartHandler",
1265 "ExtractStatHandler",
1266 "CollectDatanodeClusterInfoHandler",
1267 "CollectFrontendClusterInfoHandler",
1268 "CollectFlownodeClusterInfoHandler",
1269 "MailboxHandler",
1270 "CollectStatsHandler",
1271 "FilterInactiveRegionStatsHandler",
1272 "CollectLeaderRegionHandler",
1273 "CollectTopicStatsHandler",
1274 "CollectStatsHandler",
1275 "RemapFlowPeerHandler",
1276 ];
1277 assert_eq!(names.len(), handlers.len());
1278 for (handler, name) in handlers.iter().zip(names) {
1279 assert_eq!(handler.name, name);
1280 }
1281 }
1282
1283 #[test]
1284 fn test_handler_group_builder_add_after_last() {
1285 let mut builder =
1286 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1287 builder
1288 .add_handler_after("CollectStatsHandler", ResponseHeaderHandler)
1289 .unwrap();
1290
1291 let group = builder.build().unwrap();
1292 let handlers = group.handlers;
1293 let names = [
1294 "ResponseHeaderHandler",
1295 "DatanodeKeepLeaseHandler",
1296 "FlownodeKeepLeaseHandler",
1297 "CheckLeaderHandler",
1298 "OnLeaderStartHandler",
1299 "ExtractStatHandler",
1300 "CollectDatanodeClusterInfoHandler",
1301 "CollectFrontendClusterInfoHandler",
1302 "CollectFlownodeClusterInfoHandler",
1303 "MailboxHandler",
1304 "FilterInactiveRegionStatsHandler",
1305 "CollectLeaderRegionHandler",
1306 "CollectTopicStatsHandler",
1307 "CollectStatsHandler",
1308 "ResponseHeaderHandler",
1309 "RemapFlowPeerHandler",
1310 ];
1311 assert_eq!(names.len(), handlers.len());
1312 for (handler, name) in handlers.iter().zip(names) {
1313 assert_eq!(handler.name, name);
1314 }
1315 }
1316
1317 #[test]
1318 fn test_handler_group_builder_replace() {
1319 let mut builder =
1320 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1321 builder
1322 .replace_handler("MailboxHandler", CollectStatsHandler::default())
1323 .unwrap();
1324
1325 let group = builder.build().unwrap();
1326 let handlers = group.handlers;
1327 let names = [
1328 "ResponseHeaderHandler",
1329 "DatanodeKeepLeaseHandler",
1330 "FlownodeKeepLeaseHandler",
1331 "CheckLeaderHandler",
1332 "OnLeaderStartHandler",
1333 "ExtractStatHandler",
1334 "CollectDatanodeClusterInfoHandler",
1335 "CollectFrontendClusterInfoHandler",
1336 "CollectFlownodeClusterInfoHandler",
1337 "CollectStatsHandler",
1338 "FilterInactiveRegionStatsHandler",
1339 "CollectLeaderRegionHandler",
1340 "CollectTopicStatsHandler",
1341 "CollectStatsHandler",
1342 "RemapFlowPeerHandler",
1343 ];
1344
1345 assert_eq!(names.len(), handlers.len());
1346 for (handler, name) in handlers.iter().zip(names) {
1347 assert_eq!(handler.name, name);
1348 }
1349 }
1350
1351 #[test]
1352 fn test_handler_group_builder_replace_last() {
1353 let mut builder =
1354 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1355 builder
1356 .replace_handler("CollectStatsHandler", ResponseHeaderHandler)
1357 .unwrap();
1358
1359 let group = builder.build().unwrap();
1360 let handlers = group.handlers;
1361 let names = [
1362 "ResponseHeaderHandler",
1363 "DatanodeKeepLeaseHandler",
1364 "FlownodeKeepLeaseHandler",
1365 "CheckLeaderHandler",
1366 "OnLeaderStartHandler",
1367 "ExtractStatHandler",
1368 "CollectDatanodeClusterInfoHandler",
1369 "CollectFrontendClusterInfoHandler",
1370 "CollectFlownodeClusterInfoHandler",
1371 "MailboxHandler",
1372 "FilterInactiveRegionStatsHandler",
1373 "CollectLeaderRegionHandler",
1374 "CollectTopicStatsHandler",
1375 "ResponseHeaderHandler",
1376 "RemapFlowPeerHandler",
1377 ];
1378
1379 assert_eq!(names.len(), handlers.len());
1380 for (handler, name) in handlers.iter().zip(names) {
1381 assert_eq!(handler.name, name);
1382 }
1383 }
1384
1385 #[test]
1386 fn test_handler_group_builder_replace_first() {
1387 let mut builder =
1388 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1389 builder
1390 .replace_handler("ResponseHeaderHandler", CollectStatsHandler::default())
1391 .unwrap();
1392
1393 let group = builder.build().unwrap();
1394 let handlers = group.handlers;
1395 let names = [
1396 "CollectStatsHandler",
1397 "DatanodeKeepLeaseHandler",
1398 "FlownodeKeepLeaseHandler",
1399 "CheckLeaderHandler",
1400 "OnLeaderStartHandler",
1401 "ExtractStatHandler",
1402 "CollectDatanodeClusterInfoHandler",
1403 "CollectFrontendClusterInfoHandler",
1404 "CollectFlownodeClusterInfoHandler",
1405 "MailboxHandler",
1406 "FilterInactiveRegionStatsHandler",
1407 "CollectLeaderRegionHandler",
1408 "CollectTopicStatsHandler",
1409 "CollectStatsHandler",
1410 "RemapFlowPeerHandler",
1411 ];
1412 assert_eq!(names.len(), handlers.len());
1413 for (handler, name) in handlers.iter().zip(names) {
1414 assert_eq!(handler.name, name);
1415 }
1416 }
1417
1418 #[test]
1419 fn test_handler_group_builder_handler_not_found() {
1420 let mut builder =
1421 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1422 let err = builder
1423 .add_handler_before("NotExists", CollectStatsHandler::default())
1424 .unwrap_err();
1425 assert_matches!(err, error::Error::HandlerNotFound { .. });
1426
1427 let err = builder
1428 .add_handler_after("NotExists", CollectStatsHandler::default())
1429 .unwrap_err();
1430 assert_matches!(err, error::Error::HandlerNotFound { .. });
1431
1432 let err = builder
1433 .replace_handler("NotExists", CollectStatsHandler::default())
1434 .unwrap_err();
1435 assert_matches!(err, error::Error::HandlerNotFound { .. });
1436 }
1437
1438 #[tokio::test]
1439 async fn test_pusher_drop() {
1440 let (tx, _rx) = mpsc::channel(1);
1441 let pusher = Pusher::new(tx);
1442 let mut deregister_signal_tx = pusher.deregister_signal_receiver.clone();
1443
1444 drop(pusher);
1445 deregister_signal_tx.changed().await.unwrap();
1446 }
1447
1448 #[tokio::test]
1449 async fn test_custom_handler_extension_reaches_response() {
1450 struct CustomExtensionHandler;
1451
1452 #[async_trait::async_trait]
1453 impl HeartbeatHandler for CustomExtensionHandler {
1454 fn is_acceptable(&self, role: Role) -> bool {
1455 role == Role::Frontend
1456 }
1457
1458 async fn handle(
1459 &self,
1460 _req: &HeartbeatRequest,
1461 _ctx: &mut Context,
1462 acc: &mut HeartbeatAccumulator,
1463 ) -> crate::error::Result<HandleControl> {
1464 acc.extensions
1465 .insert("custom.key".to_string(), b"custom-value".to_vec());
1466 Ok(HandleControl::Continue)
1467 }
1468 }
1469
1470 let mut builder =
1471 HeartbeatHandlerGroupBuilder::new(Pushers::default()).add_default_handlers();
1472 builder.add_handler_last(CustomExtensionHandler);
1473
1474 let group = builder.build().unwrap();
1475
1476 let req = HeartbeatRequest {
1477 header: Some(RequestHeader::new(1, Role::Frontend, Default::default())),
1478 ..Default::default()
1479 };
1480 let ctx = TestEnv::new().ctx();
1481
1482 let res = group.handle(req, ctx).await.unwrap();
1483
1484 let extensions = res.extensions;
1485 assert_eq!(extensions.get("custom.key").unwrap(), b"custom-value");
1486 }
1487
1488 async fn full_pusher(
1489 pushers: &Pushers,
1490 id: PusherId,
1491 ) -> mpsc::Receiver<std::result::Result<HeartbeatResponse, tonic::Status>> {
1492 let (tx, rx) = mpsc::channel(1);
1493 tx.try_send(Ok(HeartbeatResponse::default())).unwrap();
1494 pushers.insert(id, Pusher::new(tx)).await;
1495 rx
1497 }
1498
1499 fn test_mailbox_message(subject: &str) -> MailboxMessage {
1500 MailboxMessage {
1501 id: 0,
1502 subject: subject.to_string(),
1503 timestamp_millis: 123,
1504 ..Default::default()
1505 }
1506 }
1507
1508 #[tokio::test]
1509 async fn test_pushers_push_does_not_fence_the_registry() {
1510 let pushers = Pushers::default();
1511
1512 let full_id = PusherId::new(Role::Datanode, 1);
1513 let _full_rx = full_pusher(&pushers, full_id).await;
1514
1515 let (healthy_tx, mut healthy_rx) = mpsc::channel(1);
1516 let healthy_id = PusherId::new(Role::Datanode, 2);
1517 pushers.insert(healthy_id, Pusher::new(healthy_tx)).await;
1518
1519 let msg = test_mailbox_message("fence-test");
1520
1521 let mut parked = Box::pin(pushers.push(full_id, msg.clone()));
1522 assert!(poll_immediate(parked.as_mut()).await.is_none());
1523
1524 let (writer_tx, _writer_rx) = mpsc::channel(1);
1525 let mut writer =
1526 Box::pin(pushers.insert(PusherId::new(Role::Datanode, 3), Pusher::new(writer_tx)));
1527 assert!(poll_immediate(writer.as_mut()).await.is_some());
1528
1529 let mut healthy = Box::pin(pushers.push(healthy_id, msg));
1530 assert!(poll_immediate(healthy.as_mut()).await.is_some());
1531 assert!(healthy_rx.try_recv().is_ok());
1532 }
1533
1534 #[tokio::test]
1535 async fn test_pusher_insert_reports_an_empty_slot() {
1536 let pushers = Pushers::default();
1537 let id = PusherId::new(Role::Datanode, 1);
1538 let (tx1, _rx1) = mpsc::channel(1);
1539 let (tx2, _rx2) = mpsc::channel(1);
1540 assert_eq!(
1541 pushers.insert(id, Pusher::new(tx1.clone())).await,
1542 Some(true)
1543 );
1544 let in_place = Pusher::new(tx1).with_node_epoch(2);
1546 assert_eq!(pushers.insert(id, in_place).await, Some(false));
1547 let lower = Pusher::new(tx2.clone()).with_node_epoch(1);
1548 assert_eq!(pushers.insert(id, lower).await, None);
1549 let other = Pusher::new(tx2).with_node_epoch(2);
1550 assert_eq!(pushers.insert(id, other).await, Some(false));
1551 }
1552
1553 #[tokio::test]
1554 async fn test_pushers_broadcast_does_not_fence_the_registry() {
1555 let pushers = Pushers::default();
1556
1557 let _full_rx = full_pusher(&pushers, PusherId::new(Role::Datanode, 1)).await;
1558 let (healthy_tx, _healthy_rx) = mpsc::channel(1);
1559 pushers
1560 .insert(PusherId::new(Role::Datanode, 2), Pusher::new(healthy_tx))
1561 .await;
1562
1563 let msg = test_mailbox_message("broadcast-fence-test");
1564 let mut parked = Box::pin(pushers.broadcast(Role::Datanode, &msg));
1565 assert!(poll_immediate(parked.as_mut()).await.is_none());
1566
1567 let (writer_tx, _writer_rx) = mpsc::channel(1);
1568 let mut writer =
1569 Box::pin(pushers.insert(PusherId::new(Role::Flownode, 1), Pusher::new(writer_tx)));
1570 assert!(poll_immediate(writer.as_mut()).await.is_some());
1571 }
1572
1573 #[tokio::test]
1574 async fn test_pusher_handle_does_not_fire_the_deregister_signal() {
1575 let (tx, _rx) = mpsc::channel(1);
1576 let pusher = Pusher::new(tx);
1577 let mut signal = pusher.deregister_signal_receiver.clone();
1578
1579 let handle = PusherHandle::from_pusher(&pusher);
1580 drop(handle);
1581
1582 assert!(
1583 tokio::time::timeout(Duration::from_millis(100), signal.changed())
1584 .await
1585 .is_err()
1586 );
1587
1588 drop(pusher);
1590 assert!(signal.changed().await.is_ok());
1591 }
1592}