gun/
state.rs

1//! State management for conflict resolution
2//!
3//! This module implements Gun's state timestamp system, which is used for conflict
4//! resolution in the HAM (Hypothetical Amnesia Machine) algorithm. State timestamps
5//! are monotonically increasing values that combine system time with a sub-millisecond
6//! counter to ensure uniqueness.
7//!
8//! Based on Gun.js `state.js`. State values are used to determine which version of
9//! data wins in conflicts - higher state always wins.
10//!
11//! ## State Format
12//!
13//! State values are `f64` timestamps in milliseconds with sub-millisecond precision:
14//! - Base: System time in milliseconds since Unix epoch
15//! - Fractional part: Sub-millisecond counter (0.0 to 0.999)
16//! - Ensures monotonicity even with high write rates
17//!
18//! ## Conflict Resolution
19//!
20//! When two peers update the same property simultaneously:
21//! - Compare state timestamps
22//! - Higher state wins
23//! - Merge non-conflicting properties automatically
24
25use serde::{Deserialize, Serialize};
26use serde_json::Value;
27use std::sync::{Arc, Mutex};
28use std::time::{SystemTime, UNIX_EPOCH};
29
30const DRIFT: f64 = 0.0; // Time drift compensation (currently unused)
31const D: f64 = 999.0;   // Divisor for sub-millisecond precision
32
33/// State timestamp generator for conflict resolution
34///
35/// Generates monotonically increasing timestamps that combine system time with
36/// a sub-millisecond counter. This ensures uniqueness and proper ordering even
37/// with high write rates.
38///
39/// State values are used throughout Gun to:
40/// - Resolve conflicts (higher state wins)
41/// - Order updates chronologically
42/// - Track when data was last modified
43///
44/// # Thread Safety
45///
46/// `State` is thread-safe and can be shared across threads using `Arc<State>`.
47#[derive(Clone)]
48pub struct State {
49    n: Arc<Mutex<f64>>,
50    last: Arc<Mutex<f64>>,
51}
52
53impl Default for State {
54    fn default() -> Self {
55        Self::new()
56    }
57}
58
59impl State {
60    /// Create a new State generator
61    ///
62    /// Initializes the state system with a counter starting at 0.
63    pub fn new() -> Self {
64        Self {
65            n: Arc::new(Mutex::new(0.0)),
66            last: Arc::new(Mutex::new(f64::NEG_INFINITY)),
67        }
68    }
69
70    /// Generate a new state timestamp
71    /// Returns a timestamp that increases with each call
72    /// 
73    /// # Panics
74    /// This function will panic if the system time is before the Unix epoch,
75    /// which should never happen in practice on modern systems.
76    pub fn next(&self) -> f64 {
77        let t = SystemTime::now()
78            .duration_since(UNIX_EPOCH)
79            .expect("System time is before Unix epoch - this should never happen")
80            .as_millis() as f64;
81
82        // std::sync::Mutex::lock() returns Result, handle potential poisoning
83        // Mutex poisoning indicates a panic occurred while holding the lock,
84        // which is a serious bug but we can still recover by using expect()
85        let mut n = self.n.lock().expect("State mutex poisoned - this indicates a serious bug");
86        let mut last = self.last.lock().expect("State mutex poisoned - this indicates a serious bug");
87
88        if *last < t {
89            *n = 0.0;
90            *last = t + DRIFT;
91            return *last;
92        }
93
94        *last = t + (*n / D) + DRIFT;
95        *n += 1.0;
96        *last
97    }
98
99    /// Get the state timestamp for a specific key on a node
100    ///
101    /// Retrieves the state value stored in the node's metadata for the given key.
102    /// Returns `None` if the key doesn't exist or has no state recorded.
103    ///
104    /// # Arguments
105    /// * `node` - Optional reference to the node
106    /// * `key` - The property key to check
107    ///
108    /// # Returns
109    /// The state timestamp for the key, or `None` if not found.
110    ///
111    /// # Example
112    ///
113    /// ```rust,no_run
114    /// use gun::state::{State, Node};
115    ///
116    /// let node = Node::new();
117    /// let state_value = State::is(&Some(node), "my_key");
118    /// ```
119    pub fn is(node: &Option<Node>, key: &str) -> Option<f64> {
120        if let Some(node) = node {
121            if let Some(Value::Object(states)) = node.meta.get(">") {
122                if let Some(state) = states.get(key) {
123                    if let Some(state_num) = state.as_f64() {
124                        return Some(state_num);
125                    }
126                }
127            }
128        }
129        None
130    }
131
132    /// Update a node with state information for a key
133    ///
134    /// This method sets the state timestamp and optionally the soul and data for a node.
135    /// It's called whenever data is updated to record when the change occurred.
136    ///
137    /// # Arguments
138    /// * `node` - Mutable reference to the node to update
139    /// * `key` - Optional property key (if `None`, only soul is set)
140    /// * `state` - Optional state timestamp (generated by [`next`](Self::next))
141    /// * `value` - Optional value to store in the node's data
142    /// * `soul` - Optional soul identifier for the node
143    ///
144    /// # Returns
145    /// A clone of the updated node (for convenience in chaining).
146    ///
147    /// # Example
148    ///
149    /// ```rust,no_run
150    /// use gun::state::{State, Node};
151    /// use serde_json::json;
152    ///
153    /// let mut node = Node::with_soul("my_soul".to_string());
154    /// let state = State::new();
155    /// let timestamp = state.next();
156    ///
157    /// State::ify(
158    ///     &mut node,
159    ///     Some("my_key"),
160    ///     Some(timestamp),
161    ///     Some(json!("my_value")),
162    ///     Some("my_soul"),
163    /// );
164    /// ```
165    pub fn ify(
166        node: &mut Node,
167        key: Option<&str>,
168        state: Option<f64>,
169        value: Option<serde_json::Value>,
170        soul: Option<&str>,
171    ) -> Node {
172        if let Some(soul) = soul {
173            node.meta
174                .insert("#".to_string(), serde_json::Value::String(soul.to_string()));
175        }
176
177        if let Some(key) = key {
178            if key != "_" {
179                let states = node
180                    .meta
181                    .entry(">".to_string())
182                    .or_insert_with(|| serde_json::Value::Object(serde_json::Map::new()));
183
184                if let Some(state_num) = state {
185                    if let serde_json::Value::Object(ref mut map) = states {
186                    // from_f64 can fail if state_num is NaN or Infinity
187                    // In practice, state_num should always be a valid finite number
188                    if let Some(number) = serde_json::Number::from_f64(state_num) {
189                        map.insert(key.to_string(), serde_json::Value::Number(number));
190                    } else {
191                        // Log error but continue - this should never happen in practice
192                        tracing::error!("Invalid state number: {} (NaN or Infinity)", state_num);
193                    }
194                    }
195                }
196
197                if let Some(val) = value {
198                    node.data.insert(key.to_string(), val);
199                }
200            }
201        }
202
203        node.clone()
204    }
205}
206
207/// A node in the Gun graph
208///
209/// Nodes are the fundamental data structure in Gun. Each node has:
210/// - **data**: Key-value pairs storing the actual data
211/// - **meta**: Metadata including the soul (`#`) and state timestamps (`>`)
212///
213/// Nodes are identified by their "soul" (stored in `meta["#"]`), which is a unique
214/// identifier generated by [`GunCore::uuid`](crate::core::GunCore::uuid).
215///
216/// State information is stored in `meta[">"]` as a map from key to timestamp.
217///
218/// # Example
219///
220/// ```rust,no_run
221/// use gun::state::Node;
222/// use serde_json::json;
223///
224/// let mut node = Node::with_soul("user_123".to_string());
225/// node.data.insert("name".to_string(), json!("Alice"));
226/// node.data.insert("age".to_string(), json!(30));
227/// ```
228#[derive(Clone, Debug, Serialize, Deserialize)]
229pub struct Node {
230    pub data: serde_json::Map<String, serde_json::Value>,
231    pub meta: serde_json::Map<String, serde_json::Value>,
232}
233
234impl Node {
235    /// Create a new empty node without a soul
236    ///
237    /// The soul will need to be set later using `meta.insert("#", ...)`.
238    pub fn new() -> Self {
239        Self {
240            data: serde_json::Map::new(),
241            meta: serde_json::Map::new(),
242        }
243    }
244
245    /// Create a new node with a specific soul
246    ///
247    /// # Arguments
248    /// * `soul` - The unique identifier for this node
249    ///
250    /// # Example
251    ///
252    /// ```rust,no_run
253    /// use gun::state::Node;
254    ///
255    /// let node = Node::with_soul("user_123".to_string());
256    /// ```
257    pub fn with_soul(soul: String) -> Self {
258        let mut meta = serde_json::Map::new();
259        meta.insert("#".to_string(), serde_json::Value::String(soul));
260        Self {
261            data: serde_json::Map::new(),
262            meta,
263        }
264    }
265
266    /// Get the soul (unique identifier) of this node
267    ///
268    /// Returns `None` if the node doesn't have a soul set.
269    ///
270    /// # Returns
271    /// The soul string, or `None` if not set.
272    ///
273    /// # Example
274    ///
275    /// ```rust,no_run
276    /// use gun::state::Node;
277    ///
278    /// let node = Node::with_soul("user_123".to_string());
279    /// assert_eq!(node.get_soul(), Some("user_123".to_string()));
280    /// ```
281    pub fn get_soul(&self) -> Option<String> {
282        self.meta
283            .get("#")
284            .and_then(|v| v.as_str())
285            .map(|s| s.to_string())
286    }
287}
288
289impl Default for Node {
290    fn default() -> Self {
291        Self::new()
292    }
293}