akar_storage/
undo_buffer.rs1use akar_common::error::StorageError;
10use akar_transaction::UndoRecord;
11
12#[derive(Debug, Default)]
14pub struct UndoBuffer {
15 records: Vec<UndoRecord>,
16}
17
18impl UndoBuffer {
19 pub fn new() -> Self {
20 Self { records: Vec::new() }
21 }
22
23 pub fn record(&mut self, table_id: u64, row_id: u64, column: u32, old_data: Vec<u8>) {
25 self.records
26 .push(UndoRecord::update(table_id, row_id, column, old_data));
27 }
28
29 pub fn len(&self) -> usize {
31 self.records.len()
32 }
33
34 pub fn is_empty(&self) -> bool {
36 self.records.is_empty()
37 }
38
39 pub fn clear(&mut self) {
41 self.records.clear();
42 }
43
44 pub fn drain(&mut self) -> Vec<UndoRecord> {
48 std::mem::take(&mut self.records)
49 }
50
51 pub fn rollback<F>(&mut self, mut apply_fn: F) -> Result<(), StorageError>
58 where
59 F: FnMut(&UndoRecord) -> Result<(), StorageError>,
60 {
61 for record in self.records.iter().rev() {
62 apply_fn(record)?;
63 }
64 self.clear();
65 Ok(())
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_empty_buffer() {
75 let buf = UndoBuffer::new();
76 assert!(buf.is_empty());
77 assert_eq!(buf.len(), 0);
78 }
79
80 #[test]
81 fn test_record_and_drain() {
82 let mut buf = UndoBuffer::new();
83 buf.record(1, 100, 0, vec![1, 2, 3]);
84 buf.record(1, 200, 1, vec![4, 5, 6]);
85 assert_eq!(buf.len(), 2);
86
87 let drained = buf.drain();
88 assert_eq!(drained.len(), 2);
89 assert!(buf.is_empty());
90 }
91
92 #[test]
93 fn test_rollback_applies_reverse_order() {
94 let mut buf = UndoBuffer::new();
95 buf.record(1, 100, 0, vec![1]); buf.record(1, 100, 0, vec![2]); let mut applied = Vec::new();
99 buf.rollback(|rec| {
100 applied.push(rec.old_data[0]);
101 Ok(())
102 })
103 .unwrap();
104
105 assert_eq!(applied, vec![2, 1]);
107 }
108
109 #[test]
110 fn test_rollback_clears_buffer() {
111 let mut buf = UndoBuffer::new();
112 buf.record(1, 100, 0, vec![1]);
113
114 buf.rollback(|_| Ok(())).unwrap();
115 assert!(buf.is_empty());
116 }
117}