Skip to main content

frontend/instance/
builder.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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
58/// The frontend [`Instance`] builder.
59pub 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        // Builds cache registry
109        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}