1pub mod flow_info;
16pub(crate) mod flow_name;
17pub mod flow_route;
18pub mod flow_state;
19mod flownode_addr_helper;
20pub(crate) mod flownode_flow;
21pub(crate) mod table_flow;
22use std::collections::{BTreeMap, HashSet};
23use std::ops::Deref;
24use std::sync::Arc;
25
26use common_telemetry::info;
27use flow_route::{FlowRouteKey, FlowRouteManager, FlowRouteValue};
28use snafu::{OptionExt, ensure};
29use table_flow::TableFlowValue;
30
31use self::flow_info::{FlowInfoKey, FlowInfoValue};
32use self::flow_name::FlowNameKey;
33use self::flownode_flow::FlownodeFlowKey;
34use self::table_flow::TableFlowKey;
35use crate::ensure_values;
36use crate::error::{self, Result};
37use crate::key::flow::flow_info::FlowInfoManager;
38use crate::key::flow::flow_name::FlowNameManager;
39use crate::key::flow::flow_state::FlowStateManager;
40use crate::key::flow::flownode_flow::FlownodeFlowManager;
41pub use crate::key::flow::table_flow::{TableFlowManager, TableFlowManagerRef};
42use crate::key::txn_helper::TxnOpGetResponseSet;
43use crate::key::{DeserializedValueWithBytes, FlowId, FlowPartitionId, MetadataKey};
44use crate::kv_backend::KvBackendRef;
45use crate::kv_backend::txn::{Txn, TxnOp};
46use crate::rpc::store::BatchDeleteRequest;
47
48pub const FLOW_KEY_PREFIX: &str = "__flow";
49
50pub fn scoped_flow_key(inner_key: &str) -> String {
52 format!("{FLOW_KEY_PREFIX}/{inner_key}")
53}
54
55pub fn scoped_flow_key_prefix(inner_prefix: &str) -> String {
57 scoped_flow_key(inner_prefix)
58}
59
60pub fn flow_info_key_prefix() -> String {
62 scoped_flow_key_prefix(flow_info::FLOW_INFO_KEY_PREFIX)
63}
64
65pub fn flow_name_key_prefix() -> String {
67 scoped_flow_key_prefix(flow_name::FLOW_NAME_KEY_PREFIX)
68}
69
70pub fn flow_route_key_prefix() -> String {
72 scoped_flow_key_prefix(flow_route::FLOW_ROUTE_KEY_PREFIX)
73}
74
75pub fn table_flow_key_prefix() -> String {
77 scoped_flow_key_prefix(table_flow::TABLE_FLOW_KEY_PREFIX)
78}
79
80pub fn flownode_flow_key_prefix() -> String {
82 scoped_flow_key_prefix(flownode_flow::FLOWNODE_FLOW_KEY_PREFIX)
83}
84
85pub fn flow_state_full_key() -> String {
87 scoped_flow_key(flow_state::FLOW_STATE_KEY)
88}
89
90#[derive(Debug, Clone, PartialEq)]
92pub struct FlowScoped<T> {
93 inner: T,
94}
95
96impl<T> Deref for FlowScoped<T> {
97 type Target = T;
98
99 fn deref(&self) -> &Self::Target {
100 &self.inner
101 }
102}
103
104impl<T> FlowScoped<T> {
105 const PREFIX: &'static str = "__flow/";
106
107 pub fn new(inner: T) -> FlowScoped<T> {
109 Self { inner }
110 }
111}
112
113impl<'a, T: MetadataKey<'a, T>> MetadataKey<'a, FlowScoped<T>> for FlowScoped<T> {
114 fn to_bytes(&self) -> Vec<u8> {
115 let prefix = FlowScoped::<T>::PREFIX.as_bytes();
116 let inner = self.inner.to_bytes();
117 let mut bytes = Vec::with_capacity(prefix.len() + inner.len());
118 bytes.extend(prefix);
119 bytes.extend(inner);
120 bytes
121 }
122
123 fn from_bytes(bytes: &'a [u8]) -> Result<FlowScoped<T>> {
124 let prefix = FlowScoped::<T>::PREFIX.as_bytes();
125 ensure!(
126 bytes.starts_with(prefix),
127 error::MismatchPrefixSnafu {
128 prefix: String::from_utf8_lossy(prefix),
129 key: String::from_utf8_lossy(bytes),
130 }
131 );
132 let inner = T::from_bytes(&bytes[prefix.len()..])?;
133 Ok(FlowScoped { inner })
134 }
135}
136
137fn build_replace_ops(
142 old_keys: impl IntoIterator<Item = Vec<u8>>,
143 new_kvs: Vec<(Vec<u8>, Vec<u8>)>,
144) -> Vec<TxnOp> {
145 let new_keys = new_kvs
146 .iter()
147 .map(|(key, _)| key.as_slice())
148 .collect::<HashSet<_>>();
149 let mut ops = old_keys
150 .into_iter()
151 .filter(|key| !new_keys.contains(key.as_slice()))
152 .map(TxnOp::Delete)
153 .collect::<Vec<_>>();
154 ops.extend(
155 new_kvs
156 .into_iter()
157 .map(|(key, value)| TxnOp::Put(key, value)),
158 );
159 ops
160}
161
162pub type FlowMetadataManagerRef = Arc<FlowMetadataManager>;
163
164pub struct FlowMetadataManager {
169 flow_info_manager: FlowInfoManager,
170 flow_route_manager: FlowRouteManager,
171 flownode_flow_manager: FlownodeFlowManager,
172 table_flow_manager: TableFlowManager,
173 flow_name_manager: FlowNameManager,
174 flow_state_manager: Option<FlowStateManager>,
176 kv_backend: KvBackendRef,
177}
178
179impl FlowMetadataManager {
180 pub fn new(kv_backend: KvBackendRef) -> Self {
182 Self {
183 flow_info_manager: FlowInfoManager::new(kv_backend.clone()),
184 flow_route_manager: FlowRouteManager::new(kv_backend.clone()),
185 flow_name_manager: FlowNameManager::new(kv_backend.clone()),
186 flownode_flow_manager: FlownodeFlowManager::new(kv_backend.clone()),
187 table_flow_manager: TableFlowManager::new(kv_backend.clone()),
188 flow_state_manager: None,
189 kv_backend,
190 }
191 }
192
193 pub fn flow_name_manager(&self) -> &FlowNameManager {
195 &self.flow_name_manager
196 }
197
198 pub fn flow_state_manager(&self) -> Option<&FlowStateManager> {
199 self.flow_state_manager.as_ref()
200 }
201
202 pub fn flow_info_manager(&self) -> &FlowInfoManager {
204 &self.flow_info_manager
205 }
206
207 pub fn flow_route_manager(&self) -> &FlowRouteManager {
209 &self.flow_route_manager
210 }
211
212 pub fn flownode_flow_manager(&self) -> &FlownodeFlowManager {
214 &self.flownode_flow_manager
215 }
216
217 pub fn table_flow_manager(&self) -> &TableFlowManager {
219 &self.table_flow_manager
220 }
221
222 pub async fn flownode_addrs(
224 &self,
225 flow_id: FlowId,
226 ) -> Result<BTreeMap<FlowPartitionId, String>> {
227 let routes = self.flow_route_manager.routes(flow_id).await?;
228
229 Ok(routes
230 .into_iter()
231 .filter_map(|(key, route)| {
232 let addr = route.peer.addr;
233 (!addr.is_empty()).then_some((key.partition_id(), addr))
234 })
235 .collect())
236 }
237
238 pub async fn create_flow_metadata(
240 &self,
241 flow_id: FlowId,
242 flow_info: FlowInfoValue,
243 flow_routes: Vec<(FlowPartitionId, FlowRouteValue)>,
244 ) -> Result<()> {
245 let (create_flow_flow_name_txn, on_create_flow_flow_name_failure) = self
246 .flow_name_manager
247 .build_create_txn(&flow_info.catalog_name, &flow_info.flow_name, flow_id)?;
248
249 let (create_flow_txn, on_create_flow_failure) = self
250 .flow_info_manager
251 .build_create_txn(flow_id, &flow_info)?;
252
253 let create_flow_routes_txn = self
254 .flow_route_manager
255 .build_create_txn(flow_id, flow_routes.clone())?;
256
257 let create_flownode_flow_txn = self
258 .flownode_flow_manager
259 .build_create_txn(flow_id, flow_info.flownode_ids().clone());
260
261 let create_table_flow_txn = self.table_flow_manager.build_create_txn(
262 flow_id,
263 flow_routes
264 .into_iter()
265 .map(|(partition_id, route)| (partition_id, TableFlowValue { peer: route.peer }))
266 .collect(),
267 flow_info.source_table_ids(),
268 )?;
269
270 let txn = Txn::merge_all(vec![
271 create_flow_flow_name_txn,
272 create_flow_txn,
273 create_flow_routes_txn,
274 create_flownode_flow_txn,
275 create_table_flow_txn,
276 ]);
277 info!(
278 "Creating flow {}.{}({}), with {} txn operations",
279 flow_info.catalog_name,
280 flow_info.flow_name,
281 flow_id,
282 txn.max_operations()
283 );
284
285 let mut resp = self.kv_backend.txn(txn).await?;
286 if !resp.succeeded {
287 let mut set = TxnOpGetResponseSet::from(&mut resp.responses);
288 let remote_flow_flow_name =
289 on_create_flow_flow_name_failure(&mut set)?.with_context(|| {
290 error::UnexpectedSnafu {
291 err_msg: format!(
292 "Reads the empty flow name in comparing operation of the creating flow, flow_id: {flow_id}"
293 ),
294 }
295 })?;
296
297 if remote_flow_flow_name.flow_id() != flow_id {
298 info!(
299 "Trying to create flow {}.{}({}), but flow({}) already exists",
300 flow_info.catalog_name,
301 flow_info.flow_name,
302 flow_id,
303 remote_flow_flow_name.flow_id()
304 );
305
306 return error::FlowAlreadyExistsSnafu {
307 flow_name: format!("{}.{}", flow_info.catalog_name, flow_info.flow_name),
308 }
309 .fail();
310 }
311
312 let remote_flow =
313 on_create_flow_failure(&mut set)?.with_context(|| error::UnexpectedSnafu {
314 err_msg: format!(
315 "Reads the empty flow in comparing operation of creating flow, flow_id: {flow_id}"
316 ),
317 })?;
318 let op_name = "creating flow";
319 ensure_values!(*remote_flow, flow_info, op_name);
320 }
321
322 Ok(())
323 }
324
325 pub async fn update_flow_metadata(
327 &self,
328 flow_id: FlowId,
329 current_flow_info: &DeserializedValueWithBytes<FlowInfoValue>,
330 new_flow_info: &FlowInfoValue,
331 flow_routes: Vec<(FlowPartitionId, FlowRouteValue)>,
332 ) -> Result<()> {
333 let (update_flow_flow_name_txn, on_create_flow_flow_name_failure) =
334 self.flow_name_manager.build_update_txn(
335 &new_flow_info.catalog_name,
336 &new_flow_info.flow_name,
337 flow_id,
338 )?;
339
340 let (update_flow_txn, on_create_flow_failure) =
341 self.flow_info_manager
342 .build_update_txn(flow_id, current_flow_info, new_flow_info)?;
343
344 let update_flow_routes_txn = self.flow_route_manager.build_update_txn(
345 flow_id,
346 current_flow_info,
347 flow_routes.clone(),
348 )?;
349
350 let update_flownode_flow_txn = self.flownode_flow_manager.build_update_txn(
351 flow_id,
352 current_flow_info,
353 new_flow_info.flownode_ids().clone(),
354 );
355
356 let update_table_flow_txn = self.table_flow_manager.build_update_txn(
357 flow_id,
358 current_flow_info,
359 flow_routes
360 .into_iter()
361 .map(|(partition_id, route)| (partition_id, TableFlowValue { peer: route.peer }))
362 .collect(),
363 new_flow_info.source_table_ids(),
364 )?;
365
366 let txn = Txn::merge_all(vec![
367 update_flow_flow_name_txn,
368 update_flow_txn,
369 update_flow_routes_txn,
370 update_flownode_flow_txn,
371 update_table_flow_txn,
372 ]);
373 info!(
374 "Creating flow {}.{}({}), with {} txn operations",
375 new_flow_info.catalog_name,
376 new_flow_info.flow_name,
377 flow_id,
378 txn.max_operations()
379 );
380
381 let mut resp = self.kv_backend.txn(txn).await?;
382 if !resp.succeeded {
383 let mut set = TxnOpGetResponseSet::from(&mut resp.responses);
384 let remote_flow_flow_name =
385 on_create_flow_flow_name_failure(&mut set)?.with_context(|| {
386 error::UnexpectedSnafu {
387 err_msg: format!(
388 "Reads the empty flow name in comparing operation of the updating flow, flow_id: {flow_id}"
389 ),
390 }
391 })?;
392
393 if remote_flow_flow_name.flow_id() != flow_id {
394 info!(
395 "Trying to updating flow {}.{}({}), but flow({}) already exists with a different flow id",
396 new_flow_info.catalog_name,
397 new_flow_info.flow_name,
398 flow_id,
399 remote_flow_flow_name.flow_id()
400 );
401
402 return error::UnexpectedSnafu {
403 err_msg: format!(
404 "Reads different flow id when updating flow({2}.{3}), prev flow id = {0}, updating with flow id = {1}",
405 remote_flow_flow_name.flow_id(),
406 flow_id,
407 new_flow_info.catalog_name,
408 new_flow_info.flow_name,
409 ),
410 }.fail();
411 }
412
413 let remote_flow =
414 on_create_flow_failure(&mut set)?.with_context(|| error::UnexpectedSnafu {
415 err_msg: format!(
416 "Reads the empty flow in comparing operation of the updating flow, flow_id: {flow_id}"
417 ),
418 })?;
419 let op_name = "updating flow";
420 ensure_values!(*remote_flow, new_flow_info.clone(), op_name);
421 }
422
423 Ok(())
424 }
425
426 fn flow_metadata_keys(&self, flow_id: FlowId, flow_value: &FlowInfoValue) -> Vec<Vec<u8>> {
427 let source_table_ids = flow_value.source_table_ids();
428 let mut keys =
429 Vec::with_capacity(2 + flow_value.flownode_ids.len() * (source_table_ids.len() + 2));
430 let flow_name = FlowNameKey::new(&flow_value.catalog_name, &flow_value.flow_name);
432 keys.push(flow_name.to_bytes());
433
434 let flow_info_key = FlowInfoKey::new(flow_id);
436 keys.push(flow_info_key.to_bytes());
437
438 flow_value
440 .flownode_ids
441 .iter()
442 .for_each(|(&partition_id, &flownode_id)| {
443 keys.push(FlownodeFlowKey::new(flownode_id, flow_id, partition_id).to_bytes());
444 keys.push(FlowRouteKey::new(flow_id, partition_id).to_bytes());
445 source_table_ids.iter().for_each(|&table_id| {
446 keys.push(
447 TableFlowKey::new(table_id, flownode_id, flow_id, partition_id).to_bytes(),
448 );
449 })
450 });
451 keys
452 }
453
454 pub async fn destroy_flow_metadata(
456 &self,
457 flow_id: FlowId,
458 flow_value: &FlowInfoValue,
459 ) -> Result<()> {
460 let keys = self.flow_metadata_keys(flow_id, flow_value);
461 let _ = self
462 .kv_backend
463 .batch_delete(BatchDeleteRequest::new().with_keys(keys))
464 .await?;
465 Ok(())
466 }
467}
468
469impl std::fmt::Debug for FlowMetadataManager {
470 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
471 f.debug_struct("FlowMetadataManager").finish()
472 }
473}
474
475#[cfg(test)]
476mod tests {
477 use std::assert_matches;
478 use std::collections::BTreeMap;
479 use std::sync::Arc;
480
481 use futures::TryStreamExt;
482 use table::metadata::TableId;
483 use table::table_name::TableName;
484 use uuid::Uuid;
485
486 use super::*;
487 use crate::FlownodeId;
488 use crate::key::flow::flow_info::FlowStatus;
489 use crate::key::flow::table_flow::TableFlowKey;
490 use crate::key::node_address::{NodeAddressKey, NodeAddressValue};
491 use crate::key::{FlowPartitionId, MetadataValue};
492 use crate::kv_backend::chroot::ChrootKvBackend;
493 use crate::kv_backend::etcd::EtcdStore;
494 use crate::kv_backend::memory::MemoryKvBackend;
495 use crate::kv_backend::{KvBackend, KvBackendRef};
496 use crate::peer::Peer;
497 use crate::rpc::store::PutRequest;
498
499 #[derive(Debug)]
500 struct MockKey {
501 inner: Vec<u8>,
502 }
503
504 impl<'a> MetadataKey<'a, MockKey> for MockKey {
505 fn to_bytes(&self) -> Vec<u8> {
506 self.inner.clone()
507 }
508
509 fn from_bytes(bytes: &'a [u8]) -> Result<MockKey> {
510 Ok(MockKey {
511 inner: bytes.to_vec(),
512 })
513 }
514 }
515
516 #[test]
517 fn test_flow_scoped_to_bytes() {
518 let key = FlowScoped::new(MockKey {
519 inner: b"hi".to_vec(),
520 });
521 assert_eq!(b"__flow/hi".to_vec(), key.to_bytes());
522 }
523
524 #[test]
525 fn test_flow_scoped_from_bytes() {
526 let bytes = b"__flow/hi";
527 let key = FlowScoped::<MockKey>::from_bytes(bytes).unwrap();
528 assert_eq!(key.inner.inner, b"hi".to_vec());
529 }
530
531 #[test]
532 fn test_flow_scoped_from_bytes_mismatch() {
533 let bytes = b"__table/hi";
534 let err = FlowScoped::<MockKey>::from_bytes(bytes).unwrap_err();
535 assert_matches!(err, error::Error::MismatchPrefix { .. });
536 }
537
538 fn test_flow_info_value(
539 flow_name: &str,
540 flownode_ids: BTreeMap<FlowPartitionId, FlownodeId>,
541 source_table_ids: Vec<TableId>,
542 ) -> FlowInfoValue {
543 let catalog_name = "greptime";
544 let sink_table_name = TableName {
545 catalog_name: catalog_name.to_string(),
546 schema_name: "my_schema".to_string(),
547 table_name: "sink_table".to_string(),
548 };
549 FlowInfoValue {
550 catalog_name: catalog_name.to_string(),
551 query_context: None,
552 flow_name: flow_name.to_string(),
553 source_table_ids,
554 all_source_table_names: vec![],
555 unresolved_source_table_names: vec![],
556 sink_table_name,
557 flownode_ids,
558 raw_sql: "raw".to_string(),
559 expire_after: Some(300),
560 eval_interval_secs: None,
561 comment: "hi".to_string(),
562 options: Default::default(),
563 status: FlowStatus::Active,
564 created_time: chrono::Utc::now(),
565 updated_time: chrono::Utc::now(),
566 eval_schedule: None,
567 }
568 }
569
570 #[tokio::test]
571 async fn test_create_flow_metadata() {
572 let mem_kv = Arc::new(MemoryKvBackend::default());
573 let flow_metadata_manager = FlowMetadataManager::new(mem_kv.clone());
574 let flow_id = 10;
575 let flow_value = test_flow_info_value(
576 "flow",
577 [(0, 1u64), (1, 2u64)].into(),
578 vec![1024, 1025, 1026],
579 );
580 let flow_routes = vec![
581 (
582 1u32,
583 FlowRouteValue {
584 peer: Peer::empty(1),
585 },
586 ),
587 (
588 2,
589 FlowRouteValue {
590 peer: Peer::empty(2),
591 },
592 ),
593 ];
594 flow_metadata_manager
595 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
596 .await
597 .unwrap();
598 flow_metadata_manager
600 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
601 .await
602 .unwrap();
603 let got = flow_metadata_manager
604 .flow_info_manager()
605 .get(flow_id)
606 .await
607 .unwrap()
608 .unwrap();
609 let routes = flow_metadata_manager
610 .flow_route_manager()
611 .routes(flow_id)
612 .await
613 .unwrap();
614 assert_eq!(
615 routes,
616 vec![
617 (
618 FlowRouteKey::new(flow_id, 1),
619 FlowRouteValue {
620 peer: Peer::empty(1),
621 },
622 ),
623 (
624 FlowRouteKey::new(flow_id, 2),
625 FlowRouteValue {
626 peer: Peer::empty(2),
627 },
628 ),
629 ]
630 );
631 assert_eq!(got, flow_value);
632 let flows = flow_metadata_manager
633 .flownode_flow_manager()
634 .flows(1)
635 .try_collect::<Vec<_>>()
636 .await
637 .unwrap();
638 assert_eq!(flows, vec![(flow_id, 0)]);
639 for table_id in [1024, 1025, 1026] {
640 let nodes = flow_metadata_manager
641 .table_flow_manager()
642 .flows(table_id)
643 .await
644 .unwrap();
645 assert_eq!(
646 nodes,
647 vec![
648 (
649 TableFlowKey::new(table_id, 1, flow_id, 1),
650 TableFlowValue {
651 peer: Peer::empty(1)
652 }
653 ),
654 (
655 TableFlowKey::new(table_id, 2, flow_id, 2),
656 TableFlowValue {
657 peer: Peer::empty(2)
658 }
659 )
660 ]
661 );
662 }
663 }
664
665 #[tokio::test]
666 async fn test_flownode_addrs_remaps_to_latest_address() {
667 let mem_kv = Arc::new(MemoryKvBackend::default());
668 let flow_metadata_manager = FlowMetadataManager::new(mem_kv.clone());
669 let flow_id = 10;
670 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024]);
671 let flow_routes = vec![(
672 0u32,
673 FlowRouteValue {
674 peer: Peer::new(1, "old-addr"),
675 },
676 )];
677
678 flow_metadata_manager
679 .create_flow_metadata(flow_id, flow_value, flow_routes)
680 .await
681 .unwrap();
682
683 mem_kv
684 .put(PutRequest {
685 key: NodeAddressKey::with_flownode(1).to_bytes(),
686 value: NodeAddressValue::new(Peer::new(1, "new-addr"))
687 .try_as_raw_value()
688 .unwrap(),
689 ..Default::default()
690 })
691 .await
692 .unwrap();
693
694 let addrs = flow_metadata_manager.flownode_addrs(flow_id).await.unwrap();
695 assert_eq!(addrs, BTreeMap::from([(0, "new-addr".to_string())]));
696 }
697
698 #[tokio::test]
699 async fn test_flownode_addrs_falls_back_to_route_address() {
700 let mem_kv = Arc::new(MemoryKvBackend::default());
701 let flow_metadata_manager = FlowMetadataManager::new(mem_kv);
702 let flow_id = 10;
703 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024]);
704 let flow_routes = vec![(
705 0u32,
706 FlowRouteValue {
707 peer: Peer::new(1, "route-addr"),
708 },
709 )];
710
711 flow_metadata_manager
712 .create_flow_metadata(flow_id, flow_value, flow_routes)
713 .await
714 .unwrap();
715
716 let addrs = flow_metadata_manager.flownode_addrs(flow_id).await.unwrap();
717 assert_eq!(addrs, BTreeMap::from([(0, "route-addr".to_string())]));
718 }
719
720 #[tokio::test]
721 async fn test_flownode_addrs_skips_empty_addresses() {
722 let mem_kv = Arc::new(MemoryKvBackend::default());
723 let flow_metadata_manager = FlowMetadataManager::new(mem_kv);
724 let flow_id = 10;
725 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024]);
726 let flow_routes = vec![(
727 0u32,
728 FlowRouteValue {
729 peer: Peer::empty(1),
730 },
731 )];
732
733 flow_metadata_manager
734 .create_flow_metadata(flow_id, flow_value, flow_routes)
735 .await
736 .unwrap();
737
738 let addrs = flow_metadata_manager.flownode_addrs(flow_id).await.unwrap();
739 assert!(addrs.is_empty());
740 }
741
742 #[tokio::test]
743 async fn test_create_flow_metadata_flow_exists_err() {
744 let mem_kv = Arc::new(MemoryKvBackend::default());
745 let flow_metadata_manager = FlowMetadataManager::new(mem_kv);
746 let flow_id = 10;
747 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024, 1025, 1026]);
748 let flow_routes = vec![
749 (
750 1u32,
751 FlowRouteValue {
752 peer: Peer::empty(1),
753 },
754 ),
755 (
756 2,
757 FlowRouteValue {
758 peer: Peer::empty(2),
759 },
760 ),
761 ];
762 flow_metadata_manager
763 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
764 .await
765 .unwrap();
766 let err = flow_metadata_manager
768 .create_flow_metadata(flow_id + 1, flow_value, flow_routes.clone())
769 .await
770 .unwrap_err();
771 assert_matches!(err, error::Error::FlowAlreadyExists { .. });
772 }
773
774 #[tokio::test]
775 async fn test_create_flow_metadata_unexpected_err() {
776 let mem_kv = Arc::new(MemoryKvBackend::default());
777 let flow_metadata_manager = FlowMetadataManager::new(mem_kv);
778 let flow_id = 10;
779 let catalog_name = "greptime";
780 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024, 1025, 1026]);
781 let flow_routes = vec![
782 (
783 1u32,
784 FlowRouteValue {
785 peer: Peer::empty(1),
786 },
787 ),
788 (
789 2,
790 FlowRouteValue {
791 peer: Peer::empty(2),
792 },
793 ),
794 ];
795 flow_metadata_manager
796 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
797 .await
798 .unwrap();
799 let another_sink_table_name = TableName {
801 catalog_name: catalog_name.to_string(),
802 schema_name: "my_schema".to_string(),
803 table_name: "another_sink_table".to_string(),
804 };
805 let flow_value = FlowInfoValue {
806 catalog_name: "greptime".to_string(),
807 query_context: None,
808 flow_name: "flow".to_string(),
809 source_table_ids: vec![1024, 1025, 1026],
810 all_source_table_names: vec![],
811 unresolved_source_table_names: vec![],
812 sink_table_name: another_sink_table_name,
813 flownode_ids: [(0, 1u64)].into(),
814 raw_sql: "raw".to_string(),
815 expire_after: Some(300),
816 eval_interval_secs: None,
817 comment: "hi".to_string(),
818 options: Default::default(),
819 status: FlowStatus::Active,
820 created_time: chrono::Utc::now(),
821 updated_time: chrono::Utc::now(),
822 eval_schedule: None,
823 };
824 let err = flow_metadata_manager
825 .create_flow_metadata(flow_id, flow_value, flow_routes.clone())
826 .await
827 .unwrap_err();
828 assert!(err.to_string().contains("Reads the different value"));
829 }
830
831 #[tokio::test]
832 async fn test_destroy_flow_metadata() {
833 let mem_kv = Arc::new(MemoryKvBackend::default());
834 let flow_metadata_manager = FlowMetadataManager::new(mem_kv.clone());
835 let flow_id = 10;
836 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024, 1025, 1026]);
837 let flow_routes = vec![(
838 0u32,
839 FlowRouteValue {
840 peer: Peer::empty(1),
841 },
842 )];
843 flow_metadata_manager
844 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
845 .await
846 .unwrap();
847
848 flow_metadata_manager
849 .destroy_flow_metadata(flow_id, &flow_value)
850 .await
851 .unwrap();
852 flow_metadata_manager
854 .destroy_flow_metadata(flow_id, &flow_value)
855 .await
856 .unwrap();
857 assert!(mem_kv.is_empty())
859 }
860
861 #[tokio::test]
862 async fn test_update_flow_metadata() {
863 let mem_kv = Arc::new(MemoryKvBackend::default());
864 let flow_metadata_manager = FlowMetadataManager::new(mem_kv.clone());
865 let flow_id = 10;
866 let flow_value = test_flow_info_value(
867 "flow",
868 [(0, 1u64), (1, 2u64)].into(),
869 vec![1024, 1025, 1026],
870 );
871 let flow_routes = vec![
872 (
873 1u32,
874 FlowRouteValue {
875 peer: Peer::empty(1),
876 },
877 ),
878 (
879 2,
880 FlowRouteValue {
881 peer: Peer::empty(2),
882 },
883 ),
884 ];
885 flow_metadata_manager
886 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
887 .await
888 .unwrap();
889
890 let new_flow_value = {
891 let mut tmp = flow_value.clone();
892 tmp.raw_sql = "new".to_string();
893 tmp
894 };
895
896 flow_metadata_manager
898 .update_flow_metadata(
899 flow_id,
900 &DeserializedValueWithBytes::from_inner(flow_value.clone()),
901 &new_flow_value,
902 flow_routes.clone(),
903 )
904 .await
905 .unwrap();
906
907 let got = flow_metadata_manager
908 .flow_info_manager()
909 .get(flow_id)
910 .await
911 .unwrap()
912 .unwrap();
913 let routes = flow_metadata_manager
914 .flow_route_manager()
915 .routes(flow_id)
916 .await
917 .unwrap();
918 assert_eq!(
919 routes,
920 vec![
921 (
922 FlowRouteKey::new(flow_id, 1),
923 FlowRouteValue {
924 peer: Peer::empty(1),
925 },
926 ),
927 (
928 FlowRouteKey::new(flow_id, 2),
929 FlowRouteValue {
930 peer: Peer::empty(2),
931 },
932 ),
933 ]
934 );
935 assert_eq!(got, new_flow_value);
936 let flows = flow_metadata_manager
937 .flownode_flow_manager()
938 .flows(1)
939 .try_collect::<Vec<_>>()
940 .await
941 .unwrap();
942 assert_eq!(flows, vec![(flow_id, 0)]);
943 for table_id in [1024, 1025, 1026] {
944 let nodes = flow_metadata_manager
945 .table_flow_manager()
946 .flows(table_id)
947 .await
948 .unwrap();
949 assert_eq!(
950 nodes,
951 vec![
952 (
953 TableFlowKey::new(table_id, 1, flow_id, 1),
954 TableFlowValue {
955 peer: Peer::empty(1)
956 }
957 ),
958 (
959 TableFlowKey::new(table_id, 2, flow_id, 2),
960 TableFlowValue {
961 peer: Peer::empty(2)
962 }
963 )
964 ]
965 );
966 }
967 }
968
969 #[tokio::test]
970 async fn test_update_flow_metadata_diff_flownode() {
971 let mem_kv = Arc::new(MemoryKvBackend::default());
972 let flow_metadata_manager = FlowMetadataManager::new(mem_kv.clone());
973 let flow_id = 10;
974 let flow_value = test_flow_info_value(
975 "flow",
976 [(0u32, 1u64), (1u32, 2u64)].into(),
977 vec![1024, 1025, 1026],
978 );
979 let flow_routes = vec![
980 (
981 0u32,
982 FlowRouteValue {
983 peer: Peer::empty(1),
984 },
985 ),
986 (
987 1,
988 FlowRouteValue {
989 peer: Peer::empty(2),
990 },
991 ),
992 ];
993 flow_metadata_manager
994 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
995 .await
996 .unwrap();
997
998 let new_flow_value = {
999 let mut tmp = flow_value.clone();
1000 tmp.raw_sql = "new".to_string();
1001 tmp.flownode_ids = [(0, 3u64), (1, 4u64)].into();
1003 tmp
1004 };
1005 let new_flow_routes = vec![
1006 (
1007 0u32,
1008 FlowRouteValue {
1009 peer: Peer::empty(3),
1010 },
1011 ),
1012 (
1013 1,
1014 FlowRouteValue {
1015 peer: Peer::empty(4),
1016 },
1017 ),
1018 ];
1019
1020 flow_metadata_manager
1022 .update_flow_metadata(
1023 flow_id,
1024 &DeserializedValueWithBytes::from_inner(flow_value.clone()),
1025 &new_flow_value,
1026 new_flow_routes.clone(),
1027 )
1028 .await
1029 .unwrap();
1030
1031 let got = flow_metadata_manager
1032 .flow_info_manager()
1033 .get(flow_id)
1034 .await
1035 .unwrap()
1036 .unwrap();
1037 let routes = flow_metadata_manager
1038 .flow_route_manager()
1039 .routes(flow_id)
1040 .await
1041 .unwrap();
1042 assert_eq!(
1043 routes,
1044 vec![
1045 (
1046 FlowRouteKey::new(flow_id, 0),
1047 FlowRouteValue {
1048 peer: Peer::empty(3),
1049 },
1050 ),
1051 (
1052 FlowRouteKey::new(flow_id, 1),
1053 FlowRouteValue {
1054 peer: Peer::empty(4),
1055 },
1056 ),
1057 ]
1058 );
1059 assert_eq!(got, new_flow_value);
1060
1061 let flows = flow_metadata_manager
1062 .flownode_flow_manager()
1063 .flows(1)
1064 .try_collect::<Vec<_>>()
1065 .await
1066 .unwrap();
1067 assert_eq!(flows, vec![]);
1069
1070 let flows = flow_metadata_manager
1071 .flownode_flow_manager()
1072 .flows(3)
1073 .try_collect::<Vec<_>>()
1074 .await
1075 .unwrap();
1076 assert_eq!(flows, vec![(flow_id, 0)]);
1077
1078 for table_id in [1024, 1025, 1026] {
1079 let nodes = flow_metadata_manager
1080 .table_flow_manager()
1081 .flows(table_id)
1082 .await
1083 .unwrap();
1084 assert_eq!(
1085 nodes,
1086 vec![
1087 (
1088 TableFlowKey::new(table_id, 3, flow_id, 0),
1089 TableFlowValue {
1090 peer: Peer::empty(3)
1091 }
1092 ),
1093 (
1094 TableFlowKey::new(table_id, 4, flow_id, 1),
1095 TableFlowValue {
1096 peer: Peer::empty(4)
1097 }
1098 )
1099 ]
1100 );
1101 }
1102 }
1103
1104 #[tokio::test]
1105 async fn test_update_flow_metadata_flow_replace_diff_id_err() {
1106 let mem_kv = Arc::new(MemoryKvBackend::default());
1107 let flow_metadata_manager = FlowMetadataManager::new(mem_kv);
1108 let flow_id = 10;
1109 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024, 1025, 1026]);
1110 let flow_routes = vec![
1111 (
1112 1u32,
1113 FlowRouteValue {
1114 peer: Peer::empty(1),
1115 },
1116 ),
1117 (
1118 2,
1119 FlowRouteValue {
1120 peer: Peer::empty(2),
1121 },
1122 ),
1123 ];
1124 flow_metadata_manager
1125 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
1126 .await
1127 .unwrap();
1128 flow_metadata_manager
1130 .update_flow_metadata(
1131 flow_id,
1132 &DeserializedValueWithBytes::from_inner(flow_value.clone()),
1133 &flow_value,
1134 flow_routes.clone(),
1135 )
1136 .await
1137 .unwrap();
1138 let err = flow_metadata_manager
1140 .update_flow_metadata(
1141 flow_id + 1,
1142 &DeserializedValueWithBytes::from_inner(flow_value.clone()),
1143 &flow_value,
1144 flow_routes,
1145 )
1146 .await
1147 .unwrap_err();
1148 assert_matches!(err, error::Error::Unexpected { .. });
1149 assert!(
1150 err.to_string()
1151 .contains("Reads different flow id when updating flow")
1152 );
1153 }
1154
1155 #[tokio::test]
1156 async fn test_update_flow_metadata_unexpected_err_prev_value_diff() {
1157 let mem_kv = Arc::new(MemoryKvBackend::default());
1158 let flow_metadata_manager = FlowMetadataManager::new(mem_kv);
1159 let flow_id = 10;
1160 let catalog_name = "greptime";
1161 let flow_value = test_flow_info_value("flow", [(0, 1u64)].into(), vec![1024, 1025, 1026]);
1162 let flow_routes = vec![
1163 (
1164 1u32,
1165 FlowRouteValue {
1166 peer: Peer::empty(1),
1167 },
1168 ),
1169 (
1170 2,
1171 FlowRouteValue {
1172 peer: Peer::empty(2),
1173 },
1174 ),
1175 ];
1176 flow_metadata_manager
1177 .create_flow_metadata(flow_id, flow_value.clone(), flow_routes.clone())
1178 .await
1179 .unwrap();
1180 let another_sink_table_name = TableName {
1182 catalog_name: catalog_name.to_string(),
1183 schema_name: "my_schema".to_string(),
1184 table_name: "another_sink_table".to_string(),
1185 };
1186 let flow_value = FlowInfoValue {
1187 catalog_name: "greptime".to_string(),
1188 query_context: None,
1189 flow_name: "flow".to_string(),
1190 source_table_ids: vec![1024, 1025, 1026],
1191 all_source_table_names: vec![],
1192 unresolved_source_table_names: vec![],
1193 sink_table_name: another_sink_table_name,
1194 flownode_ids: [(0, 1u64)].into(),
1195 raw_sql: "raw".to_string(),
1196 expire_after: Some(300),
1197 eval_interval_secs: None,
1198 comment: "hi".to_string(),
1199 options: Default::default(),
1200 status: FlowStatus::Active,
1201 created_time: chrono::Utc::now(),
1202 updated_time: chrono::Utc::now(),
1203 eval_schedule: None,
1204 };
1205 let err = flow_metadata_manager
1206 .update_flow_metadata(
1207 flow_id,
1208 &DeserializedValueWithBytes::from_inner(flow_value.clone()),
1209 &flow_value,
1210 flow_routes.clone(),
1211 )
1212 .await
1213 .unwrap_err();
1214 assert!(
1215 err.to_string().contains("Reads the different value"),
1216 "error: {:?}",
1217 err
1218 );
1219 }
1220
1221 #[test]
1222 fn test_build_replace_ops() {
1223 let ops = build_replace_ops(
1224 vec![b"a".to_vec(), b"b".to_vec()],
1225 vec![
1226 (b"b".to_vec(), b"1".to_vec()),
1227 (b"c".to_vec(), b"2".to_vec()),
1228 ],
1229 );
1230 assert_eq!(
1231 ops,
1232 vec![
1233 TxnOp::Delete(b"a".to_vec()),
1234 TxnOp::Put(b"b".to_vec(), b"1".to_vec()),
1235 TxnOp::Put(b"c".to_vec(), b"2".to_vec()),
1236 ]
1237 );
1238 }
1239
1240 async fn build_kv_backend() -> KvBackendRef {
1243 let endpoints = std::env::var("GT_ETCD_ENDPOINTS").unwrap_or_default();
1244 if endpoints.is_empty() {
1245 return Arc::new(MemoryKvBackend::default());
1246 }
1247 let endpoints = endpoints.split(',').collect::<Vec<_>>();
1248 let backend = EtcdStore::with_endpoints(endpoints, 128).await.unwrap();
1249 let chroot = format!("test_update_flow_metadata/{}/", Uuid::new_v4());
1250 Arc::new(ChrootKvBackend::new(chroot.into(), backend))
1251 }
1252
1253 async fn assert_flow_metadata(
1254 manager: &FlowMetadataManager,
1255 flow_id: FlowId,
1256 flow_info: &FlowInfoValue,
1257 ) {
1258 let got = manager.flow_info_manager().get(flow_id).await.unwrap();
1259 assert_eq!(got.as_ref(), Some(flow_info));
1260
1261 let routes = manager.flow_route_manager().routes(flow_id).await.unwrap();
1262 let expected_routes = flow_info
1263 .flownode_ids()
1264 .iter()
1265 .map(|(partition_id, flownode_id)| {
1266 (
1267 FlowRouteKey::new(flow_id, *partition_id),
1268 FlowRouteValue {
1269 peer: Peer::empty(*flownode_id),
1270 },
1271 )
1272 })
1273 .collect::<Vec<_>>();
1274 assert_eq!(routes, expected_routes);
1275
1276 for flownode_id in 1..=4 {
1277 let flows = manager
1278 .flownode_flow_manager()
1279 .flows(flownode_id)
1280 .try_collect::<Vec<_>>()
1281 .await
1282 .unwrap();
1283 let expected = flow_info
1284 .flownode_ids()
1285 .iter()
1286 .filter(|(_, id)| **id == flownode_id)
1287 .map(|(partition_id, _)| (flow_id, *partition_id))
1288 .collect::<Vec<_>>();
1289 assert_eq!(flows, expected, "flownode {flownode_id}");
1290 }
1291
1292 for table_id in 1024..=1027 {
1293 let flows = manager
1294 .table_flow_manager()
1295 .flows(table_id)
1296 .await
1297 .unwrap()
1298 .into_iter()
1299 .map(|(key, _)| (key.flownode_id(), key.partition_id()))
1300 .collect::<Vec<_>>();
1301 let expected = if flow_info.source_table_ids().contains(&table_id) {
1302 flow_info
1303 .flownode_ids()
1304 .iter()
1305 .map(|(partition_id, flownode_id)| (*flownode_id, *partition_id))
1306 .collect()
1307 } else {
1308 vec![]
1309 };
1310 assert_eq!(flows, expected, "table {table_id}");
1311 }
1312 }
1313
1314 #[tokio::test]
1315 async fn test_update_flow_metadata_with_overlapping_keys() {
1316 let flow_metadata_manager = FlowMetadataManager::new(build_kv_backend().await);
1317 let flow_id = 10;
1318 let to_routes = |flow_info: &FlowInfoValue| {
1319 flow_info
1320 .flownode_ids()
1321 .iter()
1322 .map(|(partition_id, flownode_id)| {
1323 (
1324 *partition_id,
1325 FlowRouteValue {
1326 peer: Peer::empty(*flownode_id),
1327 },
1328 )
1329 })
1330 .collect::<Vec<_>>()
1331 };
1332
1333 let mut current =
1334 test_flow_info_value("flow", [(0, 1u64), (1, 2u64)].into(), vec![1024, 1025]);
1335 flow_metadata_manager
1336 .create_flow_metadata(flow_id, current.clone(), to_routes(¤t))
1337 .await
1338 .unwrap();
1339 assert_flow_metadata(&flow_metadata_manager, flow_id, ¤t).await;
1340
1341 let updates = [
1342 ([(0, 1u64), (1, 2u64)].into(), vec![1024, 1025]),
1344 ([(0, 1u64), (1, 3u64)].into(), vec![1025, 1026]),
1346 ([(2, 4u64)].into(), vec![1027]),
1348 ];
1349 for (i, (flownode_ids, source_table_ids)) in updates.into_iter().enumerate() {
1350 let mut new_flow_info = current.clone();
1351 new_flow_info.raw_sql = format!("update {i}");
1352 new_flow_info.flownode_ids = flownode_ids;
1353 new_flow_info.source_table_ids = source_table_ids;
1354 flow_metadata_manager
1355 .update_flow_metadata(
1356 flow_id,
1357 &DeserializedValueWithBytes::from_inner(current.clone()),
1358 &new_flow_info,
1359 to_routes(&new_flow_info),
1360 )
1361 .await
1362 .unwrap();
1363 assert_flow_metadata(&flow_metadata_manager, flow_id, &new_flow_info).await;
1364 current = new_flow_info;
1365 }
1366 }
1367}