1mod artifacts;
7pub mod fleet;
8mod key_store;
9mod memory;
10mod postgres;
11mod sqlite;
12
13pub use artifacts::ObjectArtifactStore;
14pub use fleet::{FleetStore, InMemoryFleetStore};
15pub use key_store::{InMemoryKeyStore, KeyRecord, KeyStore, SqliteKeyStore, hash_key, key_prefix};
16pub use memory::InMemoryStore;
17pub use postgres::PostgresStore;
18pub use sqlite::SqliteStore;
19
20use crate::error::StoreError;
21use crate::models::{
22 AuditEvent, BaselineRecord, BaselineVersion, ListAuditEventsQuery, ListAuditEventsResponse,
23 ListBaselinesQuery, ListBaselinesResponse, ListVerdictsQuery, ListVerdictsResponse,
24 PoolMetrics, VerdictRecord,
25};
26use async_trait::async_trait;
27use chrono::{DateTime, Utc};
28
29#[derive(Debug, Clone)]
31pub struct ArtifactMeta {
32 pub path: String,
34 pub last_modified: DateTime<Utc>,
36 pub size: u64,
38}
39
40#[async_trait]
42pub trait ArtifactStore: std::fmt::Debug + Send + Sync {
43 async fn put(&self, path: &str, data: Vec<u8>) -> Result<(), StoreError>;
45
46 async fn get(&self, path: &str) -> Result<Vec<u8>, StoreError>;
48
49 async fn delete(&self, path: &str) -> Result<(), StoreError>;
51
52 async fn list(&self, prefix: Option<&str>) -> Result<Vec<ArtifactMeta>, StoreError>;
54}
55
56#[async_trait]
61pub trait BaselineStore: Send + Sync {
62 async fn create(&self, record: &BaselineRecord) -> Result<(), StoreError>;
64
65 async fn get(
67 &self,
68 project: &str,
69 benchmark: &str,
70 version: &str,
71 ) -> Result<Option<BaselineRecord>, StoreError>;
72
73 async fn get_latest(
75 &self,
76 project: &str,
77 benchmark: &str,
78 ) -> Result<Option<BaselineRecord>, StoreError>;
79
80 async fn list(
82 &self,
83 project: &str,
84 query: &ListBaselinesQuery,
85 ) -> Result<ListBaselinesResponse, StoreError>;
86
87 async fn update(&self, record: &BaselineRecord) -> Result<(), StoreError>;
89
90 async fn delete(
92 &self,
93 project: &str,
94 benchmark: &str,
95 version: &str,
96 ) -> Result<bool, StoreError>;
97
98 async fn hard_delete(
100 &self,
101 project: &str,
102 benchmark: &str,
103 version: &str,
104 ) -> Result<bool, StoreError>;
105
106 async fn list_versions(
108 &self,
109 project: &str,
110 benchmark: &str,
111 ) -> Result<Vec<BaselineVersion>, StoreError>;
112
113 async fn health_check(&self) -> Result<StorageHealth, StoreError>;
115
116 fn backend_type(&self) -> &'static str;
118
119 fn pool_metrics(&self) -> Option<PoolMetrics> {
124 None
125 }
126
127 async fn create_verdict(&self, record: &VerdictRecord) -> Result<(), StoreError>;
129
130 async fn list_verdicts(
132 &self,
133 project: &str,
134 query: &ListVerdictsQuery,
135 ) -> Result<ListVerdictsResponse, StoreError>;
136}
137
138#[async_trait]
143pub trait AuditStore: Send + Sync {
144 async fn log_event(&self, event: &AuditEvent) -> Result<(), StoreError>;
146
147 async fn list_events(
149 &self,
150 query: &ListAuditEventsQuery,
151 ) -> Result<ListAuditEventsResponse, StoreError>;
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq)]
156pub enum StorageHealth {
157 Healthy,
159 Degraded,
161 Unhealthy,
163}
164
165impl StorageHealth {
166 pub fn as_str(&self) -> &'static str {
168 match self {
169 Self::Healthy => "healthy",
170 Self::Degraded => "degraded",
171 Self::Unhealthy => "unhealthy",
172 }
173 }
174}
175
176impl std::fmt::Display for StorageHealth {
177 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178 write!(f, "{}", self.as_str())
179 }
180}