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