1use std::net::SocketAddr;
16use std::sync::Arc;
17
18use auth::UserProviderRef;
19use axum::extract::{Request, State};
20use axum::middleware::Next;
21use axum::response::IntoResponse;
22use common_base::Plugins;
23use common_config::Configurable;
24use common_telemetry::info;
25use meta_client::MetaClientOptions;
26use servers::error::Error as ServerError;
27use servers::grpc::builder::GrpcServerBuilder;
28use servers::grpc::flight::FlightCraftRef;
29use servers::grpc::frontend_grpc_handler::FrontendGrpcHandler;
30use servers::grpc::greptime_handler::GreptimeRequestHandler;
31use servers::grpc::{GrpcOptions, GrpcServer};
32use servers::http::event::LogValidatorRef;
33use servers::http::result::error_result::ErrorResponse;
34use servers::http::utils::router::RouterConfigurator;
35use servers::http::{HttpServer, HttpServerBuilder};
36use servers::interceptor::LogIngestInterceptorRef;
37use servers::metrics_handler::MetricsHandler;
38use servers::mysql::server::{MysqlServer, MysqlSpawnConfig, MysqlSpawnRef};
39use servers::otel_arrow::OtelArrowServiceHandler;
40use servers::pending_rows_batcher::PendingRowsBatcher;
41use servers::postgres::PostgresServer;
42use servers::request_memory_limiter::ServerMemoryLimiter;
43use servers::server::{Server, ServerHandlers};
44use servers::tls::{ReloadableTlsServerConfig, maybe_watch_server_tls_config};
45use snafu::ResultExt;
46use tonic::Status;
47
48use crate::error::{self, Result, StartServerSnafu, TomlFormatSnafu};
49use crate::frontend::FrontendOptions;
50use crate::instance::Instance;
51
52pub struct Services<T>
53where
54 T: Into<FrontendOptions> + Configurable + Clone,
55{
56 opts: T,
57 instance: Arc<Instance>,
58 grpc_server_builder: Option<GrpcServerBuilder>,
59 http_server_builder: Option<HttpServerBuilder>,
60 plugins: Plugins,
61 flight_handler: Option<FlightCraftRef>,
62 pub server_memory_limiter: ServerMemoryLimiter,
63}
64
65impl<T> Services<T>
66where
67 T: Into<FrontendOptions> + Configurable + Clone,
68{
69 pub fn new(opts: T, instance: Arc<Instance>, plugins: Plugins) -> Self {
70 let feopts = opts.clone().into();
71 let server_memory_limiter = ServerMemoryLimiter::new(
73 feopts.max_in_flight_write_bytes.as_bytes(),
74 feopts.write_bytes_exhausted_policy,
75 );
76
77 Self {
78 opts,
79 instance,
80 grpc_server_builder: None,
81 http_server_builder: None,
82 plugins,
83 flight_handler: None,
84 server_memory_limiter,
85 }
86 }
87
88 pub fn grpc_server_builder(
89 &self,
90 opts: &GrpcOptions,
91 request_memory_limiter: ServerMemoryLimiter,
92 ) -> Result<GrpcServerBuilder> {
93 let builder = GrpcServerBuilder::new(opts.as_config(), common_runtime::global_runtime())
94 .with_memory_limiter(request_memory_limiter)
95 .with_tls_config(opts.tls.clone())
96 .context(error::InvalidTlsConfigSnafu)?;
97 Ok(builder)
98 }
99
100 pub fn http_server_builder(
101 &self,
102 opts: &FrontendOptions,
103 request_memory_limiter: ServerMemoryLimiter,
104 ) -> HttpServerBuilder {
105 let mut builder = HttpServerBuilder::new(opts.http.clone())
106 .with_memory_limiter(request_memory_limiter)
107 .with_sql_handler(self.instance.clone());
108
109 let validator = self.plugins.get::<LogValidatorRef>();
110 let ingest_interceptor = self.plugins.get::<LogIngestInterceptorRef<ServerError>>();
111 builder =
112 builder.with_log_ingest_handler(self.instance.clone(), validator, ingest_interceptor);
113 builder = builder.with_logs_handler(self.instance.clone());
114
115 if let Some(user_provider) = self.plugins.get::<UserProviderRef>() {
116 builder = builder.with_user_provider(user_provider);
117 }
118
119 if opts.opentsdb.enable {
120 builder = builder.with_opentsdb_handler(self.instance.clone());
121 }
122
123 if opts.influxdb.enable {
124 builder = builder.with_influxdb_handler(self.instance.clone());
125 }
126
127 if opts.prom_store.enable {
128 let pending_rows_batcher = if opts.prom_store.with_metric_engine {
129 PendingRowsBatcher::try_new(
130 self.instance.partition_manager().clone(),
131 self.instance.node_manager().clone(),
132 self.instance.catalog_manager().clone(),
133 opts.prom_store.pending_rows_flush_interval,
134 opts.prom_store.max_batch_rows,
135 opts.prom_store.max_concurrent_flushes,
136 opts.prom_store.worker_channel_capacity,
137 opts.prom_store.max_inflight_requests,
138 )
139 } else {
140 None
141 };
142 builder = builder
143 .with_prom_handler(
144 self.instance.clone(),
145 Some(self.instance.clone()),
146 opts.prom_store.with_metric_engine,
147 opts.http.prom_validation_mode,
148 pending_rows_batcher,
149 )
150 .with_prometheus_handler(self.instance.clone());
151 }
152
153 if opts.otlp.enable {
154 builder = builder
155 .with_otlp_handler(self.instance.clone(), opts.prom_store.with_metric_engine);
156 }
157
158 if opts.jaeger.enable {
159 builder = builder.with_jaeger_handler(self.instance.clone());
160 }
161
162 builder = builder.with_dashboard_handler(self.instance.clone());
163
164 if let Some(configurator) = self.plugins.get::<RouterConfigurator>() {
165 info!("Adding extra router from plugins");
166 builder = builder.with_extra_router(configurator.router());
167 }
168
169 builder.add_layer(axum::middleware::from_fn_with_state(
170 self.instance.clone(),
171 async move |State(state): State<Arc<Instance>>, request: Request, next: Next| {
172 if state.is_suspended() {
173 return ErrorResponse::from_error(servers::error::SuspendedSnafu.build())
174 .into_response();
175 }
176 next.run(request).await
177 },
178 ))
179 }
180
181 pub fn with_grpc_server_builder(self, builder: GrpcServerBuilder) -> Self {
182 Self {
183 grpc_server_builder: Some(builder),
184 ..self
185 }
186 }
187
188 pub fn with_http_server_builder(self, builder: HttpServerBuilder) -> Self {
189 Self {
190 http_server_builder: Some(builder),
191 ..self
192 }
193 }
194
195 pub fn with_flight_handler(self, flight_handler: FlightCraftRef) -> Self {
196 Self {
197 flight_handler: Some(flight_handler),
198 ..self
199 }
200 }
201
202 fn build_grpc_server(
203 &mut self,
204 grpc: &GrpcOptions,
205 meta_client: &Option<MetaClientOptions>,
206 name: Option<String>,
207 external: bool,
208 request_memory_limiter: ServerMemoryLimiter,
209 ) -> Result<GrpcServer> {
210 let builder = if let Some(builder) = self.grpc_server_builder.take() {
211 builder
212 } else {
213 self.grpc_server_builder(grpc, request_memory_limiter)?
214 };
215
216 let user_provider = if external {
217 self.plugins.get::<UserProviderRef>()
218 } else {
219 None
221 };
222
223 let runtime = if meta_client.is_none() {
225 Some(builder.runtime().clone())
226 } else {
227 None
228 };
229
230 let greptime_request_handler = GreptimeRequestHandler::new(
231 self.instance.clone(),
232 user_provider.clone(),
233 runtime,
234 grpc.flight_compression,
235 );
236
237 let flight_handler = self
239 .flight_handler
240 .clone()
241 .unwrap_or_else(|| Arc::new(greptime_request_handler.clone()) as FlightCraftRef);
242
243 let grpc_server = builder
244 .name(name)
245 .database_handler(greptime_request_handler.clone())
246 .prometheus_handler(self.instance.clone(), user_provider.clone())
247 .otel_arrow_handler(OtelArrowServiceHandler::new(
248 self.instance.clone(),
249 user_provider.clone(),
250 ))
251 .flight_handler(flight_handler)
252 .add_layer(axum::middleware::from_fn_with_state(
253 self.instance.clone(),
254 async move |State(state): State<Arc<Instance>>, request: Request, next: Next| {
255 if state.is_suspended() {
256 let status = Status::from(servers::error::SuspendedSnafu.build());
257 return status.into_http();
258 }
259 next.run(request).await
260 },
261 ));
262
263 let grpc_server = if !external {
264 let frontend_grpc_handler =
265 FrontendGrpcHandler::new(self.instance.process_manager().clone());
266 grpc_server.frontend_grpc_handler(frontend_grpc_handler)
267 } else {
268 grpc_server
269 }
270 .build();
271
272 Ok(grpc_server)
273 }
274
275 fn build_http_server(
276 &mut self,
277 opts: &FrontendOptions,
278 toml: String,
279 request_memory_limiter: ServerMemoryLimiter,
280 ) -> Result<HttpServer> {
281 let builder = if let Some(builder) = self.http_server_builder.take() {
282 builder
283 } else {
284 self.http_server_builder(opts, request_memory_limiter)
285 };
286
287 let http_server = builder
288 .with_metrics_handler(MetricsHandler)
289 .with_plugins(self.plugins.clone())
290 .with_greptime_config_options(toml)
291 .build();
292 Ok(http_server)
293 }
294
295 pub fn build(mut self) -> Result<ServerHandlers> {
296 let opts = self.opts.clone();
297 let instance = self.instance.clone();
298
299 let toml = opts.to_toml().context(TomlFormatSnafu)?;
300 let opts: FrontendOptions = opts.into();
301
302 let handlers = ServerHandlers::default();
303
304 let user_provider = self.plugins.get::<UserProviderRef>();
305
306 {
307 let grpc_addr = parse_addr(&opts.grpc.bind_addr)?;
309 let grpc_server = self.build_grpc_server(
310 &opts.grpc,
311 &opts.meta_client,
312 None,
313 true,
314 self.server_memory_limiter.clone(),
315 )?;
316 handlers.insert((Box::new(grpc_server), grpc_addr));
317 }
318
319 if let Some(internal_grpc) = &opts.internal_grpc {
320 let grpc_addr = parse_addr(&internal_grpc.bind_addr)?;
322 let grpc_server = self.build_grpc_server(
323 internal_grpc,
324 &opts.meta_client,
325 Some("INTERNAL_GRPC_SERVER".to_string()),
326 false,
327 self.server_memory_limiter.clone(),
328 )?;
329 handlers.insert((Box::new(grpc_server), grpc_addr));
330 }
331
332 {
333 let http_options = &opts.http;
335 let http_addr = parse_addr(&http_options.addr)?;
336 let http_server =
337 self.build_http_server(&opts, toml, self.server_memory_limiter.clone())?;
338 handlers.insert((Box::new(http_server), http_addr));
339 }
340
341 if opts.mysql.enable {
342 let opts = &opts.mysql;
344 let mysql_addr = parse_addr(&opts.addr)?;
345
346 let tls_server_config = Arc::new(
347 ReloadableTlsServerConfig::try_new(opts.tls.clone()).context(StartServerSnafu)?,
348 );
349
350 maybe_watch_server_tls_config(tls_server_config.clone()).context(StartServerSnafu)?;
352
353 let mysql_server = MysqlServer::create_server(
354 common_runtime::global_runtime(),
355 Arc::new(MysqlSpawnRef::new(instance.clone(), user_provider.clone())),
356 Arc::new(MysqlSpawnConfig::new(
357 opts.tls.should_force_tls(),
358 tls_server_config,
359 opts.keep_alive.as_secs(),
360 opts.reject_no_database.unwrap_or(false),
361 opts.prepared_stmt_cache_size,
362 )),
363 Some(instance.process_manager().clone()),
364 );
365 handlers.insert((mysql_server, mysql_addr));
366 }
367
368 if opts.postgres.enable {
369 let opts = &opts.postgres;
371 let pg_addr = parse_addr(&opts.addr)?;
372
373 let tls_server_config = Arc::new(
374 ReloadableTlsServerConfig::try_new(opts.tls.clone()).context(StartServerSnafu)?,
375 );
376
377 maybe_watch_server_tls_config(tls_server_config.clone()).context(StartServerSnafu)?;
378
379 let pg_server = Box::new(PostgresServer::new(
380 instance.clone(),
381 opts.tls.should_force_tls(),
382 tls_server_config,
383 opts.keep_alive.as_secs(),
384 common_runtime::global_runtime(),
385 user_provider.clone(),
386 Some(self.instance.process_manager().clone()),
387 )) as Box<dyn Server>;
388
389 handlers.insert((pg_server, pg_addr));
390 }
391
392 Ok(handlers)
393 }
394}
395
396fn parse_addr(addr: &str) -> Result<SocketAddr> {
397 addr.parse().context(error::ParseAddrSnafu { addr })
398}