1pub mod builder;
16
17use std::fmt::{self, Display};
18use std::sync::atomic::{AtomicBool, Ordering};
19use std::sync::{Arc, Mutex, RwLock};
20use std::time::Duration;
21
22use api::v1::meta::{HeartbeatConfig, Role};
23use clap::ValueEnum;
24use common_base::Plugins;
25use common_base::readable_size::ReadableSize;
26use common_config::{Configurable, DEFAULT_DATA_HOME};
27use common_event_recorder::EventRecorderOptions;
28use common_greptimedb_telemetry::GreptimeDBTelemetryTask;
29use common_meta::affinity::{AffinityFallback, AffinityRef, AffinityResolverRef};
30use common_meta::cache_invalidator::CacheInvalidatorRef;
31use common_meta::ddl::allocator::resource_id::ResourceIdAllocatorRef;
32use common_meta::ddl_manager::DdlManagerRef;
33use common_meta::distributed_time_constants::{
34 self, BASE_HEARTBEAT_INTERVAL, default_distributed_time_constants, frontend_heartbeat_interval,
35};
36use common_meta::election::LeaderChangeMessage;
37pub use common_meta::election::{ElectionRef, MetasrvNodeInfo};
38use common_meta::key::TableMetadataManagerRef;
39use common_meta::key::runtime_switch::RuntimeSwitchManagerRef;
40use common_meta::kv_backend::{KvBackendRef, ResettableKvBackend, ResettableKvBackendRef};
41use common_meta::leadership_notifier::{
42 LeadershipChangeNotifier, LeadershipChangeNotifierCustomizerRef,
43};
44use common_meta::node_expiry_listener::NodeExpiryListener;
45use common_meta::peer::{Peer, PeerDiscoveryRef};
46use common_meta::reconciliation::manager::ReconciliationManagerRef;
47use common_meta::region_keeper::MemoryRegionKeeperRef;
48use common_meta::region_registry::LeaderRegionRegistryRef;
49use common_meta::stats::topic::TopicStatsRegistryRef;
50use common_meta::wal_provider::WalProviderRef;
51use common_options::datanode::DatanodeClientOptions;
52use common_options::memory::MemoryOptions;
53use common_procedure::ProcedureManagerRef;
54use common_procedure::options::ProcedureConfig;
55use common_stat::ResourceStatRef;
56use common_telemetry::logging::{LoggingOptions, TracingOptions};
57use common_telemetry::{error, info, warn};
58use common_time::util::DefaultSystemTimer;
59use common_wal::config::MetasrvWalConfig;
60use serde::{Deserialize, Serialize};
61use servers::grpc::GrpcOptions;
62use servers::http::HttpOptions;
63use servers::tls::TlsOption;
64use snafu::{OptionExt, ResultExt};
65use store_api::storage::RegionId;
66use tokio::sync::broadcast::error::RecvError;
67
68use crate::cluster::MetaPeerClientRef;
69use crate::discovery;
70use crate::discovery::node_info::NodeInfoAccessor;
71use crate::error::{
72 self, InitMetadataSnafu, KvBackendSnafu, Result, StartProcedureManagerSnafu,
73 StartTelemetryTaskSnafu, StopProcedureManagerSnafu,
74};
75use crate::failure_detector::PhiAccrualFailureDetectorOptions;
76use crate::gc::{GcSchedulerOptions, GcTickerRef};
77use crate::handler::{HeartbeatHandlerGroupBuilder, HeartbeatHandlerGroupRef};
78use crate::node_scheduling::NodeSchedulingManagerRef;
79use crate::procedure::ProcedureManagerListenerAdapter;
80use crate::procedure::drain_datanode::manager::DrainDatanodeManagerRef;
81use crate::procedure::region_migration::manager::RegionMigrationManagerRef;
82use crate::procedure::repartition::gc_requirement::RepartitionGcRequirementManagerRef;
83use crate::procedure::wal_prune::manager::WalPruneTickerRef;
84use crate::pubsub::{PublisherRef, SubscriptionManagerRef};
85use crate::region::flush_trigger::RegionFlushTickerRef;
86use crate::region::supervisor::RegionSupervisorTickerRef;
87use crate::selector::{RegionStatAwareSelector, Selector, SelectorType};
88use crate::service::mailbox::MailboxRef;
89use crate::service::store::cached_kv::LeaderCachedKvBackend;
90use crate::state::{StateRef, become_follower, become_leader};
91use crate::utils::database::DatabaseOperatorRef;
92
93pub const TABLE_ID_SEQ: &str = "table_id";
94pub const FLOW_ID_SEQ: &str = "flow_id";
95pub const METASRV_DATA_DIR: &str = "metasrv";
96
97#[derive(Clone, Debug, PartialEq, Serialize, Default, Deserialize, ValueEnum)]
99#[serde(rename_all = "snake_case")]
100pub enum BackendImpl {
101 #[default]
103 EtcdStore,
104 MemoryStore,
106 #[cfg(feature = "pg_kvbackend")]
107 PostgresStore,
109 #[cfg(feature = "mysql_kvbackend")]
110 MysqlStore,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
116pub struct StatsPersistenceOptions {
117 #[serde(with = "humantime_serde")]
119 pub ttl: Duration,
120 #[serde(with = "humantime_serde")]
122 pub interval: Duration,
123}
124
125impl Default for StatsPersistenceOptions {
126 fn default() -> Self {
127 Self {
128 ttl: Duration::ZERO,
129 interval: Duration::from_secs(10 * 60),
130 }
131 }
132}
133
134#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
136#[serde(default)]
137pub struct HeartbeatOptions {
138 #[serde(with = "humantime_serde")]
140 pub interval: Duration,
141 #[serde(with = "humantime_serde")]
143 pub retry_interval: Duration,
144}
145
146impl Default for HeartbeatOptions {
147 fn default() -> Self {
148 Self {
149 interval: BASE_HEARTBEAT_INTERVAL,
150 retry_interval: BASE_HEARTBEAT_INTERVAL,
151 }
152 }
153}
154
155impl HeartbeatOptions {
156 pub fn datanode_from(base_interval: Duration) -> Self {
157 Self {
158 interval: base_interval,
159 retry_interval: base_interval,
160 }
161 }
162
163 pub fn frontend_from(base_interval: Duration) -> Self {
164 Self {
165 interval: frontend_heartbeat_interval(base_interval),
166 retry_interval: base_interval,
167 }
168 }
169
170 pub fn flownode_from(base_interval: Duration) -> Self {
171 Self {
172 interval: base_interval,
173 retry_interval: base_interval,
174 }
175 }
176}
177
178impl From<HeartbeatOptions> for HeartbeatConfig {
179 fn from(opts: HeartbeatOptions) -> Self {
180 Self {
181 heartbeat_interval_ms: opts.interval.as_millis() as u64,
182 retry_interval_ms: opts.retry_interval.as_millis() as u64,
183 gc_enabled: false,
184 }
185 }
186}
187
188#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
189#[serde(default)]
190pub struct BackendClientOptions {
191 #[serde(with = "humantime_serde")]
192 pub keep_alive_timeout: Duration,
193 #[serde(with = "humantime_serde")]
194 pub keep_alive_interval: Duration,
195 #[serde(with = "humantime_serde")]
196 pub connect_timeout: Duration,
197}
198
199impl Default for BackendClientOptions {
200 fn default() -> Self {
201 Self {
202 keep_alive_interval: Duration::from_secs(10),
203 keep_alive_timeout: Duration::from_secs(3),
204 connect_timeout: Duration::from_secs(3),
205 }
206 }
207}
208
209#[derive(Clone, PartialEq, Serialize, Deserialize)]
210#[serde(default)]
211pub struct MetasrvOptions {
212 #[deprecated(note = "Use grpc.bind_addr instead")]
214 pub bind_addr: String,
215 #[deprecated(note = "Use grpc.server_addr instead")]
217 pub server_addr: String,
218 pub store_addrs: Vec<String>,
220 #[serde(default)]
223 pub backend_tls: Option<TlsOption>,
224 #[serde(default)]
227 pub backend_client: BackendClientOptions,
228 pub selector: SelectorType,
230 pub enable_region_failover: bool,
232 #[serde(with = "humantime_serde")]
237 pub heartbeat_interval: Duration,
238 #[serde(with = "humantime_serde")]
242 pub region_failure_detector_initialization_delay: Duration,
243 pub allow_region_failover_on_local_wal: bool,
248 pub grpc: GrpcOptions,
249 pub http: HttpOptions,
251 pub logging: LoggingOptions,
253 pub procedure: ProcedureConfig,
255 pub failure_detector: PhiAccrualFailureDetectorOptions,
257 pub datanode: DatanodeClientOptions,
259 pub enable_telemetry: bool,
261 pub data_home: String,
263 pub wal: MetasrvWalConfig,
265 pub store_key_prefix: String,
268 pub max_txn_ops: usize,
279 pub flush_stats_factor: usize,
283 pub tracing: TracingOptions,
285 pub memory: MemoryOptions,
287 pub backend: BackendImpl,
289 #[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
290 pub meta_table_name: String,
292 #[cfg(feature = "pg_kvbackend")]
293 pub meta_election_lock_id: u64,
295 #[cfg(feature = "pg_kvbackend")]
296 pub meta_schema_name: Option<String>,
298 #[cfg(feature = "pg_kvbackend")]
299 pub auto_create_schema: bool,
301 #[serde(with = "humantime_serde")]
302 pub node_max_idle_time: Duration,
303 pub event_recorder: EventRecorderOptions,
305 pub stats_persistence: StatsPersistenceOptions,
307 pub gc: GcSchedulerOptions,
309}
310
311impl fmt::Debug for MetasrvOptions {
312 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313 let mut debug_struct = f.debug_struct("MetasrvOptions");
314 debug_struct
315 .field("store_addrs", &self.sanitize_store_addrs())
316 .field("backend_tls", &self.backend_tls)
317 .field("selector", &self.selector)
318 .field("enable_region_failover", &self.enable_region_failover)
319 .field(
320 "allow_region_failover_on_local_wal",
321 &self.allow_region_failover_on_local_wal,
322 )
323 .field("grpc", &self.grpc)
324 .field("http", &self.http)
325 .field("logging", &self.logging)
326 .field("procedure", &self.procedure)
327 .field("failure_detector", &self.failure_detector)
328 .field("datanode", &self.datanode)
329 .field("enable_telemetry", &self.enable_telemetry)
330 .field("data_home", &self.data_home)
331 .field("wal", &self.wal)
332 .field("store_key_prefix", &self.store_key_prefix)
333 .field("max_txn_ops", &self.max_txn_ops)
334 .field("flush_stats_factor", &self.flush_stats_factor)
335 .field("tracing", &self.tracing)
336 .field("backend", &self.backend)
337 .field("event_recorder", &self.event_recorder)
338 .field("stats_persistence", &self.stats_persistence)
339 .field("heartbeat_interval", &self.heartbeat_interval)
340 .field("backend_client", &self.backend_client);
341
342 #[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
343 debug_struct.field("meta_table_name", &self.meta_table_name);
344
345 #[cfg(feature = "pg_kvbackend")]
346 debug_struct.field("meta_election_lock_id", &self.meta_election_lock_id);
347 #[cfg(feature = "pg_kvbackend")]
348 debug_struct.field("meta_schema_name", &self.meta_schema_name);
349
350 debug_struct
351 .field("node_max_idle_time", &self.node_max_idle_time)
352 .finish()
353 }
354}
355
356const DEFAULT_METASRV_ADDR_PORT: &str = "3002";
357
358impl Default for MetasrvOptions {
359 fn default() -> Self {
360 Self {
361 #[allow(deprecated)]
362 bind_addr: String::new(),
363 #[allow(deprecated)]
364 server_addr: String::new(),
365 store_addrs: vec!["127.0.0.1:2379".to_string()],
366 backend_tls: Some(TlsOption::prefer()),
367 selector: SelectorType::default(),
368 enable_region_failover: false,
369 heartbeat_interval: distributed_time_constants::BASE_HEARTBEAT_INTERVAL,
370 region_failure_detector_initialization_delay: Duration::from_secs(10 * 60),
371 allow_region_failover_on_local_wal: false,
372 grpc: GrpcOptions {
373 bind_addr: format!("127.0.0.1:{}", DEFAULT_METASRV_ADDR_PORT),
374 ..Default::default()
375 },
376 http: HttpOptions::default(),
377 logging: LoggingOptions::default(),
378 procedure: ProcedureConfig {
379 max_retry_times: 12,
380 retry_delay: Duration::from_millis(500),
381 max_metadata_value_size: Some(ReadableSize::kb(1500)),
384 max_running_procedures: 128,
385 },
386 failure_detector: PhiAccrualFailureDetectorOptions::default(),
387 datanode: DatanodeClientOptions::default(),
388 enable_telemetry: true,
389 data_home: DEFAULT_DATA_HOME.to_string(),
390 wal: MetasrvWalConfig::default(),
391 store_key_prefix: String::new(),
392 max_txn_ops: 128,
393 flush_stats_factor: 3,
394 tracing: TracingOptions::default(),
395 memory: MemoryOptions::default(),
396 backend: BackendImpl::EtcdStore,
397 #[cfg(any(feature = "pg_kvbackend", feature = "mysql_kvbackend"))]
398 meta_table_name: common_meta::kv_backend::DEFAULT_META_TABLE_NAME.to_string(),
399 #[cfg(feature = "pg_kvbackend")]
400 meta_election_lock_id: common_meta::kv_backend::DEFAULT_META_ELECTION_LOCK_ID,
401 #[cfg(feature = "pg_kvbackend")]
402 meta_schema_name: None,
403 #[cfg(feature = "pg_kvbackend")]
404 auto_create_schema: true,
405 node_max_idle_time: Duration::from_secs(24 * 60 * 60),
406 event_recorder: EventRecorderOptions::default(),
407 stats_persistence: StatsPersistenceOptions::default(),
408 gc: GcSchedulerOptions::default(),
409 backend_client: BackendClientOptions::default(),
410 }
411 }
412}
413
414impl Configurable for MetasrvOptions {
415 fn env_list_keys() -> Option<&'static [&'static str]> {
416 Some(&[
417 "wal.broker_endpoints",
418 "store_addrs",
419 "event_recorder.event_types",
420 ])
421 }
422}
423
424impl MetasrvOptions {
425 fn sanitize_store_addrs(&self) -> Vec<String> {
426 self.store_addrs
427 .iter()
428 .map(|addr| common_meta::kv_backend::util::sanitize_connection_string(addr))
429 .collect()
430 }
431}
432
433pub struct MetasrvInfo {
434 pub server_addr: String,
435}
436#[derive(Clone)]
437pub struct Context {
438 pub server_addr: String,
439 pub in_memory: ResettableKvBackendRef,
440 pub kv_backend: KvBackendRef,
441 pub leader_cached_kv_backend: ResettableKvBackendRef,
442 pub meta_peer_client: MetaPeerClientRef,
443 pub mailbox: MailboxRef,
444 pub election: Option<ElectionRef>,
445 pub is_infancy: bool,
446 pub table_metadata_manager: TableMetadataManagerRef,
447 pub cache_invalidator: CacheInvalidatorRef,
448 pub leader_region_registry: LeaderRegionRegistryRef,
449 pub topic_stats_registry: TopicStatsRegistryRef,
450 pub heartbeat_interval: Duration,
451 pub gc_enabled: bool,
452 pub is_handshake: bool,
453}
454
455impl Context {
456 pub fn reset_in_memory(&self) {
457 self.in_memory.reset();
458 self.leader_region_registry.reset();
459 }
460
461 pub fn with_handshake(mut self, is_handshake: bool) -> Self {
462 self.is_handshake = is_handshake;
463 self
464 }
465
466 pub fn heartbeat_options_for(&self, role: Role) -> HeartbeatOptions {
467 match role {
468 Role::Datanode => HeartbeatOptions::datanode_from(self.heartbeat_interval),
469 Role::Frontend => HeartbeatOptions::frontend_from(self.heartbeat_interval),
470 Role::Flownode => HeartbeatOptions::flownode_from(self.heartbeat_interval),
471 }
472 }
473}
474
475#[derive(Clone, Copy)]
476pub enum SelectTarget {
477 Datanode,
478 Flownode,
479}
480
481impl Display for SelectTarget {
482 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
483 match self {
484 SelectTarget::Datanode => write!(f, "datanode"),
485 SelectTarget::Flownode => write!(f, "flownode"),
486 }
487 }
488}
489
490#[derive(Clone)]
491pub struct SelectorContext {
492 pub peer_discovery: PeerDiscoveryRef,
493 pub affinity: AffinityRef,
495 pub affinity_fallback: AffinityFallback,
497}
498
499pub type SelectorRef = Arc<dyn Selector<Context = SelectorContext, Output = Vec<Peer>>>;
500
501pub struct SelectorFactoryContext {
508 pub metasrv_options: MetasrvOptions,
509 pub meta_peer_client: MetaPeerClientRef,
510 pub in_memory: ResettableKvBackendRef,
511 pub election: Option<ElectionRef>,
512 pub base_selector: SelectorRef,
513}
514
515pub trait SelectorFactory: Send + Sync {
517 fn build(&self, ctx: SelectorFactoryContext) -> SelectorRef;
518
519 fn build_affinity_resolver(
524 &self,
525 _node_info_accessor: Arc<dyn NodeInfoAccessor>,
526 _peer_discovery: PeerDiscoveryRef,
527 ) -> Option<AffinityResolverRef> {
528 None
529 }
530}
531
532pub type SelectorFactoryRef = Arc<dyn SelectorFactory>;
534pub type RegionStatAwareSelectorRef =
535 Arc<dyn RegionStatAwareSelector<Context = SelectorContext, Output = Vec<(RegionId, Peer)>>>;
536
537pub struct MetaStateHandler {
538 subscribe_manager: Option<SubscriptionManagerRef>,
539 greptimedb_telemetry_task: Arc<GreptimeDBTelemetryTask>,
540 leader_cached_kv_backend: Arc<LeaderCachedKvBackend>,
541 leadership_change_notifier: LeadershipChangeNotifier,
542 state: StateRef,
543}
544
545impl MetaStateHandler {
546 pub async fn on_leader_start(&self) {
547 self.state.write().unwrap().next_state(become_leader(false));
548
549 if let Err(e) = self.leader_cached_kv_backend.load().await {
550 error!(e; "Failed to load kv into leader cache kv store");
551 } else {
552 self.state.write().unwrap().next_state(become_leader(true));
553 }
554
555 self.leadership_change_notifier
556 .notify_on_leader_start()
557 .await;
558
559 self.greptimedb_telemetry_task.should_report(true);
560 }
561
562 pub async fn on_leader_stop(&self) {
563 self.state.write().unwrap().next_state(become_follower());
564
565 self.leadership_change_notifier
566 .notify_on_leader_stop()
567 .await;
568
569 self.greptimedb_telemetry_task.should_report(false);
571
572 if let Some(sub_manager) = self.subscribe_manager.clone() {
573 info!("Leader changed, un_subscribe all");
574 if let Err(e) = sub_manager.unsubscribe_all() {
575 error!(e; "Failed to un_subscribe all");
576 }
577 }
578 }
579}
580
581pub struct Metasrv {
582 state: StateRef,
583 started: Arc<AtomicBool>,
584 start_time_ms: u64,
585 options: MetasrvOptions,
586 in_memory: ResettableKvBackendRef,
589 kv_backend: KvBackendRef,
590 leader_cached_kv_backend: Arc<LeaderCachedKvBackend>,
591 meta_peer_client: MetaPeerClientRef,
592 selector: SelectorRef,
594 selector_ctx: SelectorContext,
595 flow_selector: SelectorRef,
597 handler_group: RwLock<Option<HeartbeatHandlerGroupRef>>,
598 handler_group_builder: Mutex<Option<HeartbeatHandlerGroupBuilder>>,
599 election: Option<ElectionRef>,
600 procedure_manager: ProcedureManagerRef,
601 mailbox: MailboxRef,
602 ddl_manager: DdlManagerRef,
603 wal_provider: WalProviderRef,
604 table_metadata_manager: TableMetadataManagerRef,
605 runtime_switch_manager: RuntimeSwitchManagerRef,
606 repartition_gc_requirement_manager: RepartitionGcRequirementManagerRef,
607 memory_region_keeper: MemoryRegionKeeperRef,
608 greptimedb_telemetry_task: Arc<GreptimeDBTelemetryTask>,
609 region_migration_manager: RegionMigrationManagerRef,
610 drain_datanode_manager: DrainDatanodeManagerRef,
611 region_supervisor_ticker: Option<RegionSupervisorTickerRef>,
612 cache_invalidator: CacheInvalidatorRef,
613 leader_region_registry: LeaderRegionRegistryRef,
614 topic_stats_registry: TopicStatsRegistryRef,
615 wal_prune_ticker: Option<WalPruneTickerRef>,
616 region_flush_ticker: Option<RegionFlushTickerRef>,
617 table_id_allocator: ResourceIdAllocatorRef,
618 reconciliation_manager: ReconciliationManagerRef,
619 resource_stat: ResourceStatRef,
620 gc_ticker: Option<GcTickerRef>,
621 database_operator: DatabaseOperatorRef,
622 node_scheduling_manager: NodeSchedulingManagerRef,
623
624 plugins: Plugins,
625}
626
627impl Metasrv {
628 pub(crate) async fn ensure_repartition_gc_enabled(&self) -> Result<()> {
629 self.repartition_gc_requirement_manager
630 .ensure_gc_enabled(self.options.gc.enable, &self.procedure_manager)
631 .await
632 }
633
634 pub async fn try_start(&self) -> Result<()> {
635 self.ensure_repartition_gc_enabled().await?;
636 self.try_start_after_gc_check().await
637 }
638
639 pub(crate) async fn try_start_after_gc_check(&self) -> Result<()> {
640 if self
641 .started
642 .compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire)
643 .is_err()
644 {
645 warn!("Metasrv already started");
646 return Ok(());
647 }
648
649 let handler_group_builder =
650 self.handler_group_builder
651 .lock()
652 .unwrap()
653 .take()
654 .context(error::UnexpectedSnafu {
655 violated: "expected heartbeat handler group builder",
656 })?;
657 *self.handler_group.write().unwrap() = Some(Arc::new(handler_group_builder.build()?));
658
659 self.table_metadata_manager
661 .init()
662 .await
663 .context(InitMetadataSnafu)?;
664
665 if let Some(election) = self.election() {
666 let procedure_manager = self.procedure_manager.clone();
667 let in_memory = self.in_memory.clone();
668 let leader_cached_kv_backend = self.leader_cached_kv_backend.clone();
669 let subscribe_manager = self.subscription_manager();
670 let mut rx = election.subscribe_leader_change();
671 let greptimedb_telemetry_task = self.greptimedb_telemetry_task.clone();
672 greptimedb_telemetry_task
673 .start()
674 .context(StartTelemetryTaskSnafu)?;
675
676 let mut leadership_change_notifier = LeadershipChangeNotifier::default();
678 leadership_change_notifier.add_listener(self.wal_provider.clone());
679 leadership_change_notifier
680 .add_listener(Arc::new(ProcedureManagerListenerAdapter(procedure_manager)));
681 leadership_change_notifier.add_listener(Arc::new(NodeExpiryListener::new(
682 self.options.node_max_idle_time,
683 self.in_memory.clone(),
684 )));
685 if let Some(region_supervisor_ticker) = &self.region_supervisor_ticker {
686 leadership_change_notifier.add_listener(region_supervisor_ticker.clone() as _);
687 }
688 if let Some(wal_prune_ticker) = &self.wal_prune_ticker {
689 leadership_change_notifier.add_listener(wal_prune_ticker.clone() as _);
690 }
691 if let Some(region_flush_trigger) = &self.region_flush_ticker {
692 leadership_change_notifier.add_listener(region_flush_trigger.clone() as _);
693 }
694 if let Some(gc_ticker) = &self.gc_ticker {
695 leadership_change_notifier.add_listener(gc_ticker.clone() as _);
696 }
697 if let Some(customizer) = self.plugins.get::<LeadershipChangeNotifierCustomizerRef>() {
698 customizer.customize(&mut leadership_change_notifier);
699 }
700
701 let state_handler = MetaStateHandler {
702 greptimedb_telemetry_task,
703 subscribe_manager,
704 state: self.state.clone(),
705 leader_cached_kv_backend: leader_cached_kv_backend.clone(),
706 leadership_change_notifier,
707 };
708 let _handle = common_runtime::spawn_global(async move {
709 loop {
710 match rx.recv().await {
711 Ok(msg) => {
712 in_memory.reset();
713 leader_cached_kv_backend.reset();
714 info!("Leader's cache has bean cleared on leader change: {msg}");
715 match msg {
716 LeaderChangeMessage::Elected(_) => {
717 state_handler.on_leader_start().await;
718 }
719 LeaderChangeMessage::StepDown(leader) => {
720 error!("Leader :{:?} step down", leader);
721
722 state_handler.on_leader_stop().await;
723 }
724 }
725 }
726 Err(RecvError::Closed) => {
727 error!("Not expected, is leader election loop still running?");
728 break;
729 }
730 Err(RecvError::Lagged(_)) => {
731 break;
732 }
733 }
734 }
735
736 state_handler.on_leader_stop().await;
737 });
738
739 {
741 let election = election.clone();
742 let started = self.started.clone();
743 let node_info = self.node_info();
744 let _handle = common_runtime::spawn_global(async move {
745 while started.load(Ordering::Acquire) {
746 let res = election.register_candidate(&node_info).await;
747 if let Err(e) = res {
748 warn!(e; "Metasrv register candidate error");
749 }
750 }
751 });
752 }
753
754 {
756 let election = election.clone();
757 let started = self.started.clone();
758 let _handle = common_runtime::spawn_global(async move {
759 while started.load(Ordering::Acquire) {
760 let res = election.campaign().await;
761 if let Err(e) = res {
762 warn!(e; "Metasrv election error");
763 }
764 election.reset_campaign().await;
765 info!("Metasrv re-initiate election");
766 }
767 info!("Metasrv stopped");
768 });
769 }
770 } else {
771 warn!(
772 "Ensure only one instance of Metasrv is running, as there is no election service."
773 );
774
775 if let Err(e) = self.wal_provider.start().await {
776 error!(e; "Failed to start wal provider");
777 }
778 self.leader_cached_kv_backend
780 .load()
781 .await
782 .context(KvBackendSnafu)?;
783 self.procedure_manager
784 .start()
785 .await
786 .context(StartProcedureManagerSnafu)?;
787 }
788
789 info!("Metasrv started");
790
791 Ok(())
792 }
793
794 pub async fn shutdown(&self) -> Result<()> {
795 if self
796 .started
797 .compare_exchange(true, false, Ordering::AcqRel, Ordering::Acquire)
798 .is_err()
799 {
800 warn!("Metasrv already stopped");
801 return Ok(());
802 }
803
804 self.procedure_manager
805 .stop()
806 .await
807 .context(StopProcedureManagerSnafu)?;
808
809 info!("Metasrv stopped");
810
811 Ok(())
812 }
813
814 pub fn start_time_ms(&self) -> u64 {
815 self.start_time_ms
816 }
817
818 pub fn resource_stat(&self) -> &ResourceStatRef {
819 &self.resource_stat
820 }
821
822 pub fn node_info(&self) -> MetasrvNodeInfo {
823 let build_info = common_version::build_info();
824 MetasrvNodeInfo {
825 addr: self.options().grpc.server_addr.clone(),
826 version: build_info.version.to_string(),
827 git_commit: build_info.commit_short.to_string(),
828 start_time_ms: self.start_time_ms(),
829 total_cpu_millicores: self.resource_stat.get_total_cpu_millicores(),
830 total_memory_bytes: self.resource_stat.get_total_memory_bytes(),
831 cpu_usage_millicores: self.resource_stat.get_cpu_usage_millicores(),
832 memory_usage_bytes: self.resource_stat.get_memory_usage_bytes(),
833 hostname: hostname::get()
834 .unwrap_or_default()
835 .to_string_lossy()
836 .to_string(),
837 }
838 }
839
840 pub(crate) async fn lookup_datanode_peer(&self, peer_id: u64) -> Result<Option<Peer>> {
843 discovery::utils::alive_datanode(
844 &DefaultSystemTimer,
845 self.meta_peer_client.as_ref(),
846 peer_id,
847 default_distributed_time_constants().datanode_lease,
848 )
849 .await
850 }
851
852 pub fn options(&self) -> &MetasrvOptions {
853 &self.options
854 }
855
856 pub fn in_memory(&self) -> &ResettableKvBackendRef {
857 &self.in_memory
858 }
859
860 pub fn kv_backend(&self) -> &KvBackendRef {
861 &self.kv_backend
862 }
863
864 pub fn meta_peer_client(&self) -> &MetaPeerClientRef {
869 &self.meta_peer_client
870 }
871
872 pub fn selector(&self) -> &SelectorRef {
873 &self.selector
874 }
875
876 pub fn selector_ctx(&self) -> &SelectorContext {
878 &self.selector_ctx
879 }
880
881 pub fn flow_selector(&self) -> &SelectorRef {
882 &self.flow_selector
883 }
884
885 pub fn handler_group(&self) -> Option<HeartbeatHandlerGroupRef> {
886 self.handler_group.read().unwrap().clone()
887 }
888
889 pub fn election(&self) -> Option<&ElectionRef> {
890 self.election.as_ref()
891 }
892
893 pub fn mailbox(&self) -> &MailboxRef {
894 &self.mailbox
895 }
896
897 pub fn ddl_manager(&self) -> &DdlManagerRef {
898 &self.ddl_manager
899 }
900
901 pub fn procedure_manager(&self) -> &ProcedureManagerRef {
902 &self.procedure_manager
903 }
904
905 pub fn table_metadata_manager(&self) -> &TableMetadataManagerRef {
906 &self.table_metadata_manager
907 }
908
909 pub fn runtime_switch_manager(&self) -> &RuntimeSwitchManagerRef {
910 &self.runtime_switch_manager
911 }
912
913 pub fn memory_region_keeper(&self) -> &MemoryRegionKeeperRef {
914 &self.memory_region_keeper
915 }
916
917 pub fn region_migration_manager(&self) -> &RegionMigrationManagerRef {
918 &self.region_migration_manager
919 }
920
921 pub fn drain_datanode_manager(&self) -> &DrainDatanodeManagerRef {
923 &self.drain_datanode_manager
924 }
925
926 pub fn publish(&self) -> Option<PublisherRef> {
927 self.plugins.get::<PublisherRef>()
928 }
929
930 pub fn subscription_manager(&self) -> Option<SubscriptionManagerRef> {
931 self.plugins.get::<SubscriptionManagerRef>()
932 }
933
934 pub fn table_id_allocator(&self) -> &ResourceIdAllocatorRef {
935 &self.table_id_allocator
936 }
937
938 pub fn reconciliation_manager(&self) -> &ReconciliationManagerRef {
939 &self.reconciliation_manager
940 }
941
942 pub fn database_operator(&self) -> &DatabaseOperatorRef {
943 &self.database_operator
944 }
945
946 pub fn node_scheduling_manager(&self) -> &NodeSchedulingManagerRef {
947 &self.node_scheduling_manager
948 }
949
950 pub fn plugins(&self) -> &Plugins {
951 &self.plugins
952 }
953
954 pub fn started(&self) -> Arc<AtomicBool> {
955 self.started.clone()
956 }
957
958 pub fn gc_ticker(&self) -> Option<GcTickerRef> {
959 self.gc_ticker.as_ref().cloned()
960 }
961
962 #[inline]
963 pub fn new_ctx(&self) -> Context {
964 let server_addr = self.options().grpc.server_addr.clone();
965 let in_memory = self.in_memory.clone();
966 let kv_backend = self.kv_backend.clone();
967 let leader_cached_kv_backend = self.leader_cached_kv_backend.clone();
968 let meta_peer_client = self.meta_peer_client.clone();
969 let mailbox = self.mailbox.clone();
970 let election = self.election.clone();
971 let table_metadata_manager = self.table_metadata_manager.clone();
972 let cache_invalidator = self.cache_invalidator.clone();
973 let leader_region_registry = self.leader_region_registry.clone();
974 let topic_stats_registry = self.topic_stats_registry.clone();
975
976 Context {
977 server_addr,
978 in_memory,
979 kv_backend,
980 leader_cached_kv_backend,
981 meta_peer_client,
982 mailbox,
983 election,
984 is_infancy: false,
985 table_metadata_manager,
986 cache_invalidator,
987 leader_region_registry,
988 topic_stats_registry,
989 heartbeat_interval: self.options().heartbeat_interval,
990 gc_enabled: self.options().gc.enable,
991 is_handshake: false,
992 }
993 }
994}
995
996#[cfg(test)]
997mod tests {
998 use common_event_recorder::EventTypeFilter;
999
1000 use super::*;
1001 use crate::metasrv::MetasrvNodeInfo;
1002
1003 #[test]
1004 fn test_deserialize_metasrv_node_info() {
1005 let str = r#"{"addr":"127.0.0.1:4002","version":"0.1.0","git_commit":"1234567890","start_time_ms":1715145600}"#;
1006 let node_info: MetasrvNodeInfo = serde_json::from_str(str).unwrap();
1007 assert_eq!(node_info.addr, "127.0.0.1:4002");
1008 assert_eq!(node_info.version, "0.1.0");
1009 assert_eq!(node_info.git_commit, "1234567890");
1010 assert_eq!(node_info.start_time_ms, 1715145600);
1011 }
1012
1013 #[test]
1014 fn test_metasrv_event_recorder_options_preserve_event_type_filter_semantics() {
1015 let all = MetasrvOptions::default().event_recorder;
1016 let none: EventRecorderOptions = toml::from_str("ttl = '90d'\nevent_types = []").unwrap();
1017 let selected: EventRecorderOptions =
1018 toml::from_str("ttl = '90d'\nevent_types = ['create_database']").unwrap();
1019
1020 assert!(all.event_types.allows("future_event"));
1021 assert_eq!(
1022 none.event_types.as_ref(),
1023 &EventTypeFilter::Only(Default::default())
1024 );
1025 assert!(selected.event_types.allows("create_database"));
1026 assert!(!selected.event_types.allows("drop_database"));
1027 }
1028}