1use std::sync::Arc;
16use std::sync::atomic::AtomicBool;
17
18use auth::PermissionCheckerRef;
19use cache::{PARTITION_INFO_CACHE_NAME, TABLE_FLOWNODE_SET_CACHE_NAME, TABLE_ROUTE_CACHE_NAME};
20use catalog::CatalogManagerRef;
21use catalog::kvbackend::KvBackendCatalogManager;
22use catalog::process_manager::ProcessManagerRef;
23use catalog::system_schema::semantic_graph::EntityGraphProviderRef;
24use common_base::Plugins;
25use common_batcher::request_limiter::RequestLimiter;
26use common_datasource::object_store::LocalFileAccess;
27use common_event_recorder::{EventRecorderImpl, EventRecorderRef};
28use common_meta::cache::{LayeredCacheRegistryRef, TableFlownodeSetCacheRef, TableRouteCacheRef};
29use common_meta::cache_invalidator::{CacheInvalidatorRef, DummyCacheInvalidator};
30use common_meta::key::TableMetadataManager;
31use common_meta::key::flow::FlowMetadataManager;
32use common_meta::kv_backend::KvBackendRef;
33use common_meta::node_manager::NodeManagerRef;
34use common_meta::procedure_executor::ProcedureExecutorRef;
35use dashmap::DashMap;
36use operator::batcher::PendingRowsBatcher;
37use operator::delete::Deleter;
38use operator::flow::FlowServiceOperator;
39use operator::insert::Inserter;
40use operator::procedure::ProcedureServiceOperator;
41use operator::request::Requester;
42#[cfg(feature = "enterprise")]
43use operator::statement::CreateDatabaseHandlerRef;
44use operator::statement::{
45 AdminEventRecorderHandle, AdminFunctionRecordingLayer, ExecutorConfigureContext,
46 StatementExecutor, StatementExecutorConfiguratorRef, StatementExecutorRef,
47};
48use operator::table::TableMutationOperator;
49use partition::cache::PartitionInfoCacheRef;
50use partition::manager::PartitionRuleManager;
51use pipeline::pipeline_operator::PipelineOperator;
52use query::QueryEngineFactory;
53use query::region_query::RegionQueryHandlerFactoryRef;
54use servers::batcher::table::TablePendingRowsBatcher;
55use servers::batcher::{BatchingProtocol, pending_rows_batch_sync_enabled};
56use snafu::{OptionExt, ResultExt};
57
58use crate::error::{self, DataFusionSnafu, ExternalSnafu, Result};
59use crate::events::EventHandlerImpl;
60use crate::frontend::FrontendOptions;
61use crate::heartbeat::frontend_peer_addr;
62use crate::instance::Instance;
63use crate::instance::entity_graph::EntityGraphProviderImpl;
64use crate::instance::otlp::TraceAuxCache;
65use crate::instance::region_query::FrontendRegionQueryHandler;
66use crate::service_config::BatcherOptions;
67
68pub struct FrontendBuilder {
70 options: FrontendOptions,
71 kv_backend: KvBackendRef,
72 layered_cache_registry: LayeredCacheRegistryRef,
73 local_cache_invalidator: Option<CacheInvalidatorRef>,
74 catalog_manager: CatalogManagerRef,
75 node_manager: NodeManagerRef,
76 plugins: Option<Plugins>,
77 procedure_executor: ProcedureExecutorRef,
78 process_manager: ProcessManagerRef,
79 local_file_access: LocalFileAccess,
80}
81
82impl FrontendBuilder {
83 #[allow(clippy::too_many_arguments)]
84 pub fn new(
85 options: FrontendOptions,
86 kv_backend: KvBackendRef,
87 layered_cache_registry: LayeredCacheRegistryRef,
88 catalog_manager: CatalogManagerRef,
89 node_manager: NodeManagerRef,
90 procedure_executor: ProcedureExecutorRef,
91 process_manager: ProcessManagerRef,
92 ) -> Self {
93 Self {
94 options,
95 kv_backend,
96 layered_cache_registry,
97 local_cache_invalidator: None,
98 catalog_manager,
99 node_manager,
100 plugins: None,
101 procedure_executor,
102 process_manager,
103 local_file_access: LocalFileAccess::Disabled,
104 }
105 }
106
107 #[cfg(test)]
108 pub(crate) fn new_test(
109 options: &FrontendOptions,
110 meta_client: meta_client::MetaClientRef,
111 ) -> Self {
112 use cache::{build_fundamental_cache_registry, with_default_composite_cache_registry};
113 use common_meta::cache::LayeredCacheRegistryBuilder;
114 use common_meta::kv_backend::memory::MemoryKvBackend;
115
116 let kv_backend = Arc::new(MemoryKvBackend::new());
117
118 let layered_cache_builder = LayeredCacheRegistryBuilder::default();
120 let fundamental_cache_registry = build_fundamental_cache_registry(kv_backend.clone());
121 let layered_cache_registry = Arc::new(
122 with_default_composite_cache_registry(
123 layered_cache_builder.add_cache_registry(fundamental_cache_registry),
124 )
125 .unwrap()
126 .build(),
127 );
128
129 Self::new(
130 options.clone(),
131 kv_backend,
132 layered_cache_registry,
133 catalog::memory::MemoryCatalogManager::with_default_setup(),
134 Arc::new(client::client_manager::NodeClients::default()),
135 meta_client,
136 Arc::new(catalog::process_manager::ProcessManager::new(
137 "".to_string(),
138 None,
139 )),
140 )
141 }
142
143 pub fn with_local_cache_invalidator(self, cache_invalidator: CacheInvalidatorRef) -> Self {
144 Self {
145 local_cache_invalidator: Some(cache_invalidator),
146 ..self
147 }
148 }
149
150 pub fn with_local_file_access(mut self, local_file_access: LocalFileAccess) -> Self {
151 self.local_file_access = local_file_access;
152 self
153 }
154
155 pub fn options(&self) -> &FrontendOptions {
156 &self.options
157 }
158
159 pub fn kv_backend(&self) -> &KvBackendRef {
160 &self.kv_backend
161 }
162
163 pub fn layered_cache_registry(&self) -> &LayeredCacheRegistryRef {
164 &self.layered_cache_registry
165 }
166
167 pub fn catalog_manager(&self) -> &CatalogManagerRef {
168 &self.catalog_manager
169 }
170
171 pub fn node_manager(&self) -> &NodeManagerRef {
172 &self.node_manager
173 }
174
175 pub fn procedure_executor(&self) -> &ProcedureExecutorRef {
176 &self.procedure_executor
177 }
178
179 pub fn process_manager(&self) -> &ProcessManagerRef {
180 &self.process_manager
181 }
182
183 pub fn with_plugin(self, plugins: Plugins) -> Self {
184 Self {
185 plugins: Some(plugins),
186 ..self
187 }
188 }
189
190 pub async fn try_build(self) -> Result<Instance> {
191 let kv_backend = self.kv_backend;
192 let node_manager = self.node_manager;
193 let plugins = self.plugins.unwrap_or_default();
194 let process_manager = self.process_manager;
195 let table_route_cache: TableRouteCacheRef =
196 self.layered_cache_registry
197 .get()
198 .context(error::CacheRequiredSnafu {
199 name: TABLE_ROUTE_CACHE_NAME,
200 })?;
201 let partition_info_cache: PartitionInfoCacheRef = self
202 .layered_cache_registry
203 .get()
204 .context(error::CacheRequiredSnafu {
205 name: PARTITION_INFO_CACHE_NAME,
206 })?;
207 let partition_manager = Arc::new(PartitionRuleManager::new(
208 kv_backend.clone(),
209 table_route_cache.clone(),
210 partition_info_cache.clone(),
211 ));
212
213 let local_cache_invalidator = self
214 .local_cache_invalidator
215 .unwrap_or_else(|| Arc::new(DummyCacheInvalidator));
216
217 let region_query_handler =
218 if let Some(factory) = plugins.get::<RegionQueryHandlerFactoryRef>() {
219 factory.build(partition_manager.clone(), node_manager.clone())
220 } else {
221 FrontendRegionQueryHandler::arc(partition_manager.clone(), node_manager.clone())
222 };
223
224 let table_flownode_cache: TableFlownodeSetCacheRef = self
225 .layered_cache_registry
226 .get()
227 .context(error::CacheRequiredSnafu {
228 name: TABLE_FLOWNODE_SET_CACHE_NAME,
229 })?;
230
231 let create_inserter = || {
232 Inserter::new(
233 self.catalog_manager.clone(),
234 partition_manager.clone(),
235 node_manager.clone(),
236 table_flownode_cache.clone(),
237 self.options.auto_create_table,
238 )
239 };
240 let bulk_inserter = Arc::new(create_inserter());
242 let build_batcher = |options: &BatcherOptions| -> Option<Arc<dyn PendingRowsBatcher>> {
243 if !options.pending_rows_batching_enabled()
244 || (self.options.prom_store.with_metric_engine
245 && options
246 .protocols
247 .iter()
248 .all(|protocol| *protocol == BatchingProtocol::Prom))
249 {
250 return None;
251 }
252 TablePendingRowsBatcher::try_new(
253 options.pending_rows_flush_interval,
254 options.max_batch_rows,
255 options.max_concurrent_flushes,
256 options.worker_channel_capacity,
257 options.max_inflight_requests,
258 options.flow_notification_queue_capacity,
259 bulk_inserter.clone(),
260 )
261 .map(|batcher| batcher as Arc<dyn PendingRowsBatcher>)
262 };
263 let inserter = Arc::new(
264 create_inserter()
265 .with_pending_rows_batcher(build_batcher(self.options.table_batcher_options())),
266 );
267 let deleter = Arc::new(Deleter::new(
268 self.catalog_manager.clone(),
269 partition_manager.clone(),
270 node_manager.clone(),
271 ));
272 let requester = Arc::new(Requester::new(
273 self.catalog_manager.clone(),
274 partition_manager.clone(),
275 node_manager.clone(),
276 ));
277 let table_mutation_handler = Arc::new(TableMutationOperator::new(
278 inserter.clone(),
279 deleter.clone(),
280 requester,
281 ));
282
283 let table_metadata_manager = Arc::new(TableMetadataManager::new(kv_backend.clone()));
284 let procedure_service_handler = Arc::new(ProcedureServiceOperator::new(
285 self.procedure_executor.clone(),
286 self.catalog_manager.clone(),
287 table_metadata_manager.clone(),
288 ));
289
290 let flow_metadata_manager: Arc<FlowMetadataManager> =
291 Arc::new(FlowMetadataManager::new(kv_backend.clone()));
292 let flow_service = FlowServiceOperator::new(flow_metadata_manager, node_manager.clone());
293
294 let mut query_options = self.options.query.clone();
295 query_options.enable_per_region_metrics = self.options.logging.enable_per_region_metrics;
296 let query_engine = QueryEngineFactory::try_new_with_plugins(
297 self.catalog_manager.clone(),
298 Some(partition_manager.clone()),
299 Some(region_query_handler.clone()),
300 Some(table_mutation_handler),
301 Some(procedure_service_handler),
302 Some(Arc::new(flow_service)),
303 true,
304 plugins.clone(),
305 query_options,
306 )
307 .context(DataFusionSnafu)?
308 .query_engine();
309
310 if let Some(kv_catalog) = self
315 .catalog_manager
316 .as_any()
317 .downcast_ref::<KvBackendCatalogManager>()
318 {
319 let provider: EntityGraphProviderRef = Arc::new(EntityGraphProviderImpl::new(
320 query_engine.clone(),
321 Arc::downgrade(&self.catalog_manager),
322 plugins.get::<PermissionCheckerRef>(),
323 ));
324 kv_catalog.set_entity_graph_provider(provider);
325 }
326
327 let frontend_peer_addr = frontend_peer_addr(&self.options);
328 let statement_executor = StatementExecutor::new(
329 self.catalog_manager.clone(),
330 query_engine.clone(),
331 self.procedure_executor,
332 kv_backend.clone(),
333 local_cache_invalidator,
334 inserter.clone(),
335 partition_manager,
336 Some(process_manager.clone()),
337 frontend_peer_addr.clone(),
338 self.local_file_access,
339 );
340
341 let statement_executor =
342 if let Some(configurator) = plugins.get::<StatementExecutorConfiguratorRef>() {
343 let ctx = ExecutorConfigureContext {
344 kv_backend: kv_backend.clone(),
345 };
346 configurator
347 .configure(statement_executor, ctx)
348 .await
349 .context(ExternalSnafu)?
350 } else {
351 statement_executor
352 };
353
354 #[cfg(feature = "enterprise")]
355 let statement_executor = if let Some(handler) = plugins.get::<CreateDatabaseHandlerRef>() {
356 statement_executor.with_create_database_handler(handler)
357 } else {
358 statement_executor
359 };
360
361 let admin_event_recorder = AdminEventRecorderHandle::default();
362 let statement_executor = statement_executor.with_admin_function_layer(Arc::new(
363 AdminFunctionRecordingLayer::new(admin_event_recorder.clone()),
364 ));
365 let statement_executor = Arc::new(statement_executor);
366
367 let pipeline_operator = Arc::new(PipelineOperator::new(
368 inserter.clone(),
369 statement_executor.clone(),
370 self.catalog_manager.clone(),
371 query_engine.clone(),
372 &self.options.pipeline,
373 ));
374
375 plugins.insert::<StatementExecutorRef>(statement_executor.clone());
376
377 let slow_query_recorder = Arc::new(EventRecorderImpl::new(Box::new(
378 EventHandlerImpl::new(statement_executor.clone(), self.options.slow_query.ttl),
379 )));
380 let event_recorder: EventRecorderRef = Arc::new(EventRecorderImpl::with_event_type_filter(
381 Box::new(EventHandlerImpl::new(
382 statement_executor.clone(),
383 self.options.event_recorder.ttl,
384 )),
385 self.options.event_recorder.event_types.clone(),
386 self.options.event_recorder.flush_interval,
387 ));
388 admin_event_recorder.install(&event_recorder);
389
390 let batcher_options = self.options.table_batcher_options();
391 let trace_aux_limiter = if batcher_options.pending_rows_batching_enabled()
392 && !pending_rows_batch_sync_enabled()
393 {
394 RequestLimiter::try_new(batcher_options.max_inflight_requests)
395 } else {
396 None
397 };
398
399 Ok(Instance {
400 logical_batcher: Default::default(),
401 frontend_peer_addr,
402 experimental_metric_export: self.options.experimental_metric_export,
403 catalog_manager: self.catalog_manager,
404 pipeline_operator,
405 statement_executor,
406 query_engine,
407 plugins,
408 inserter,
409 deleter,
410 table_metadata_manager,
411 event_recorder,
412 slow_query_recorder,
413 process_manager,
414 otlp_metrics_table_legacy_cache: Arc::new(DashMap::new()),
415 slow_query_options: self.options.slow_query.clone(),
416 influxdb_default_merge_mode: self.options.influxdb.default_merge_mode,
417 trace_ingest_chunk_size: self.options.otlp.trace_ingest_chunk_size,
418 trace_aux_cache: TraceAuxCache::new(self.options.otlp.trace_aux_cache_size.as_bytes()),
419 trace_aux_limiter,
420 otlp_resource_info: self.options.otlp.experimental_enable_resource_info,
421 suspend: Arc::new(AtomicBool::new(false)),
422 })
423 }
424}