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