reddb-io-server 1.2.0

RedDB server-side engine: storage, runtime, replication, MCP, AI, and the gRPC/HTTP/RedWire/PG-wire dispatchers. Re-exported by the umbrella `reddb` crate.
Documentation
use super::*;
use crate::application::entity::metadata_to_json;
use crate::storage::query::ast::{
    CreateTreeQuery, DropTreeQuery, TreeCommand, TreeNodeSpec, TreePosition,
};

fn api_tree_query(label: &str, collection: &str, tree: &str) -> String {
    format!("api.{label}({collection}.{tree})")
}

fn tree_position(position: crate::application::TreePositionInput) -> TreePosition {
    match position {
        crate::application::TreePositionInput::First => TreePosition::First,
        crate::application::TreePositionInput::Last => TreePosition::Last,
        crate::application::TreePositionInput::Index(index) => TreePosition::Index(index),
    }
}

fn tree_node_spec(input: crate::application::TreeNodeInput) -> RedDBResult<TreeNodeSpec> {
    let metadata = input
        .metadata
        .into_iter()
        .map(|(key, value)| {
            let json = metadata_to_json(&crate::storage::unified::Metadata::with_fields(
                [(key.clone(), value)].into_iter().collect(),
            ));
            let value = json
                .get(&key)
                .ok_or_else(|| {
                    crate::RedDBError::Query(format!(
                        "failed to convert tree metadata field '{}'",
                        key
                    ))
                })
                .and_then(crate::application::entity::json_to_storage_value)?;
            Ok((key, value))
        })
        .collect::<RedDBResult<Vec<_>>>()?;

    Ok(TreeNodeSpec {
        label: input.label,
        node_type: input.node_type,
        properties: input.properties,
        metadata,
        max_children: input.max_children,
    })
}

impl RuntimeTreePort for RedDBRuntime {
    fn create_tree(&self, input: CreateTreeInput) -> RedDBResult<RuntimeQueryResult> {
        let raw_query = api_tree_query("create_tree", &input.collection, &input.name);
        let query = CreateTreeQuery {
            collection: input.collection,
            name: input.name,
            root: tree_node_spec(input.root)?,
            default_max_children: input.default_max_children,
            if_not_exists: input.if_not_exists,
        };
        RedDBRuntime::execute_create_tree(self, &raw_query, &query)
    }

    fn drop_tree(&self, input: DropTreeInput) -> RedDBResult<RuntimeQueryResult> {
        let raw_query = api_tree_query("drop_tree", &input.collection, &input.name);
        let query = DropTreeQuery {
            collection: input.collection,
            name: input.name,
            if_exists: input.if_exists,
        };
        RedDBRuntime::execute_drop_tree(self, &raw_query, &query)
    }

    fn insert_tree_node(&self, input: InsertTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
        let raw_query = api_tree_query("tree_insert", &input.collection, &input.tree_name);
        let command = TreeCommand::Insert {
            collection: input.collection,
            tree_name: input.tree_name,
            parent_id: input.parent_id,
            node: tree_node_spec(input.node)?,
            position: tree_position(input.position),
        };
        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
    }

    fn move_tree_node(&self, input: MoveTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
        let raw_query = api_tree_query("tree_move", &input.collection, &input.tree_name);
        let command = TreeCommand::Move {
            collection: input.collection,
            tree_name: input.tree_name,
            node_id: input.node_id,
            parent_id: input.parent_id,
            position: tree_position(input.position),
        };
        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
    }

    fn delete_tree_node(&self, input: DeleteTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
        let raw_query = api_tree_query("tree_delete", &input.collection, &input.tree_name);
        let command = TreeCommand::Delete {
            collection: input.collection,
            tree_name: input.tree_name,
            node_id: input.node_id,
        };
        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
    }

    fn validate_tree(&self, input: ValidateTreeInput) -> RedDBResult<RuntimeQueryResult> {
        let raw_query = api_tree_query("tree_validate", &input.collection, &input.tree_name);
        let command = TreeCommand::Validate {
            collection: input.collection,
            tree_name: input.tree_name,
        };
        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
    }

    fn rebalance_tree(&self, input: RebalanceTreeInput) -> RedDBResult<RuntimeQueryResult> {
        let raw_query = api_tree_query("tree_rebalance", &input.collection, &input.tree_name);
        let command = TreeCommand::Rebalance {
            collection: input.collection,
            tree_name: input.tree_name,
            dry_run: input.dry_run,
        };
        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
    }
}