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