1use std::sync::Arc;
16use std::sync::atomic::AtomicBool;
17
18use cache::{PARTITION_INFO_CACHE_NAME, TABLE_FLOWNODE_SET_CACHE_NAME, TABLE_ROUTE_CACHE_NAME};
19use catalog::CatalogManagerRef;
20use catalog::process_manager::ProcessManagerRef;
21use common_base::Plugins;
22use common_datasource::object_store::LocalFileAccess;
23use common_event_recorder::EventRecorderImpl;
24use common_meta::cache::{LayeredCacheRegistryRef, TableRouteCacheRef};
25use common_meta::cache_invalidator::{CacheInvalidatorRef, DummyCacheInvalidator};
26use common_meta::key::TableMetadataManager;
27use common_meta::key::flow::FlowMetadataManager;
28use common_meta::kv_backend::KvBackendRef;
29use common_meta::node_manager::NodeManagerRef;
30use common_meta::procedure_executor::ProcedureExecutorRef;
31use dashmap::DashMap;
32use operator::delete::Deleter;
33use operator::flow::FlowServiceOperator;
34use operator::insert::Inserter;
35use operator::procedure::ProcedureServiceOperator;
36use operator::request::Requester;
37#[cfg(feature = "enterprise")]
38use operator::statement::CreateDatabaseHandlerRef;
39use operator::statement::{
40 ExecutorConfigureContext, StatementExecutor, StatementExecutorConfiguratorRef,
41 StatementExecutorRef,
42};
43use operator::table::TableMutationOperator;
44use partition::cache::PartitionInfoCacheRef;
45use partition::manager::PartitionRuleManager;
46use pipeline::pipeline_operator::PipelineOperator;
47use query::QueryEngineFactory;
48use query::region_query::RegionQueryHandlerFactoryRef;
49use snafu::{OptionExt, ResultExt};
50
51use crate::error::{self, DataFusionSnafu, ExternalSnafu, Result};
52use crate::events::EventHandlerImpl;
53use crate::frontend::FrontendOptions;
54use crate::heartbeat::frontend_peer_addr;
55use crate::instance::Instance;
56use crate::instance::region_query::FrontendRegionQueryHandler;
57
58pub struct FrontendBuilder {
60 options: FrontendOptions,
61 kv_backend: KvBackendRef,
62 layered_cache_registry: LayeredCacheRegistryRef,
63 local_cache_invalidator: Option<CacheInvalidatorRef>,
64 catalog_manager: CatalogManagerRef,
65 node_manager: NodeManagerRef,
66 plugins: Option<Plugins>,
67 procedure_executor: ProcedureExecutorRef,
68 process_manager: ProcessManagerRef,
69 local_file_access: LocalFileAccess,
70}
71
72impl FrontendBuilder {
73 #[allow(clippy::too_many_arguments)]
74 pub fn new(
75 options: FrontendOptions,
76 kv_backend: KvBackendRef,
77 layered_cache_registry: LayeredCacheRegistryRef,
78 catalog_manager: CatalogManagerRef,
79 node_manager: NodeManagerRef,
80 procedure_executor: ProcedureExecutorRef,
81 process_manager: ProcessManagerRef,
82 ) -> Self {
83 Self {
84 options,
85 kv_backend,
86 layered_cache_registry,
87 local_cache_invalidator: None,
88 catalog_manager,
89 node_manager,
90 plugins: None,
91 procedure_executor,
92 process_manager,
93 local_file_access: LocalFileAccess::Disabled,
94 }
95 }
96
97 #[cfg(test)]
98 pub(crate) fn new_test(
99 options: &FrontendOptions,
100 meta_client: meta_client::MetaClientRef,
101 ) -> Self {
102 use cache::{build_fundamental_cache_registry, with_default_composite_cache_registry};
103 use common_meta::cache::LayeredCacheRegistryBuilder;
104 use common_meta::kv_backend::memory::MemoryKvBackend;
105
106 let kv_backend = Arc::new(MemoryKvBackend::new());
107
108 let layered_cache_builder = LayeredCacheRegistryBuilder::default();
110 let fundamental_cache_registry = build_fundamental_cache_registry(kv_backend.clone());
111 let layered_cache_registry = Arc::new(
112 with_default_composite_cache_registry(
113 layered_cache_builder.add_cache_registry(fundamental_cache_registry),
114 )
115 .unwrap()
116 .build(),
117 );
118
119 Self::new(
120 options.clone(),
121 kv_backend,
122 layered_cache_registry,
123 catalog::memory::MemoryCatalogManager::with_default_setup(),
124 Arc::new(client::client_manager::NodeClients::default()),
125 meta_client,
126 Arc::new(catalog::process_manager::ProcessManager::new(
127 "".to_string(),
128 None,
129 )),
130 )
131 }
132
133 pub fn with_local_cache_invalidator(self, cache_invalidator: CacheInvalidatorRef) -> Self {
134 Self {
135 local_cache_invalidator: Some(cache_invalidator),
136 ..self
137 }
138 }
139
140 pub fn with_local_file_access(mut self, local_file_access: LocalFileAccess) -> Self {
141 self.local_file_access = local_file_access;
142 self
143 }
144
145 pub fn options(&self) -> &FrontendOptions {
146 &self.options
147 }
148
149 pub fn kv_backend(&self) -> &KvBackendRef {
150 &self.kv_backend
151 }
152
153 pub fn layered_cache_registry(&self) -> &LayeredCacheRegistryRef {
154 &self.layered_cache_registry
155 }
156
157 pub fn catalog_manager(&self) -> &CatalogManagerRef {
158 &self.catalog_manager
159 }
160
161 pub fn node_manager(&self) -> &NodeManagerRef {
162 &self.node_manager
163 }
164
165 pub fn procedure_executor(&self) -> &ProcedureExecutorRef {
166 &self.procedure_executor
167 }
168
169 pub fn process_manager(&self) -> &ProcessManagerRef {
170 &self.process_manager
171 }
172
173 pub fn with_plugin(self, plugins: Plugins) -> Self {
174 Self {
175 plugins: Some(plugins),
176 ..self
177 }
178 }
179
180 pub async fn try_build(self) -> Result<Instance> {
181 let kv_backend = self.kv_backend;
182 let node_manager = self.node_manager;
183 let plugins = self.plugins.unwrap_or_default();
184 let process_manager = self.process_manager;
185 let table_route_cache: TableRouteCacheRef =
186 self.layered_cache_registry
187 .get()
188 .context(error::CacheRequiredSnafu {
189 name: TABLE_ROUTE_CACHE_NAME,
190 })?;
191 let partition_info_cache: PartitionInfoCacheRef = self
192 .layered_cache_registry
193 .get()
194 .context(error::CacheRequiredSnafu {
195 name: PARTITION_INFO_CACHE_NAME,
196 })?;
197 let partition_manager = Arc::new(PartitionRuleManager::new(
198 kv_backend.clone(),
199 table_route_cache.clone(),
200 partition_info_cache.clone(),
201 ));
202
203 let local_cache_invalidator = self
204 .local_cache_invalidator
205 .unwrap_or_else(|| Arc::new(DummyCacheInvalidator));
206
207 let region_query_handler =
208 if let Some(factory) = plugins.get::<RegionQueryHandlerFactoryRef>() {
209 factory.build(partition_manager.clone(), node_manager.clone())
210 } else {
211 FrontendRegionQueryHandler::arc(partition_manager.clone(), node_manager.clone())
212 };
213
214 let table_flownode_cache =
215 self.layered_cache_registry
216 .get()
217 .context(error::CacheRequiredSnafu {
218 name: TABLE_FLOWNODE_SET_CACHE_NAME,
219 })?;
220
221 let inserter = Arc::new(Inserter::new(
222 self.catalog_manager.clone(),
223 partition_manager.clone(),
224 node_manager.clone(),
225 table_flownode_cache,
226 self.options.auto_create_table,
227 ));
228 let deleter = Arc::new(Deleter::new(
229 self.catalog_manager.clone(),
230 partition_manager.clone(),
231 node_manager.clone(),
232 ));
233 let requester = Arc::new(Requester::new(
234 self.catalog_manager.clone(),
235 partition_manager.clone(),
236 node_manager.clone(),
237 ));
238 let table_mutation_handler = Arc::new(TableMutationOperator::new(
239 inserter.clone(),
240 deleter.clone(),
241 requester,
242 ));
243
244 let table_metadata_manager = Arc::new(TableMetadataManager::new(kv_backend.clone()));
245 let procedure_service_handler = Arc::new(ProcedureServiceOperator::new(
246 self.procedure_executor.clone(),
247 self.catalog_manager.clone(),
248 table_metadata_manager.clone(),
249 ));
250
251 let flow_metadata_manager: Arc<FlowMetadataManager> =
252 Arc::new(FlowMetadataManager::new(kv_backend.clone()));
253 let flow_service = FlowServiceOperator::new(flow_metadata_manager, node_manager.clone());
254
255 let mut query_options = self.options.query.clone();
256 query_options.enable_per_region_metrics = self.options.logging.enable_per_region_metrics;
257 let query_engine = QueryEngineFactory::try_new_with_plugins(
258 self.catalog_manager.clone(),
259 Some(partition_manager.clone()),
260 Some(region_query_handler.clone()),
261 Some(table_mutation_handler),
262 Some(procedure_service_handler),
263 Some(Arc::new(flow_service)),
264 true,
265 plugins.clone(),
266 query_options,
267 )
268 .context(DataFusionSnafu)?
269 .query_engine();
270
271 let frontend_peer_addr = frontend_peer_addr(&self.options);
272 let statement_executor = StatementExecutor::new(
273 self.catalog_manager.clone(),
274 query_engine.clone(),
275 self.procedure_executor,
276 kv_backend.clone(),
277 local_cache_invalidator,
278 inserter.clone(),
279 partition_manager,
280 Some(process_manager.clone()),
281 frontend_peer_addr.clone(),
282 self.local_file_access,
283 );
284
285 let statement_executor =
286 if let Some(configurator) = plugins.get::<StatementExecutorConfiguratorRef>() {
287 let ctx = ExecutorConfigureContext {
288 kv_backend: kv_backend.clone(),
289 };
290 configurator
291 .configure(statement_executor, ctx)
292 .await
293 .context(ExternalSnafu)?
294 } else {
295 statement_executor
296 };
297
298 #[cfg(feature = "enterprise")]
299 let statement_executor = if let Some(handler) = plugins.get::<CreateDatabaseHandlerRef>() {
300 statement_executor.with_create_database_handler(handler)
301 } else {
302 statement_executor
303 };
304
305 let statement_executor = Arc::new(statement_executor);
306
307 let pipeline_operator = Arc::new(PipelineOperator::new(
308 inserter.clone(),
309 statement_executor.clone(),
310 self.catalog_manager.clone(),
311 query_engine.clone(),
312 ));
313
314 plugins.insert::<StatementExecutorRef>(statement_executor.clone());
315
316 let slow_query_recorder = Arc::new(EventRecorderImpl::new(Box::new(
317 EventHandlerImpl::new(statement_executor.clone(), self.options.slow_query.ttl),
318 )));
319 let event_recorder = Arc::new(EventRecorderImpl::with_event_type_filter(
320 Box::new(EventHandlerImpl::new(
321 statement_executor.clone(),
322 self.options.event_recorder.ttl,
323 )),
324 self.options.event_recorder.event_types.clone(),
325 ));
326
327 Ok(Instance {
328 frontend_peer_addr,
329 catalog_manager: self.catalog_manager,
330 pipeline_operator,
331 statement_executor,
332 query_engine,
333 plugins,
334 inserter,
335 deleter,
336 table_metadata_manager,
337 event_recorder,
338 slow_query_recorder,
339 process_manager,
340 otlp_metrics_table_legacy_cache: DashMap::new(),
341 slow_query_options: self.options.slow_query.clone(),
342 influxdb_default_merge_mode: self.options.influxdb.default_merge_mode,
343 trace_ingest_chunk_size: self.options.otlp.trace_ingest_chunk_size,
344 suspend: Arc::new(AtomicBool::new(false)),
345 })
346 }
347}