Skip to main content

meta_srv/
handler.rs

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