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