1use std::sync::Arc;
16use std::time::Duration;
17
18use cache::{
19 build_datanode_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 cmd::error::StartFlownodeSnafu;
26use common_base::Plugins;
27use common_catalog::consts::{MIN_USER_FLOW_ID, MIN_USER_TABLE_ID};
28use common_config::KvBackendConfig;
29use common_meta::cache::LayeredCacheRegistryBuilder;
30use common_meta::ddl::flow_meta::FlowMetadataAllocator;
31use common_meta::ddl::table_meta::TableMetadataAllocator;
32use common_meta::ddl::{DdlContext, NoopRegionFailureDetectorControl};
33use common_meta::ddl_manager::DdlManager;
34use common_meta::key::TableMetadataManager;
35use common_meta::key::flow::FlowMetadataManager;
36use common_meta::kv_backend::KvBackendRef;
37use common_meta::procedure_executor::LocalProcedureExecutor;
38use common_meta::region_keeper::MemoryRegionKeeper;
39use common_meta::region_registry::LeaderRegionRegistry;
40use common_meta::sequence::SequenceBuilder;
41use common_meta::wal_provider::build_wal_provider;
42use common_procedure::ProcedureManagerRef;
43use common_procedure::options::ProcedureConfig;
44use common_telemetry::logging::SlowQueryOptions;
45use common_wal::config::{DatanodeWalConfig, MetasrvWalConfig};
46use datanode::datanode::DatanodeBuilder;
47use flow::{FlownodeBuilder, FrontendClient, GrpcQueryHandlerWithBoxedError};
48use frontend::frontend::Frontend;
49use frontend::instance::builder::FrontendBuilder;
50use frontend::instance::{Instance, StandaloneDatanodeManager};
51use frontend::server::Services;
52use meta_srv::metasrv::{FLOW_ID_SEQ, TABLE_ID_SEQ};
53use servers::grpc::GrpcOptions;
54use snafu::ResultExt;
55use standalone::StandaloneRepartitionProcedureFactory;
56use standalone::options::StandaloneOptions;
57
58use crate::test_util::{self, StorageType, TestGuard, create_tmp_dir_and_datanode_opts};
59
60pub struct GreptimeDbStandalone {
61 pub frontend: Arc<Frontend>,
62 pub opts: StandaloneOptions,
63 pub guard: TestGuard,
64 pub kv_backend: KvBackendRef,
66 pub procedure_manager: ProcedureManagerRef,
67}
68
69impl GreptimeDbStandalone {
70 pub fn fe_instance(&self) -> &Arc<Instance> {
71 &self.frontend.instance
72 }
73}
74
75pub struct GreptimeDbStandaloneBuilder {
76 instance_name: String,
77 datanode_wal_config: DatanodeWalConfig,
78 metasrv_wal_config: MetasrvWalConfig,
79 store_providers: Option<Vec<StorageType>>,
80 default_store: Option<StorageType>,
81 plugin: Option<Plugins>,
82 slow_query_options: SlowQueryOptions,
83 auto_create_table: bool,
84}
85
86impl GreptimeDbStandaloneBuilder {
87 pub fn new(instance_name: &str) -> Self {
88 Self {
89 instance_name: instance_name.to_string(),
90 store_providers: None,
91 plugin: None,
92 default_store: None,
93 datanode_wal_config: DatanodeWalConfig::default(),
94 metasrv_wal_config: MetasrvWalConfig::default(),
95 slow_query_options: SlowQueryOptions {
97 enable: true,
98 threshold: Duration::from_secs(1),
99 ..Default::default()
100 },
101 auto_create_table: true,
102 }
103 }
104
105 #[must_use]
106 pub fn with_auto_create_table(mut self, auto_create_table: bool) -> Self {
107 self.auto_create_table = auto_create_table;
108 self
109 }
110
111 #[must_use]
112 pub fn with_default_store_type(self, store_type: StorageType) -> Self {
113 Self {
114 default_store: Some(store_type),
115 ..self
116 }
117 }
118
119 #[cfg(test)]
120 #[must_use]
121 pub fn with_store_providers(self, store_providers: Vec<StorageType>) -> Self {
122 Self {
123 store_providers: Some(store_providers),
124 ..self
125 }
126 }
127
128 #[must_use]
129 pub fn with_plugin(self, plugin: Plugins) -> Self {
130 Self {
131 plugin: Some(plugin),
132 ..self
133 }
134 }
135
136 #[must_use]
137 pub fn with_slow_query_threshold(mut self, threshold: Duration) -> Self {
138 self.slow_query_options.threshold = threshold;
139 self
140 }
141
142 #[must_use]
143 pub fn with_datanode_wal_config(mut self, datanode_wal_config: DatanodeWalConfig) -> Self {
144 self.datanode_wal_config = datanode_wal_config;
145 self
146 }
147
148 #[must_use]
149 pub fn with_metasrv_wal_config(mut self, metasrv_wal_config: MetasrvWalConfig) -> Self {
150 self.metasrv_wal_config = metasrv_wal_config;
151 self
152 }
153
154 pub async fn build_with(
155 &self,
156 kv_backend: KvBackendRef,
157 guard: TestGuard,
158 opts: StandaloneOptions,
159 procedure_manager: ProcedureManagerRef,
160 register_procedure_loaders: bool,
161 ) -> GreptimeDbStandalone {
162 let plugins = self.plugin.clone().unwrap_or_default();
163
164 let layered_cache_registry = Arc::new(
165 LayeredCacheRegistryBuilder::default()
166 .add_cache_registry(build_datanode_cache_registry(kv_backend.clone()))
167 .build(),
168 );
169
170 let mut builder =
171 DatanodeBuilder::new(opts.datanode_options(), plugins.clone(), kv_backend.clone());
172 builder.with_cache_registry(layered_cache_registry);
173 let datanode = builder.build().await.unwrap();
174
175 let table_metadata_manager = Arc::new(TableMetadataManager::new(kv_backend.clone()));
176 table_metadata_manager.init().await.unwrap();
177
178 let flow_metadata_manager = Arc::new(FlowMetadataManager::new(kv_backend.clone()));
179
180 let layered_cache_builder = LayeredCacheRegistryBuilder::default();
181 let fundamental_cache_registry = build_fundamental_cache_registry(kv_backend.clone());
182 let cache_registry = Arc::new(
183 with_default_composite_cache_registry(
184 layered_cache_builder.add_cache_registry(fundamental_cache_registry),
185 )
186 .unwrap()
187 .build(),
188 );
189
190 let catalog_manager = KvBackendCatalogManagerBuilder::new(
191 Arc::new(NoopInformationExtension),
192 kv_backend.clone(),
193 cache_registry.clone(),
194 )
195 .with_procedure_manager(procedure_manager.clone())
196 .build();
197
198 let (frontend_client, frontend_instance_handler) =
199 FrontendClient::from_empty_grpc_handler(opts.query.clone());
200 let flow_builder = FlownodeBuilder::new(
201 Default::default(),
202 plugins.clone(),
203 table_metadata_manager.clone(),
204 catalog_manager.clone(),
205 flow_metadata_manager.clone(),
206 Arc::new(frontend_client),
207 );
208 let flownode = Arc::new(flow_builder.build().await.unwrap());
209
210 let node_manager = Arc::new(StandaloneDatanodeManager {
211 region_server: datanode.region_server(),
212 flow_server: flownode.flow_engine(),
213 });
214
215 let table_id_allocator = Arc::new(
216 SequenceBuilder::new(TABLE_ID_SEQ, kv_backend.clone())
217 .initial(MIN_USER_TABLE_ID as u64)
218 .step(10)
219 .build(),
220 );
221 let flow_id_sequence = Arc::new(
222 SequenceBuilder::new(FLOW_ID_SEQ, kv_backend.clone())
223 .initial(MIN_USER_FLOW_ID as u64)
224 .step(10)
225 .build(),
226 );
227 let kafka_options = opts.wal.clone().try_into().unwrap();
228 let wal_provider = build_wal_provider(&kafka_options, kv_backend.clone())
229 .await
230 .unwrap();
231 let wal_provider = Arc::new(wal_provider);
232 let table_metadata_allocator = Arc::new(TableMetadataAllocator::new(
233 table_id_allocator,
234 wal_provider.clone(),
235 ));
236 let flow_metadata_allocator = Arc::new(FlowMetadataAllocator::with_noop_peer_allocator(
237 flow_id_sequence,
238 ));
239
240 let repartition_procedure_factory = Arc::new(StandaloneRepartitionProcedureFactory);
241 let ddl_manager = Arc::new(
242 DdlManager::try_new(
243 DdlContext {
244 node_manager: node_manager.clone(),
245 cache_invalidator: cache_registry.clone(),
246 memory_region_keeper: Arc::new(MemoryRegionKeeper::default()),
247 leader_region_registry: Arc::new(LeaderRegionRegistry::default()),
248 table_metadata_manager,
249 table_metadata_allocator,
250 flow_metadata_manager,
251 flow_metadata_allocator,
252 region_failure_detector_controller: Arc::new(NoopRegionFailureDetectorControl),
253 },
254 procedure_manager.clone(),
255 repartition_procedure_factory,
256 register_procedure_loaders,
257 )
258 .unwrap(),
259 );
260 let procedure_executor = Arc::new(LocalProcedureExecutor::new(
261 ddl_manager,
262 procedure_manager.clone(),
263 ));
264
265 let server_addr = opts.frontend_options().grpc.server_addr.clone();
266
267 let instance = FrontendBuilder::new(
268 opts.frontend_options(),
269 kv_backend.clone(),
270 cache_registry.clone(),
271 catalog_manager.clone(),
272 node_manager.clone(),
273 procedure_executor.clone(),
274 Arc::new(ProcessManager::new(server_addr, None)),
275 )
276 .with_plugin(plugins.clone())
277 .try_build()
278 .await
279 .unwrap();
280 let instance = Arc::new(instance);
281
282 let grpc_handler = instance.clone() as Arc<dyn GrpcQueryHandlerWithBoxedError>;
284 let weak_grpc_handler = Arc::downgrade(&grpc_handler);
285 frontend_instance_handler
286 .set_handler(weak_grpc_handler)
287 .await;
288
289 let flow_streaming_engine = flownode.flow_engine().streaming_engine();
290 let invoker = flow::FrontendInvoker::build_from(
291 flow_streaming_engine.clone(),
292 catalog_manager.clone(),
293 kv_backend.clone(),
294 cache_registry.clone(),
295 procedure_executor.clone(),
296 node_manager.clone(),
297 instance.frontend_peer_addr().to_string(),
298 )
299 .await
300 .context(StartFlownodeSnafu)
301 .unwrap();
302
303 flow_streaming_engine.set_frontend_invoker(invoker).await;
304
305 procedure_manager.start().await.unwrap();
306 wal_provider.start().await.unwrap();
307
308 test_util::prepare_another_catalog_and_schema(&instance).await;
309
310 let servers = Services::new(opts.clone(), instance.clone(), plugins)
311 .build()
312 .unwrap();
313 let frontend = Frontend {
314 instance,
315 servers,
316 heartbeat_task: None,
317 };
318
319 GreptimeDbStandalone {
320 frontend: Arc::new(frontend),
321 opts,
322 guard,
323 kv_backend,
324 procedure_manager,
325 }
326 }
327
328 pub async fn build(&self) -> GreptimeDbStandalone {
329 let default_store_type = self.default_store.unwrap_or(StorageType::File);
330 let store_types = self.store_providers.clone().unwrap_or_default();
331
332 let (opts, guard) = create_tmp_dir_and_datanode_opts(
333 default_store_type,
334 store_types,
335 &self.instance_name,
336 self.datanode_wal_config.clone(),
337 Default::default(),
338 );
339
340 let kv_backend_config = KvBackendConfig::default();
341 let procedure_config = ProcedureConfig::default();
342
343 let kv_backend = standalone::build_metadata_kvbackend(
344 format!("{}/kv", &opts.storage.data_home),
345 kv_backend_config,
346 )
347 .unwrap();
348 let procedure_manager =
349 standalone::build_procedure_manager(kv_backend.clone(), procedure_config);
350
351 let standalone_opts = StandaloneOptions {
352 storage: opts.storage,
353 procedure: procedure_config,
354 metadata_store: kv_backend_config,
355 wal: self.metasrv_wal_config.clone().into(),
356 grpc: GrpcOptions::default().with_server_addr("127.0.0.1:4001"),
357 slow_query: self.slow_query_options.clone(),
358 auto_create_table: self.auto_create_table,
359 ..StandaloneOptions::default()
360 };
361
362 self.build_with(kv_backend, guard, standalone_opts, procedure_manager, true)
363 .await
364 }
365}