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