guts_storage/
traits.rs

1//! Storage backend traits.
2//!
3//! Defines the interface that all storage backends must implement,
4//! enabling pluggable storage strategies.
5
6use crate::{GitObject, ObjectId, Result};
7use std::sync::Arc;
8
9/// Trait for object storage backends.
10///
11/// Implementations include in-memory, RocksDB, and hybrid storage.
12pub trait ObjectStoreBackend: Send + Sync {
13    /// Stores an object and returns its ID.
14    fn put(&self, object: GitObject) -> Result<ObjectId>;
15
16    /// Retrieves an object by ID.
17    fn get(&self, id: &ObjectId) -> Result<Option<GitObject>>;
18
19    /// Checks if an object exists.
20    fn contains(&self, id: &ObjectId) -> Result<bool>;
21
22    /// Deletes an object by ID.
23    fn delete(&self, id: &ObjectId) -> Result<bool>;
24
25    /// Returns the number of objects in the store.
26    fn len(&self) -> Result<usize>;
27
28    /// Returns true if the store is empty.
29    fn is_empty(&self) -> Result<bool> {
30        Ok(self.len()? == 0)
31    }
32
33    /// Lists all object IDs.
34    fn list_objects(&self) -> Result<Vec<ObjectId>>;
35
36    /// Batch put operation for improved throughput.
37    fn batch_put(&self, objects: Vec<GitObject>) -> Result<Vec<ObjectId>> {
38        objects.into_iter().map(|obj| self.put(obj)).collect()
39    }
40
41    /// Batch get operation.
42    fn batch_get(&self, ids: &[ObjectId]) -> Result<Vec<Option<GitObject>>> {
43        ids.iter().map(|id| self.get(id)).collect()
44    }
45
46    /// Flush any pending writes to durable storage.
47    fn flush(&self) -> Result<()> {
48        Ok(())
49    }
50
51    /// Compact the storage to reclaim space.
52    fn compact(&self) -> Result<()> {
53        Ok(())
54    }
55}
56
57// Implement ObjectStoreBackend for Arc<T> where T: ObjectStoreBackend
58impl<T: ObjectStoreBackend> ObjectStoreBackend for Arc<T> {
59    fn put(&self, object: GitObject) -> Result<ObjectId> {
60        (**self).put(object)
61    }
62
63    fn get(&self, id: &ObjectId) -> Result<Option<GitObject>> {
64        (**self).get(id)
65    }
66
67    fn contains(&self, id: &ObjectId) -> Result<bool> {
68        (**self).contains(id)
69    }
70
71    fn delete(&self, id: &ObjectId) -> Result<bool> {
72        (**self).delete(id)
73    }
74
75    fn len(&self) -> Result<usize> {
76        (**self).len()
77    }
78
79    fn list_objects(&self) -> Result<Vec<ObjectId>> {
80        (**self).list_objects()
81    }
82
83    fn batch_put(&self, objects: Vec<GitObject>) -> Result<Vec<ObjectId>> {
84        (**self).batch_put(objects)
85    }
86
87    fn batch_get(&self, ids: &[ObjectId]) -> Result<Vec<Option<GitObject>>> {
88        (**self).batch_get(ids)
89    }
90
91    fn flush(&self) -> Result<()> {
92        (**self).flush()
93    }
94
95    fn compact(&self) -> Result<()> {
96        (**self).compact()
97    }
98}
99
100/// High-level storage backend trait with lifecycle management.
101pub trait StorageBackend: ObjectStoreBackend {
102    /// Opens or creates the storage at the given path.
103    fn open(path: &std::path::Path) -> Result<Self>
104    where
105        Self: Sized;
106
107    /// Closes the storage, flushing any pending data.
108    fn close(&self) -> Result<()> {
109        self.flush()
110    }
111
112    /// Returns storage statistics.
113    fn stats(&self) -> StorageStats {
114        StorageStats::default()
115    }
116}
117
118/// Storage statistics.
119#[derive(Debug, Clone, Default)]
120pub struct StorageStats {
121    /// Total number of objects.
122    pub object_count: u64,
123    /// Total size of all objects in bytes.
124    pub total_size_bytes: u64,
125    /// Size of storage on disk (if applicable).
126    pub disk_size_bytes: Option<u64>,
127    /// Number of read operations.
128    pub reads: u64,
129    /// Number of write operations.
130    pub writes: u64,
131    /// Cache hit ratio (if caching enabled).
132    pub cache_hit_ratio: Option<f64>,
133}
134
135#[cfg(test)]
136mod tests {
137    use super::*;
138
139    // Mock implementation for testing
140    struct MockStorage;
141
142    impl ObjectStoreBackend for MockStorage {
143        fn put(&self, _object: GitObject) -> Result<ObjectId> {
144            Ok(ObjectId::from_bytes([0u8; 20]))
145        }
146
147        fn get(&self, _id: &ObjectId) -> Result<Option<GitObject>> {
148            Ok(None)
149        }
150
151        fn contains(&self, _id: &ObjectId) -> Result<bool> {
152            Ok(false)
153        }
154
155        fn delete(&self, _id: &ObjectId) -> Result<bool> {
156            Ok(false)
157        }
158
159        fn len(&self) -> Result<usize> {
160            Ok(0)
161        }
162
163        fn list_objects(&self) -> Result<Vec<ObjectId>> {
164            Ok(vec![])
165        }
166    }
167
168    #[test]
169    fn test_is_empty_default() {
170        let storage = MockStorage;
171        assert!(storage.is_empty().unwrap());
172    }
173}