leptos_sync_core/crdt/tree/
add_wins.rs

1//! Add-Wins Tree CRDT implementation
2
3use super::super::{CRDT, Mergeable, ReplicaId};
4use super::{config::TreeConfig, error::TreeError, types::{NodeId, TreeNode}};
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8/// Add-Wins Tree CRDT implementation
9/// 
10/// This implementation ensures that nodes are never completely lost.
11/// Deleted nodes are marked as deleted but preserved for potential recovery.
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct AddWinsTree<T> {
14    /// Configuration
15    config: TreeConfig,
16    /// Nodes in the tree
17    nodes: HashMap<NodeId, TreeNode<T>>,
18    /// Replica ID for this instance
19    replica: ReplicaId,
20}
21
22impl<T: Clone + PartialEq + Eq + Send + Sync> AddWinsTree<T> {
23    /// Create a new Add-Wins tree
24    pub fn new(replica: ReplicaId) -> Self {
25        Self {
26            config: TreeConfig::default(),
27            nodes: HashMap::new(),
28            replica,
29        }
30    }
31
32    /// Create with custom configuration
33    pub fn with_config(replica: ReplicaId, config: TreeConfig) -> Self {
34        Self {
35            config,
36            nodes: HashMap::new(),
37            replica,
38        }
39    }
40
41    /// Add a root node to the tree
42    pub fn add_root(&mut self, value: T, timestamp: u64) -> NodeId {
43        let node = TreeNode::new(value, self.replica, timestamp);
44        let id = node.id.clone();
45        self.nodes.insert(id.clone(), node);
46        id
47    }
48
49    /// Add a child node
50    pub fn add_child(&mut self, parent_id: &NodeId, value: T, timestamp: u64) -> Result<NodeId, TreeError> {
51        if !self.nodes.contains_key(parent_id) {
52            return Err(TreeError::new("Parent node not found".to_string()));
53        }
54
55        let node = TreeNode::new_child(value, self.replica, timestamp, parent_id.clone());
56        let id = node.id.clone();
57        
58        // Add the child node
59        self.nodes.insert(id.clone(), node);
60        
61        // Update parent's children list
62        if let Some(parent) = self.nodes.get_mut(parent_id) {
63            parent.add_child(id.clone());
64        }
65        
66        Ok(id)
67    }
68
69    /// Update an existing node
70    pub fn update(&mut self, id: &NodeId, value: T, timestamp: u64) -> Result<(), TreeError> {
71        if let Some(node) = self.nodes.get_mut(id) {
72            node.value = value;
73            node.mark_modified(self.replica, timestamp);
74            Ok(())
75        } else {
76            Err(TreeError::new("Node not found".to_string()))
77        }
78    }
79
80    /// Mark a node as deleted
81    pub fn remove(&mut self, id: &NodeId, timestamp: u64) -> Result<(), TreeError> {
82        if let Some(node) = self.nodes.get_mut(id) {
83            node.mark_deleted(self.replica, timestamp);
84            Ok(())
85        } else {
86            Err(TreeError::new("Node not found".to_string()))
87        }
88    }
89
90    /// Move a node to a new parent
91    pub fn move_node(&mut self, id: &NodeId, new_parent_id: &NodeId) -> Result<(), TreeError> {
92        if !self.nodes.contains_key(id) || !self.nodes.contains_key(new_parent_id) {
93            return Err(TreeError::new("Node not found".to_string()));
94        }
95
96        // Get the old parent ID first
97        let old_parent_id = self.nodes.get(id).and_then(|node| node.parent.clone());
98        
99        // Remove from old parent
100        if let Some(old_parent_id) = old_parent_id {
101            if let Some(old_parent) = self.nodes.get_mut(&old_parent_id) {
102                old_parent.remove_child(id);
103            }
104        }
105        
106        // Update the node's parent reference
107        if let Some(node) = self.nodes.get_mut(id) {
108            node.parent = Some(new_parent_id.clone());
109        }
110        
111        // Add to new parent
112        if let Some(new_parent) = self.nodes.get_mut(new_parent_id) {
113            new_parent.add_child(id.clone());
114        }
115        
116        Ok(())
117    }
118
119    /// Get a node by ID
120    pub fn get(&self, id: &NodeId) -> Option<&TreeNode<T>> {
121        self.nodes.get(id)
122    }
123
124    /// Get all visible nodes (not deleted)
125    pub fn visible_nodes(&self) -> Vec<&TreeNode<T>> {
126        self.nodes
127            .values()
128            .filter(|n| !n.metadata.deleted)
129            .collect()
130    }
131
132    /// Get all nodes including deleted ones
133    pub fn all_nodes(&self) -> Vec<&TreeNode<T>> {
134        self.nodes.values().collect()
135    }
136
137    /// Get root nodes
138    pub fn roots(&self) -> Vec<&TreeNode<T>> {
139        self.nodes
140            .values()
141            .filter(|n| n.parent.is_none() && !n.metadata.deleted)
142            .collect()
143    }
144
145    /// Get children of a node
146    pub fn children(&self, id: &NodeId) -> Vec<&TreeNode<T>> {
147        if let Some(node) = self.nodes.get(id) {
148            node.children
149                .iter()
150                .filter_map(|child_id| self.nodes.get(child_id))
151                .filter(|n| !n.metadata.deleted)
152                .collect()
153        } else {
154            Vec::new()
155        }
156    }
157
158    /// Get descendants of a node (recursive)
159    pub fn descendants(&self, id: &NodeId) -> Vec<&TreeNode<T>> {
160        let mut descendants = Vec::new();
161        self.collect_descendants(id, &mut descendants);
162        descendants
163    }
164    
165    fn collect_descendants<'a>(&'a self, id: &NodeId, descendants: &mut Vec<&'a TreeNode<T>>) {
166        if let Some(node) = self.nodes.get(id) {
167            if !node.metadata.deleted {
168                for child_id in &node.children {
169                    if let Some(child_node) = self.nodes.get(child_id) {
170                        if !child_node.metadata.deleted {
171                            descendants.push(child_node);
172                            self.collect_descendants(child_id, descendants);
173                        }
174                    }
175                }
176            }
177        }
178    }
179
180    /// Check if the tree contains a node
181    pub fn contains(&self, id: &NodeId) -> bool {
182        self.nodes.contains_key(id)
183    }
184
185    /// Get the number of visible nodes
186    pub fn len(&self) -> usize {
187        self.visible_nodes().len()
188    }
189
190    /// Check if the tree is empty
191    pub fn is_empty(&self) -> bool {
192        self.len() == 0
193    }
194
195    /// Clear all nodes
196    pub fn clear(&mut self) {
197        self.nodes.clear();
198    }
199
200    /// Get the configuration
201    pub fn config(&self) -> &TreeConfig {
202        &self.config
203    }
204}
205
206impl<T: Clone + PartialEq + Eq + Send + Sync> CRDT for AddWinsTree<T> {
207    fn replica_id(&self) -> &ReplicaId {
208        &self.replica
209    }
210}
211
212impl<T: Clone + PartialEq + Eq + Send + Sync> Mergeable for AddWinsTree<T> {
213    type Error = TreeError;
214
215    fn merge(&mut self, other: &Self) -> Result<(), Self::Error> {
216        for (id, node) in &other.nodes {
217            match self.nodes.get(id) {
218                Some(existing) => {
219                    // Conflict resolution: later timestamp wins
220                    if node.metadata.modified_at > existing.metadata.modified_at {
221                        self.nodes.insert(id.clone(), node.clone());
222                    }
223                }
224                None => {
225                    // New node, add it
226                    self.nodes.insert(id.clone(), node.clone());
227                }
228            }
229        }
230        Ok(())
231    }
232
233    fn has_conflict(&self, other: &Self) -> bool {
234        for (id, node) in &other.nodes {
235            if let Some(existing) = self.nodes.get(id) {
236                // Check for conflicts: same timestamp but different replica
237                if node.metadata.modified_at == existing.metadata.modified_at
238                    && node.metadata.last_modified_by != existing.metadata.last_modified_by
239                {
240                    return true;
241                }
242            }
243        }
244        false
245    }
246}