Skip to main content

tests_integration/
standalone.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::time::Duration;
17
18use cache::{
19    build_datanode_layered_cache_registry, build_fundamental_cache_registry,
20    with_default_composite_cache_registry,
21};
22use catalog::information_schema::NoopInformationExtension;
23use catalog::kvbackend::KvBackendCatalogManagerBuilder;
24use catalog::process_manager::ProcessManager;
25use common_base::Plugins;
26use common_catalog::consts::{MIN_USER_FLOW_ID, MIN_USER_TABLE_ID};
27use common_config::KvBackendConfig;
28use common_datasource::object_store::LocalFileAccess;
29use common_event_recorder::EventRecorderOptions;
30use common_meta::cache::LayeredCacheRegistryBuilder;
31use common_meta::ddl::flow_meta::FlowMetadataAllocator;
32use common_meta::ddl::table_meta::TableMetadataAllocator;
33use common_meta::ddl::{DdlContext, NoopRegionFailureDetectorControl};
34use common_meta::ddl_manager::DdlManager;
35use common_meta::key::TableMetadataManager;
36use common_meta::key::flow::FlowMetadataManager;
37use common_meta::kv_backend::KvBackendRef;
38use common_meta::procedure_executor::LocalProcedureExecutor;
39use common_meta::region_keeper::MemoryRegionKeeper;
40use common_meta::region_registry::LeaderRegionRegistry;
41use common_meta::sequence::SequenceBuilder;
42use common_procedure::ProcedureManagerRef;
43use common_procedure::local::EventRecorderHandle;
44use common_procedure::options::ProcedureConfig;
45use common_telemetry::logging::SlowQueryOptions;
46use common_test_util::find_workspace_path;
47use common_wal::config::DatanodeWalConfig;
48use datanode::datanode::{Datanode, DatanodeBuilder};
49use flow::{FlownodeBuilder, FrontendClient, GrpcQueryHandlerWithBoxedError};
50use frontend::frontend::Frontend;
51use frontend::instance::Instance;
52use frontend::instance::builder::FrontendBuilder;
53use frontend::server::Services;
54use frontend::service_config::{BatcherOptions, PendingRowsBatcherOptions};
55use meta_srv::metasrv::{FLOW_ID_SEQ, TABLE_ID_SEQ};
56use servers::grpc::GrpcOptions;
57use standalone::options::StandaloneOptions;
58use standalone::{StandaloneDatanodeManager, StandaloneRepartitionProcedureFactory};
59
60use crate::test_util::{self, StorageType, TestGuard, create_tmp_dir_and_datanode_opts};
61
62pub struct GreptimeDbStandalone {
63    /// Storage engine for assertions across protocol and storage boundaries.
64    pub mito_engine: mito2::engine::MitoEngine,
65    /// Owns the region server and the log store, so a test can shut them down.
66    pub datanode: Datanode,
67    pub frontend: Arc<Frontend>,
68    pub opts: StandaloneOptions,
69    pub guard: TestGuard,
70    // Used in rebuild.
71    pub kv_backend: KvBackendRef,
72    pub procedure_manager: ProcedureManagerRef,
73    pub event_recorder_handle: EventRecorderHandle,
74}
75
76impl GreptimeDbStandalone {
77    pub fn fe_instance(&self) -> &Arc<Instance> {
78        &self.frontend.instance
79    }
80}
81
82pub struct GreptimeDbStandaloneBuilder {
83    instance_name: String,
84    datanode_wal_config: DatanodeWalConfig,
85    store_providers: Option<Vec<StorageType>>,
86    default_store: Option<StorageType>,
87    plugin: Option<Plugins>,
88    slow_query_options: SlowQueryOptions,
89    event_recorder_options: EventRecorderOptions,
90    auto_create_table: bool,
91    logical_batcher: Option<BatcherOptions>,
92    table_batcher: BatcherOptions,
93    mito_config: Option<mito2::config::MitoConfig>,
94}
95
96impl GreptimeDbStandaloneBuilder {
97    pub fn new(instance_name: &str) -> Self {
98        Self {
99            instance_name: instance_name.to_string(),
100            store_providers: None,
101            plugin: None,
102            default_store: None,
103            datanode_wal_config: DatanodeWalConfig::default(),
104            // Enable slow query log with 1s threshold by default for integration tests.
105            slow_query_options: SlowQueryOptions {
106                enable: true,
107                threshold: Duration::from_secs(1),
108                ..Default::default()
109            },
110            event_recorder_options: EventRecorderOptions::default(),
111            auto_create_table: true,
112            logical_batcher: None,
113            table_batcher: BatcherOptions::default(),
114            mito_config: None,
115        }
116    }
117
118    /// Overrides the Mito configuration for this test instance.
119    #[must_use]
120    pub fn with_mito_config(mut self, config: mito2::config::MitoConfig) -> Self {
121        self.mito_config = Some(config);
122        self
123    }
124
125    /// Configures ordinary-table batching for protocol integration tests.
126    #[must_use]
127    pub fn with_table_batcher(mut self, options: BatcherOptions) -> Self {
128        self.table_batcher = options;
129        self
130    }
131
132    /// Configures logical-table batching for integration tests.
133    #[must_use]
134    pub fn with_logical_batcher(mut self, options: BatcherOptions) -> Self {
135        self.logical_batcher = Some(options);
136        self
137    }
138
139    #[must_use]
140    pub fn with_auto_create_table(mut self, auto_create_table: bool) -> Self {
141        self.auto_create_table = auto_create_table;
142        self
143    }
144
145    /// Sets the event recorder options for the standalone instance.
146    #[must_use]
147    pub fn with_event_recorder_options(
148        mut self,
149        event_recorder_options: EventRecorderOptions,
150    ) -> Self {
151        self.event_recorder_options = event_recorder_options;
152        self
153    }
154
155    #[must_use]
156    pub fn with_default_store_type(self, store_type: StorageType) -> Self {
157        Self {
158            default_store: Some(store_type),
159            ..self
160        }
161    }
162
163    #[cfg(test)]
164    #[must_use]
165    pub fn with_store_providers(self, store_providers: Vec<StorageType>) -> Self {
166        Self {
167            store_providers: Some(store_providers),
168            ..self
169        }
170    }
171
172    #[must_use]
173    pub fn with_plugin(self, plugin: Plugins) -> Self {
174        Self {
175            plugin: Some(plugin),
176            ..self
177        }
178    }
179
180    #[must_use]
181    pub fn with_slow_query_threshold(mut self, threshold: Duration) -> Self {
182        self.slow_query_options.threshold = threshold;
183        self
184    }
185
186    #[must_use]
187    pub fn with_datanode_wal_config(mut self, datanode_wal_config: DatanodeWalConfig) -> Self {
188        self.datanode_wal_config = datanode_wal_config;
189        self
190    }
191
192    pub async fn build_with(
193        &self,
194        kv_backend: KvBackendRef,
195        guard: TestGuard,
196        opts: StandaloneOptions,
197        procedure_manager: ProcedureManagerRef,
198        event_recorder_handle: EventRecorderHandle,
199        register_procedure_loaders: bool,
200    ) -> GreptimeDbStandalone {
201        let plugins = self.plugin.clone().unwrap_or_default();
202
203        let layered_cache_registry =
204            Arc::new(build_datanode_layered_cache_registry(kv_backend.clone()));
205
206        let mut builder =
207            DatanodeBuilder::new(opts.datanode_options(), plugins.clone(), kv_backend.clone());
208        let local_file_access = LocalFileAccess::sandboxed(find_workspace_path(".")).unwrap();
209        builder.with_cache_registry(layered_cache_registry);
210        builder.with_local_file_access(local_file_access.clone());
211        let datanode = builder.build().await.unwrap();
212
213        let table_metadata_manager = Arc::new(TableMetadataManager::new(kv_backend.clone()));
214        table_metadata_manager.init().await.unwrap();
215
216        let flow_metadata_manager = Arc::new(FlowMetadataManager::new(kv_backend.clone()));
217
218        let layered_cache_builder = LayeredCacheRegistryBuilder::default();
219        let fundamental_cache_registry = build_fundamental_cache_registry(kv_backend.clone());
220        let cache_registry = Arc::new(
221            with_default_composite_cache_registry(
222                layered_cache_builder.add_cache_registry(fundamental_cache_registry),
223            )
224            .unwrap()
225            .build(),
226        );
227
228        let catalog_manager = KvBackendCatalogManagerBuilder::new(
229            Arc::new(NoopInformationExtension),
230            kv_backend.clone(),
231            cache_registry.clone(),
232        )
233        .with_procedure_manager(procedure_manager.clone())
234        .build();
235
236        let (frontend_client, frontend_instance_handler) =
237            FrontendClient::from_empty_grpc_handler(opts.query.clone());
238        let flow_builder = FlownodeBuilder::new(
239            Default::default(),
240            plugins.clone(),
241            table_metadata_manager.clone(),
242            catalog_manager.clone(),
243            flow_metadata_manager.clone(),
244            Arc::new(frontend_client),
245        );
246        let flownode = Arc::new(flow_builder.build().await.unwrap());
247
248        let node_manager = Arc::new(StandaloneDatanodeManager {
249            region_server: datanode.region_server(),
250            flow_server: flownode.flow_engine(),
251        });
252
253        let table_id_allocator = Arc::new(
254            SequenceBuilder::new(TABLE_ID_SEQ, kv_backend.clone())
255                .initial(MIN_USER_TABLE_ID as u64)
256                .step(10)
257                .build(),
258        );
259        let flow_id_sequence = Arc::new(
260            SequenceBuilder::new(FLOW_ID_SEQ, kv_backend.clone())
261                .initial(MIN_USER_FLOW_ID as u64)
262                .step(10)
263                .build(),
264        );
265        let wal_provider = cmd::standalone::build_standalone_wal_provider(
266            &opts.wal,
267            opts.datanode_options().node_id,
268            kv_backend.clone(),
269        )
270        .await
271        .unwrap();
272        let wal_provider = Arc::new(wal_provider);
273        let table_metadata_allocator = Arc::new(TableMetadataAllocator::new(
274            table_id_allocator,
275            wal_provider.clone(),
276        ));
277        let flow_metadata_allocator = Arc::new(FlowMetadataAllocator::with_noop_peer_allocator(
278            flow_id_sequence,
279        ));
280
281        let repartition_procedure_factory = Arc::new(StandaloneRepartitionProcedureFactory);
282        let ddl_manager = Arc::new(DdlManager::new(
283            DdlContext {
284                node_manager: node_manager.clone(),
285                cache_invalidator: cache_registry.clone(),
286                memory_region_keeper: Arc::new(MemoryRegionKeeper::default()),
287                leader_region_registry: Arc::new(LeaderRegionRegistry::default()),
288                table_metadata_manager,
289                table_metadata_allocator,
290                flow_metadata_manager,
291                flow_metadata_allocator,
292                region_failure_detector_controller: Arc::new(NoopRegionFailureDetectorControl),
293                soft_drop_enabled: false,
294                soft_drop_retention: None,
295                create_database_metadata_committer: None,
296            },
297            procedure_manager.clone(),
298            repartition_procedure_factory,
299        ));
300        if register_procedure_loaders {
301            ddl_manager.register_loaders().unwrap();
302        }
303        let procedure_executor = Arc::new(LocalProcedureExecutor::new(
304            ddl_manager,
305            procedure_manager.clone(),
306        ));
307
308        let server_addr = opts.frontend_options().grpc.server_addr.clone();
309
310        let instance = FrontendBuilder::new(
311            opts.frontend_options(),
312            kv_backend.clone(),
313            cache_registry.clone(),
314            catalog_manager.clone(),
315            node_manager.clone(),
316            procedure_executor.clone(),
317            Arc::new(ProcessManager::new(server_addr, None)),
318        )
319        .with_local_file_access(local_file_access)
320        .with_plugin(plugins.clone())
321        .try_build()
322        .await
323        .unwrap();
324        let instance = Arc::new(instance);
325
326        event_recorder_handle.install(instance.event_recorder());
327
328        // set the frontend client for flownode
329        let grpc_handler = instance.clone() as Arc<dyn GrpcQueryHandlerWithBoxedError>;
330        let weak_grpc_handler = Arc::downgrade(&grpc_handler);
331        frontend_instance_handler
332            .set_handler(weak_grpc_handler)
333            .await;
334        procedure_manager.start().await.unwrap();
335        wal_provider.start().await.unwrap();
336
337        test_util::prepare_another_catalog_and_schema(&instance).await;
338
339        let servers = Services::new(opts.clone(), instance.clone(), plugins)
340            .build()
341            .unwrap();
342        let frontend = Frontend {
343            instance,
344            servers,
345            heartbeat_task: None,
346        };
347
348        GreptimeDbStandalone {
349            mito_engine: datanode.region_server().mito_engine().unwrap(),
350            datanode,
351            frontend: Arc::new(frontend),
352            opts,
353            guard,
354            kv_backend,
355            procedure_manager,
356            event_recorder_handle,
357        }
358    }
359
360    pub async fn build(&self) -> GreptimeDbStandalone {
361        let default_store_type = self.default_store.unwrap_or(StorageType::File);
362        let store_types = self.store_providers.clone().unwrap_or_default();
363
364        let (opts, guard) = create_tmp_dir_and_datanode_opts(
365            default_store_type,
366            store_types,
367            &self.instance_name,
368            self.datanode_wal_config.clone(),
369            Default::default(),
370        );
371
372        let kv_backend_config = KvBackendConfig::default();
373        let procedure_config = ProcedureConfig::default();
374
375        let kv_backend = standalone::build_metadata_kvbackend(
376            format!("{}/kv", opts.storage.data_home),
377            kv_backend_config,
378        )
379        .unwrap();
380        let (procedure_manager, event_recorder_handle) =
381            standalone::build_procedure_manager(kv_backend.clone(), procedure_config);
382
383        let mut standalone_opts = StandaloneOptions {
384            storage: opts.storage,
385            procedure: procedure_config,
386            metadata_store: kv_backend_config,
387            wal: opts.wal,
388            grpc: GrpcOptions::default().with_server_addr("127.0.0.1:4001"),
389            slow_query: self.slow_query_options.clone(),
390            event_recorder: self.event_recorder_options.clone(),
391            auto_create_table: self.auto_create_table,
392            pending_rows_batcher: PendingRowsBatcherOptions {
393                logical_table: self.logical_batcher.clone(),
394                table: self.table_batcher.clone(),
395            },
396            // Tests cover the descriptor, so they run with it enabled.
397            otlp: frontend::service_config::OtlpOptions {
398                experimental_enable_resource_info: true,
399                ..Default::default()
400            },
401            ..StandaloneOptions::default()
402        };
403
404        if let Some(config) = &self.mito_config {
405            for engine in &mut standalone_opts.region_engine {
406                if let datanode::config::RegionEngineConfig::Mito(mito) = engine {
407                    *mito = config.clone();
408                }
409            }
410        }
411
412        self.build_with(
413            kv_backend,
414            guard,
415            standalone_opts,
416            procedure_manager,
417            event_recorder_handle,
418            true,
419        )
420        .await
421    }
422}