mentedb_index/
temporal.rs1use std::collections::BTreeMap;
4
5use ahash::HashMap;
6use parking_lot::RwLock;
7use serde::{Deserialize, Serialize};
8
9use mentedb_core::error::{MenteError, MenteResult};
10use mentedb_core::types::{MemoryId, Timestamp};
11
12pub struct TemporalIndex {
14 inner: RwLock<TemporalInner>,
15}
16
17struct TemporalInner {
18 tree: BTreeMap<Timestamp, Vec<MemoryId>>,
20 id_to_ts: HashMap<MemoryId, Timestamp>,
22}
23
24impl TemporalIndex {
25 pub fn new() -> Self {
27 Self {
28 inner: RwLock::new(TemporalInner {
29 tree: BTreeMap::new(),
30 id_to_ts: HashMap::default(),
31 }),
32 }
33 }
34
35 pub fn insert(&self, id: MemoryId, timestamp: Timestamp) {
37 let mut inner = self.inner.write();
38 inner.tree.entry(timestamp).or_default().push(id);
39 inner.id_to_ts.insert(id, timestamp);
40 }
41
42 pub fn range(&self, start: Timestamp, end: Timestamp) -> Vec<MemoryId> {
44 let inner = self.inner.read();
45 inner
46 .tree
47 .range(start..=end)
48 .flat_map(|(_, ids)| ids.iter().copied())
49 .collect()
50 }
51
52 pub fn latest(&self, n: usize) -> Vec<MemoryId> {
54 let inner = self.inner.read();
55 let mut results = Vec::with_capacity(n);
56 for (_, ids) in inner.tree.iter().rev() {
57 for &id in ids.iter().rev() {
58 results.push(id);
59 if results.len() >= n {
60 return results;
61 }
62 }
63 }
64 results
65 }
66
67 pub fn remove(&self, id: MemoryId, timestamp: Timestamp) {
69 let mut inner = self.inner.write();
70 if let Some(ids) = inner.tree.get_mut(×tamp) {
71 ids.retain(|&i| i != id);
72 if ids.is_empty() {
73 inner.tree.remove(×tamp);
74 }
75 }
76 inner.id_to_ts.remove(&id);
77 }
78
79 pub fn remove_by_id(&self, id: MemoryId) {
81 let mut inner = self.inner.write();
82 if let Some(ts) = inner.id_to_ts.remove(&id)
83 && let Some(ids) = inner.tree.get_mut(&ts)
84 {
85 ids.retain(|&i| i != id);
86 if ids.is_empty() {
87 inner.tree.remove(&ts);
88 }
89 }
90 }
91
92 pub fn get_timestamp(&self, id: MemoryId) -> Option<Timestamp> {
94 let inner = self.inner.read();
95 inner.id_to_ts.get(&id).copied()
96 }
97}
98
99#[derive(Serialize, Deserialize)]
101struct TemporalSnapshot {
102 tree: Vec<(Timestamp, Vec<MemoryId>)>,
103 id_to_ts: Vec<(MemoryId, Timestamp)>,
104}
105
106impl TemporalIndex {
107 pub fn save(&self, path: &std::path::Path) -> MenteResult<()> {
109 let inner = self.inner.read();
110 let snapshot = TemporalSnapshot {
111 tree: inner.tree.iter().map(|(&k, v)| (k, v.clone())).collect(),
112 id_to_ts: inner.id_to_ts.iter().map(|(&k, &v)| (k, v)).collect(),
113 };
114 let data =
115 serde_json::to_vec(&snapshot).map_err(|e| MenteError::Serialization(e.to_string()))?;
116 std::fs::write(path, data)?;
117 Ok(())
118 }
119
120 pub fn load(path: &std::path::Path) -> MenteResult<Self> {
122 let data = std::fs::read(path)?;
123 let snapshot: TemporalSnapshot =
124 serde_json::from_slice(&data).map_err(|e| MenteError::Serialization(e.to_string()))?;
125
126 let mut tree = BTreeMap::new();
127 for (ts, ids) in snapshot.tree {
128 tree.insert(ts, ids);
129 }
130
131 let mut id_to_ts = HashMap::default();
132 for (id, ts) in snapshot.id_to_ts {
133 id_to_ts.insert(id, ts);
134 }
135
136 Ok(Self {
137 inner: RwLock::new(TemporalInner { tree, id_to_ts }),
138 })
139 }
140}
141
142impl Default for TemporalIndex {
143 fn default() -> Self {
144 Self::new()
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn test_insert_and_range() {
154 let idx = TemporalIndex::new();
155 let a = MemoryId::new();
156 let b = MemoryId::new();
157 let c = MemoryId::new();
158
159 idx.insert(a, 100);
160 idx.insert(b, 200);
161 idx.insert(c, 300);
162
163 let result = idx.range(100, 200);
164 assert_eq!(result.len(), 2);
165 assert!(result.contains(&a));
166 assert!(result.contains(&b));
167 }
168
169 #[test]
170 fn test_latest() {
171 let idx = TemporalIndex::new();
172 let a = MemoryId::new();
173 let b = MemoryId::new();
174 let c = MemoryId::new();
175
176 idx.insert(a, 100);
177 idx.insert(b, 200);
178 idx.insert(c, 300);
179
180 let latest = idx.latest(2);
181 assert_eq!(latest.len(), 2);
182 assert_eq!(latest[0], c);
183 assert_eq!(latest[1], b);
184 }
185
186 #[test]
187 fn test_remove() {
188 let idx = TemporalIndex::new();
189 let a = MemoryId::new();
190 idx.insert(a, 100);
191 idx.remove(a, 100);
192
193 assert!(idx.range(0, 1000).is_empty());
194 }
195
196 #[test]
197 fn test_remove_by_id() {
198 let idx = TemporalIndex::new();
199 let a = MemoryId::new();
200 idx.insert(a, 500);
201 idx.remove_by_id(a);
202
203 assert!(idx.range(0, 1000).is_empty());
204 }
205
206 #[test]
207 fn test_empty_range() {
208 let idx = TemporalIndex::new();
209 assert!(idx.range(0, 100).is_empty());
210 }
211}