leptos_sync_core/reliability/data_integrity/
version.rs

1//! Version verification for data consistency
2
3use super::super::IntegrityError;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7/// Configuration for version verification
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct VersionConfig {
10    /// Whether to verify versions on read
11    pub verify_on_read: bool,
12    /// Whether to increment versions on write
13    pub increment_on_write: bool,
14    /// Maximum version difference allowed
15    pub max_version_diff: u64,
16}
17
18impl Default for VersionConfig {
19    fn default() -> Self {
20        Self {
21            verify_on_read: true,
22            increment_on_write: true,
23            max_version_diff: 1,
24        }
25    }
26}
27
28/// Version verifier for data consistency
29#[derive(Debug, Clone)]
30pub struct VersionVerifier {
31    /// Configuration
32    config: VersionConfig,
33    /// Version tracking for data items
34    versions: HashMap<String, u64>,
35}
36
37impl VersionVerifier {
38    /// Create a new version verifier
39    pub fn new() -> Self {
40        Self {
41            config: VersionConfig::default(),
42            versions: HashMap::new(),
43        }
44    }
45    
46    /// Create a new version verifier with configuration
47    pub fn with_config(config: VersionConfig) -> Self {
48        Self {
49            config,
50            versions: HashMap::new(),
51        }
52    }
53    
54    /// Get current version for a data item
55    pub fn get_version(&self, key: &str) -> u64 {
56        self.versions.get(key).copied().unwrap_or(0)
57    }
58    
59    /// Increment version for a data item
60    pub fn increment_version(&mut self, key: &str) -> u64 {
61        let current_version = self.get_version(key);
62        let new_version = current_version + 1;
63        self.versions.insert(key.to_string(), new_version);
64        new_version
65    }
66    
67    /// Verify version consistency
68    pub fn verify_version(&self, key: &str, expected_version: u64) -> Result<bool, IntegrityError> {
69        let current_version = self.get_version(key);
70        let version_diff = if current_version > expected_version {
71            current_version - expected_version
72        } else {
73            expected_version - current_version
74        };
75        
76        if version_diff > self.config.max_version_diff {
77            return Err(IntegrityError::VersionMismatch {
78                key: key.to_string(),
79                expected: expected_version,
80                actual: current_version,
81            });
82        }
83        
84        Ok(true)
85    }
86    
87    /// Set version for a data item
88    pub fn set_version(&mut self, key: &str, version: u64) {
89        self.versions.insert(key.to_string(), version);
90    }
91    
92    /// Remove version tracking for a data item
93    pub fn remove_version(&mut self, key: &str) {
94        self.versions.remove(key);
95    }
96    
97    /// Get all tracked versions
98    pub fn get_all_versions(&self) -> &HashMap<String, u64> {
99        &self.versions
100    }
101    
102    /// Clear all version tracking
103    pub fn clear_versions(&mut self) {
104        self.versions.clear();
105    }
106    
107    /// Get configuration
108    pub fn config(&self) -> &VersionConfig {
109        &self.config
110    }
111}
112
113impl Default for VersionVerifier {
114    fn default() -> Self {
115        Self::new()
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122    
123    #[test]
124    fn test_version_verifier_creation() {
125        let verifier = VersionVerifier::new();
126        assert!(verifier.config().verify_on_read);
127        assert!(verifier.config().increment_on_write);
128        assert_eq!(verifier.config().max_version_diff, 1);
129    }
130    
131    #[test]
132    fn test_version_verifier_with_config() {
133        let config = VersionConfig {
134            verify_on_read: false,
135            increment_on_write: true,
136            max_version_diff: 5,
137        };
138        let verifier = VersionVerifier::with_config(config.clone());
139        assert!(!verifier.config().verify_on_read);
140        assert!(verifier.config().increment_on_write);
141        assert_eq!(verifier.config().max_version_diff, 5);
142    }
143    
144    #[test]
145    fn test_get_version() {
146        let verifier = VersionVerifier::new();
147        assert_eq!(verifier.get_version("test_key"), 0);
148    }
149    
150    #[test]
151    fn test_increment_version() {
152        let mut verifier = VersionVerifier::new();
153        let key = "test_key";
154        
155        assert_eq!(verifier.get_version(key), 0);
156        assert_eq!(verifier.increment_version(key), 1);
157        assert_eq!(verifier.get_version(key), 1);
158        assert_eq!(verifier.increment_version(key), 2);
159        assert_eq!(verifier.get_version(key), 2);
160    }
161    
162    #[test]
163    fn test_verify_version() {
164        let mut verifier = VersionVerifier::new();
165        let key = "test_key";
166        
167        // Set version to 5
168        verifier.set_version(key, 5);
169        
170        // Verify exact match
171        assert!(verifier.verify_version(key, 5).unwrap());
172        
173        // Verify within tolerance
174        assert!(verifier.verify_version(key, 4).unwrap());
175        assert!(verifier.verify_version(key, 6).unwrap());
176        
177        // Verify outside tolerance
178        assert!(verifier.verify_version(key, 3).is_err());
179        assert!(verifier.verify_version(key, 7).is_err());
180    }
181    
182    #[test]
183    fn test_set_version() {
184        let mut verifier = VersionVerifier::new();
185        let key = "test_key";
186        
187        verifier.set_version(key, 42);
188        assert_eq!(verifier.get_version(key), 42);
189    }
190    
191    #[test]
192    fn test_remove_version() {
193        let mut verifier = VersionVerifier::new();
194        let key = "test_key";
195        
196        verifier.set_version(key, 5);
197        assert_eq!(verifier.get_version(key), 5);
198        
199        verifier.remove_version(key);
200        assert_eq!(verifier.get_version(key), 0);
201    }
202    
203    #[test]
204    fn test_clear_versions() {
205        let mut verifier = VersionVerifier::new();
206        
207        verifier.set_version("key1", 1);
208        verifier.set_version("key2", 2);
209        assert_eq!(verifier.get_all_versions().len(), 2);
210        
211        verifier.clear_versions();
212        assert_eq!(verifier.get_all_versions().len(), 0);
213    }
214}