frontend/
frontend.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::sync::Arc;
16
17use common_base::readable_size::ReadableSize;
18use common_config::config::Configurable;
19use common_options::datanode::DatanodeClientOptions;
20use common_telemetry::logging::{LoggingOptions, SlowQueryOptions, TracingOptions};
21use meta_client::MetaClientOptions;
22use query::options::QueryOptions;
23use serde::{Deserialize, Serialize};
24use servers::export_metrics::{ExportMetricsOption, ExportMetricsTask};
25use servers::grpc::GrpcOptions;
26use servers::heartbeat_options::HeartbeatOptions;
27use servers::http::HttpOptions;
28use servers::server::ServerHandlers;
29use snafu::ResultExt;
30
31use crate::error;
32use crate::error::Result;
33use crate::heartbeat::HeartbeatTask;
34use crate::instance::prom_store::ExportMetricHandler;
35use crate::instance::Instance;
36use crate::service_config::{
37    InfluxdbOptions, JaegerOptions, MysqlOptions, OpentsdbOptions, OtlpOptions, PostgresOptions,
38    PromStoreOptions,
39};
40
41#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
42#[serde(default)]
43pub struct FrontendOptions {
44    pub node_id: Option<String>,
45    pub default_timezone: Option<String>,
46    pub heartbeat: HeartbeatOptions,
47    pub http: HttpOptions,
48    pub grpc: GrpcOptions,
49    pub mysql: MysqlOptions,
50    pub postgres: PostgresOptions,
51    pub opentsdb: OpentsdbOptions,
52    pub influxdb: InfluxdbOptions,
53    pub prom_store: PromStoreOptions,
54    pub jaeger: JaegerOptions,
55    pub otlp: OtlpOptions,
56    pub meta_client: Option<MetaClientOptions>,
57    pub logging: LoggingOptions,
58    pub datanode: DatanodeClientOptions,
59    pub user_provider: Option<String>,
60    pub export_metrics: ExportMetricsOption,
61    pub tracing: TracingOptions,
62    pub query: QueryOptions,
63    pub max_in_flight_write_bytes: Option<ReadableSize>,
64    pub slow_query: Option<SlowQueryOptions>,
65}
66
67impl Default for FrontendOptions {
68    fn default() -> Self {
69        Self {
70            node_id: None,
71            default_timezone: None,
72            heartbeat: HeartbeatOptions::frontend_default(),
73            http: HttpOptions::default(),
74            grpc: GrpcOptions::default(),
75            mysql: MysqlOptions::default(),
76            postgres: PostgresOptions::default(),
77            opentsdb: OpentsdbOptions::default(),
78            influxdb: InfluxdbOptions::default(),
79            jaeger: JaegerOptions::default(),
80            prom_store: PromStoreOptions::default(),
81            otlp: OtlpOptions::default(),
82            meta_client: None,
83            logging: LoggingOptions::default(),
84            datanode: DatanodeClientOptions::default(),
85            user_provider: None,
86            export_metrics: ExportMetricsOption::default(),
87            tracing: TracingOptions::default(),
88            query: QueryOptions::default(),
89            max_in_flight_write_bytes: None,
90            slow_query: Some(SlowQueryOptions::default()),
91        }
92    }
93}
94
95impl Configurable for FrontendOptions {
96    fn env_list_keys() -> Option<&'static [&'static str]> {
97        Some(&["meta_client.metasrv_addrs"])
98    }
99}
100
101/// The [`Frontend`] struct is the main entry point for the frontend service
102/// which contains server handlers, frontend instance and some background tasks.
103pub struct Frontend {
104    pub instance: Arc<Instance>,
105    pub servers: ServerHandlers,
106    pub heartbeat_task: Option<HeartbeatTask>,
107    pub export_metrics_task: Option<ExportMetricsTask>,
108}
109
110impl Frontend {
111    pub async fn start(&mut self) -> Result<()> {
112        if let Some(t) = &self.heartbeat_task {
113            t.start().await?;
114        }
115
116        if let Some(t) = self.export_metrics_task.as_ref() {
117            if t.send_by_handler {
118                let inserter = self.instance.inserter().clone();
119                let statement_executor = self.instance.statement_executor().clone();
120                let handler = ExportMetricHandler::new_handler(inserter, statement_executor);
121                t.start(Some(handler)).context(error::StartServerSnafu)?
122            } else {
123                t.start(None).context(error::StartServerSnafu)?;
124            }
125        }
126
127        self.servers
128            .start_all()
129            .await
130            .context(error::StartServerSnafu)
131    }
132
133    pub async fn shutdown(&mut self) -> Result<()> {
134        self.servers
135            .shutdown_all()
136            .await
137            .context(error::ShutdownServerSnafu)
138    }
139
140    pub fn server_handlers(&self) -> &ServerHandlers {
141        &self.servers
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn test_toml() {
151        let opts = FrontendOptions::default();
152        let toml_string = toml::to_string(&opts).unwrap();
153        let _parsed: FrontendOptions = toml::from_str(&toml_string).unwrap();
154    }
155}