Skip to main content

agentic_reality/query/
delta.rs

1//! Delta retrieval — change-proportional queries.
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6pub enum ChangeType {
7    Created,
8    Updated,
9    Deleted,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Change<T> {
14    pub id: String,
15    pub change_type: ChangeType,
16    pub timestamp: i64,
17    pub value: Option<T>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct DeltaResult<T> {
22    pub changes: Vec<Change<T>>,
23    pub from_version: u64,
24    pub to_version: u64,
25    pub has_more: bool,
26}
27
28impl<T> DeltaResult<T> {
29    pub fn empty(version: u64) -> Self {
30        Self {
31            changes: Vec::new(),
32            from_version: version,
33            to_version: version,
34            has_more: false,
35        }
36    }
37
38    pub fn is_empty(&self) -> bool {
39        self.changes.is_empty()
40    }
41
42    pub fn len(&self) -> usize {
43        self.changes.len()
44    }
45}
46
47#[derive(Debug, Clone)]
48pub struct VersionedState {
49    version: u64,
50    timestamps: Vec<(String, i64, ChangeType)>,
51}
52
53impl VersionedState {
54    pub fn new() -> Self {
55        Self {
56            version: 0,
57            timestamps: Vec::new(),
58        }
59    }
60
61    pub fn record_change(&mut self, id: impl Into<String>, change_type: ChangeType) {
62        self.version += 1;
63        let ts = chrono::Utc::now().timestamp_micros();
64        self.timestamps.push((id.into(), ts, change_type));
65    }
66
67    pub fn version(&self) -> u64 {
68        self.version
69    }
70
71    pub fn changes_since(&self, since_ts: i64) -> Vec<&(String, i64, ChangeType)> {
72        self.timestamps
73            .iter()
74            .filter(|(_, ts, _)| *ts > since_ts)
75            .collect()
76    }
77
78    pub fn changes_since_version(&self, since_version: u64) -> Vec<&(String, i64, ChangeType)> {
79        if since_version as usize >= self.timestamps.len() {
80            return Vec::new();
81        }
82        self.timestamps[since_version as usize..].iter().collect()
83    }
84
85    pub fn last_change_timestamp(&self) -> i64 {
86        self.timestamps.last().map(|(_, ts, _)| *ts).unwrap_or(0)
87    }
88
89    pub fn is_unchanged_since(&self, since_version: u64) -> bool {
90        self.version <= since_version
91    }
92}
93
94impl Default for VersionedState {
95    fn default() -> Self {
96        Self::new()
97    }
98}