Skip to main content

hyperopt_core/
storage.rs

1use crate::{Direction, Trial};
2use std::fmt;
3
4/// Persisted study-level metadata (everything about a study except its trials).
5#[derive(Debug, Clone, PartialEq)]
6pub struct StudyMetadata {
7    pub study_name: String,
8    pub direction: Direction,
9}
10
11/// Errors a [`Storage`] backend can raise.
12#[derive(Debug)]
13pub enum StorageError {
14    /// A study with the requested name was not found.
15    StudyNotFound(String),
16    /// Serialization/deserialization of a trial failed.
17    Serialization(String),
18    /// The backing store (file, DB) is at an incompatible schema version.
19    SchemaMismatch { found: i64, expected: i64 },
20    /// Any backend-specific I/O or driver error.
21    Backend(String),
22}
23
24impl fmt::Display for StorageError {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        match self {
27            StorageError::StudyNotFound(name) => write!(f, "study not found: {name}"),
28            StorageError::Serialization(msg) => write!(f, "serialization error: {msg}"),
29            StorageError::SchemaMismatch { found, expected } => write!(
30                f,
31                "storage schema version mismatch: found {found}, expected {expected}"
32            ),
33            StorageError::Backend(msg) => write!(f, "storage backend error: {msg}"),
34        }
35    }
36}
37
38impl std::error::Error for StorageError {}
39
40/// Where a study's trial history lives.
41///
42/// Abstracting this keeps [`crate::Study`] agnostic to whether history is a
43/// `Vec` in memory or rows in SQLite. Backends must be `Send + Sync` so a study
44/// can be optimized in parallel; they are expected to use interior mutability
45/// (all methods take `&self`) and upsert trials by `(study, trial number)`.
46pub trait Storage: Send + Sync {
47    /// Insert or update a trial for the given study.
48    fn save_trial(&self, study_name: &str, trial: &Trial) -> Result<(), StorageError>;
49
50    /// Load all trials for a study, in trial-number order. Returns an empty
51    /// vec for a study that exists but has no trials yet.
52    fn load_trials(&self, study_name: &str) -> Result<Vec<Trial>, StorageError>;
53
54    /// Insert or update study-level metadata.
55    fn save_study_metadata(&self, meta: &StudyMetadata) -> Result<(), StorageError>;
56
57    /// Fetch study-level metadata, or `None` if the study is unknown.
58    fn load_study_metadata(&self, study_name: &str)
59        -> Result<Option<StudyMetadata>, StorageError>;
60}