Skip to main content

common_meta/key/
flow.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
15pub 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
50/// Returns a flow metadata key under the `__flow` scope.
51pub fn scoped_flow_key(inner_key: &str) -> String {
52    format!("{FLOW_KEY_PREFIX}/{inner_key}")
53}
54
55/// Returns a flow metadata key prefix under the `__flow` scope.
56pub fn scoped_flow_key_prefix(inner_prefix: &str) -> String {
57    scoped_flow_key(inner_prefix)
58}
59
60/// Returns the full prefix of flow info keys.
61pub fn flow_info_key_prefix() -> String {
62    scoped_flow_key_prefix(flow_info::FLOW_INFO_KEY_PREFIX)
63}
64
65/// Returns the full prefix of flow name keys.
66pub fn flow_name_key_prefix() -> String {
67    scoped_flow_key_prefix(flow_name::FLOW_NAME_KEY_PREFIX)
68}
69
70/// Returns the full prefix of flow route keys.
71pub fn flow_route_key_prefix() -> String {
72    scoped_flow_key_prefix(flow_route::FLOW_ROUTE_KEY_PREFIX)
73}
74
75/// Returns the full prefix of table flow keys.
76pub fn table_flow_key_prefix() -> String {
77    scoped_flow_key_prefix(table_flow::TABLE_FLOW_KEY_PREFIX)
78}
79
80/// Returns the full prefix of flownode flow keys.
81pub fn flownode_flow_key_prefix() -> String {
82    scoped_flow_key_prefix(flownode_flow::FLOWNODE_FLOW_KEY_PREFIX)
83}
84
85/// Returns the full key of flow state.
86pub fn flow_state_full_key() -> String {
87    scoped_flow_key(flow_state::FLOW_STATE_KEY)
88}
89
90/// The key of `__flow/` scope.
91#[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    /// Returns a new [FlowScoped] key.
108    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
137/// Builds txn ops that replace the `old_keys` with the `new_kvs`.
138///
139/// Only deletes the old keys absent from `new_kvs`: etcd rejects a txn that
140/// writes the same key more than once ("duplicate key given in txn request").
141fn 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
164/// The manager of metadata, provides ability to:
165/// - Create metadata of the flow.
166/// - Retrieve metadata of the flow.
167/// - Delete metadata of the flow.
168pub 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    /// only metasrv have access to itself's memory backend, so for other case it should be None
175    flow_state_manager: Option<FlowStateManager>,
176    kv_backend: KvBackendRef,
177}
178
179impl FlowMetadataManager {
180    /// Returns a new [`FlowMetadataManager`].
181    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    /// Returns the [`FlowNameManager`].
194    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    /// Returns the [`FlowInfoManager`].
203    pub fn flow_info_manager(&self) -> &FlowInfoManager {
204        &self.flow_info_manager
205    }
206
207    /// Returns the [`FlowRouteManager`].
208    pub fn flow_route_manager(&self) -> &FlowRouteManager {
209        &self.flow_route_manager
210    }
211
212    /// Returns the [`FlownodeFlowManager`].
213    pub fn flownode_flow_manager(&self) -> &FlownodeFlowManager {
214        &self.flownode_flow_manager
215    }
216
217    /// Returns the [`TableFlowManager`].
218    pub fn table_flow_manager(&self) -> &TableFlowManager {
219        &self.table_flow_manager
220    }
221
222    /// Returns a best-effort mapping from flow partition to flownode address.
223    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    /// Creates metadata for flow and returns an error if different metadata exists.
239    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    /// Update metadata for flow and returns an error if old metadata IS NOT exists.
326    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        // Builds flow name key
431        let flow_name = FlowNameKey::new(&flow_value.catalog_name, &flow_value.flow_name);
432        keys.push(flow_name.to_bytes());
433
434        // Builds flow value key
435        let flow_info_key = FlowInfoKey::new(flow_id);
436        keys.push(flow_info_key.to_bytes());
437
438        // Builds flownode flow keys & table flow keys
439        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    /// Deletes metadata for table **permanently**.
455    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        // Creates again.
599        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        // Creates again
767        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        // Creates again.
800        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        // Destroys again
853        flow_metadata_manager
854            .destroy_flow_metadata(flow_id, &flow_value)
855            .await
856            .unwrap();
857        // Ensures all keys are deleted
858        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        // Update flow instead
897        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            // move to different flownodes
1002            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        // Update flow instead
1021        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        // should moved to different flownode
1068        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        // update again with same flow id
1129        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        // update again with wrong flow id, expected error
1139        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        // Creates again.
1181        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    /// Returns an etcd backend isolated by a chroot if `GT_ETCD_ENDPOINTS` is set,
1241    /// because only etcd rejects txns that write the same key more than once.
1242    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(&current))
1337            .await
1338            .unwrap();
1339        assert_flow_metadata(&flow_metadata_manager, flow_id, &current).await;
1340
1341        let updates = [
1342            // Unchanged partitions, flownodes and source tables.
1343            ([(0, 1u64), (1, 2u64)].into(), vec![1024, 1025]),
1344            // Partially overlapping flownodes and source tables.
1345            ([(0, 1u64), (1, 3u64)].into(), vec![1025, 1026]),
1346            // Fully changed partitions, flownodes and source tables.
1347            ([(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}