Skip to main content

reddb_server/application/
ports_impls_tree.rs

1use super::*;
2use crate::application::entity::metadata_to_json;
3use crate::storage::query::ast::{
4    CreateTreeQuery, DropTreeQuery, TreeCommand, TreeNodeSpec, TreePosition,
5};
6
7fn api_tree_query(label: &str, collection: &str, tree: &str) -> String {
8    format!("api.{label}({collection}.{tree})")
9}
10
11fn tree_position(position: crate::application::TreePositionInput) -> TreePosition {
12    match position {
13        crate::application::TreePositionInput::First => TreePosition::First,
14        crate::application::TreePositionInput::Last => TreePosition::Last,
15        crate::application::TreePositionInput::Index(index) => TreePosition::Index(index),
16    }
17}
18
19fn tree_node_spec(input: crate::application::TreeNodeInput) -> RedDBResult<TreeNodeSpec> {
20    let metadata = input
21        .metadata
22        .into_iter()
23        .map(|(key, value)| {
24            let json = metadata_to_json(&crate::storage::unified::Metadata::with_fields(
25                [(key.clone(), value)].into_iter().collect(),
26            ));
27            let value = json
28                .get(&key)
29                .ok_or_else(|| {
30                    crate::RedDBError::Query(format!(
31                        "failed to convert tree metadata field '{}'",
32                        key
33                    ))
34                })
35                .and_then(crate::application::entity::json_to_storage_value)?;
36            Ok((key, value))
37        })
38        .collect::<RedDBResult<Vec<_>>>()?;
39
40    Ok(TreeNodeSpec {
41        label: input.label,
42        node_type: input.node_type,
43        properties: input.properties,
44        metadata,
45        max_children: input.max_children,
46    })
47}
48
49impl RuntimeTreePort for RedDBRuntime {
50    fn create_tree(&self, input: CreateTreeInput) -> RedDBResult<RuntimeQueryResult> {
51        let raw_query = api_tree_query("create_tree", &input.collection, &input.name);
52        let query = CreateTreeQuery {
53            collection: input.collection,
54            name: input.name,
55            root: tree_node_spec(input.root)?,
56            default_max_children: input.default_max_children,
57            if_not_exists: input.if_not_exists,
58        };
59        RedDBRuntime::execute_create_tree(self, &raw_query, &query)
60    }
61
62    fn drop_tree(&self, input: DropTreeInput) -> RedDBResult<RuntimeQueryResult> {
63        let raw_query = api_tree_query("drop_tree", &input.collection, &input.name);
64        let query = DropTreeQuery {
65            collection: input.collection,
66            name: input.name,
67            if_exists: input.if_exists,
68        };
69        RedDBRuntime::execute_drop_tree(self, &raw_query, &query)
70    }
71
72    fn insert_tree_node(&self, input: InsertTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
73        let raw_query = api_tree_query("tree_insert", &input.collection, &input.tree_name);
74        let command = TreeCommand::Insert {
75            collection: input.collection,
76            tree_name: input.tree_name,
77            parent_id: input.parent_id,
78            node: tree_node_spec(input.node)?,
79            position: tree_position(input.position),
80        };
81        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
82    }
83
84    fn move_tree_node(&self, input: MoveTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
85        let raw_query = api_tree_query("tree_move", &input.collection, &input.tree_name);
86        let command = TreeCommand::Move {
87            collection: input.collection,
88            tree_name: input.tree_name,
89            node_id: input.node_id,
90            parent_id: input.parent_id,
91            position: tree_position(input.position),
92        };
93        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
94    }
95
96    fn delete_tree_node(&self, input: DeleteTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
97        let raw_query = api_tree_query("tree_delete", &input.collection, &input.tree_name);
98        let command = TreeCommand::Delete {
99            collection: input.collection,
100            tree_name: input.tree_name,
101            node_id: input.node_id,
102        };
103        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
104    }
105
106    fn validate_tree(&self, input: ValidateTreeInput) -> RedDBResult<RuntimeQueryResult> {
107        let raw_query = api_tree_query("tree_validate", &input.collection, &input.tree_name);
108        let command = TreeCommand::Validate {
109            collection: input.collection,
110            tree_name: input.tree_name,
111        };
112        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
113    }
114
115    fn rebalance_tree(&self, input: RebalanceTreeInput) -> RedDBResult<RuntimeQueryResult> {
116        let raw_query = api_tree_query("tree_rebalance", &input.collection, &input.tree_name);
117        let command = TreeCommand::Rebalance {
118            collection: input.collection,
119            tree_name: input.tree_name,
120            dry_run: input.dry_run,
121        };
122        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
123    }
124}