Skip to main content

perfgate_server/storage/
mod.rs

1//! Storage trait and implementations for baseline persistence.
2//!
3//! This module provides the [`BaselineStore`] trait for abstracting storage
4//! operations and implementations for different backends.
5
6mod memory;
7mod postgres;
8mod sqlite;
9
10pub use memory::InMemoryStore;
11pub use postgres::PostgresStore;
12pub use sqlite::SqliteStore;
13
14use crate::error::StoreError;
15use crate::models::{BaselineRecord, BaselineVersion, ListBaselinesQuery, ListBaselinesResponse};
16use async_trait::async_trait;
17
18/// Trait for baseline storage operations.
19///
20/// This trait abstracts the storage layer, allowing different backends
21/// (in-memory, SQLite, PostgreSQL) to be used interchangeably.
22#[async_trait]
23pub trait BaselineStore: Send + Sync {
24    /// Stores a new baseline record.
25    async fn create(&self, record: &BaselineRecord) -> Result<(), StoreError>;
26
27    /// Retrieves a baseline by project, benchmark, and version.
28    async fn get(
29        &self,
30        project: &str,
31        benchmark: &str,
32        version: &str,
33    ) -> Result<Option<BaselineRecord>, StoreError>;
34
35    /// Retrieves the latest baseline for a project and benchmark.
36    async fn get_latest(
37        &self,
38        project: &str,
39        benchmark: &str,
40    ) -> Result<Option<BaselineRecord>, StoreError>;
41
42    /// Lists baselines with optional filtering.
43    async fn list(
44        &self,
45        project: &str,
46        query: &ListBaselinesQuery,
47    ) -> Result<ListBaselinesResponse, StoreError>;
48
49    /// Updates an existing baseline record.
50    async fn update(&self, record: &BaselineRecord) -> Result<(), StoreError>;
51
52    /// Deletes a baseline (soft delete).
53    async fn delete(
54        &self,
55        project: &str,
56        benchmark: &str,
57        version: &str,
58    ) -> Result<bool, StoreError>;
59
60    /// Permanently removes a deleted baseline.
61    async fn hard_delete(
62        &self,
63        project: &str,
64        benchmark: &str,
65        version: &str,
66    ) -> Result<bool, StoreError>;
67
68    /// Lists all versions for a benchmark.
69    async fn list_versions(
70        &self,
71        project: &str,
72        benchmark: &str,
73    ) -> Result<Vec<BaselineVersion>, StoreError>;
74
75    /// Checks if the storage backend is healthy.
76    async fn health_check(&self) -> Result<StorageHealth, StoreError>;
77
78    /// Returns the backend type name.
79    fn backend_type(&self) -> &'static str;
80}
81
82/// Storage backend health status.
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84pub enum StorageHealth {
85    /// Storage is healthy and operational
86    Healthy,
87    /// Storage is degraded but functional
88    Degraded,
89    /// Storage is unavailable
90    Unhealthy,
91}
92
93impl StorageHealth {
94    /// Returns the string representation.
95    pub fn as_str(&self) -> &'static str {
96        match self {
97            Self::Healthy => "healthy",
98            Self::Degraded => "degraded",
99            Self::Unhealthy => "unhealthy",
100        }
101    }
102}
103
104impl std::fmt::Display for StorageHealth {
105    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106        write!(f, "{}", self.as_str())
107    }
108}