Skip to main content

shipper_core/state/store/
fs.rs

1//! Filesystem-backed implementation of [`StateStore`].
2
3use std::path::{Path, PathBuf};
4
5use anyhow::{Context, Result};
6
7use crate::state::events::EventLog;
8use crate::state::execution_state as state;
9use crate::types::{ExecutionState, Receipt};
10
11use super::StateStore;
12
13/// Filesystem-based state store implementation.
14///
15/// This is the default implementation that stores state in a local directory.
16pub struct FileStore {
17    state_dir: PathBuf,
18}
19
20impl FileStore {
21    /// Create a new FileStore with the specified state directory
22    pub fn new(state_dir: PathBuf) -> Self {
23        Self { state_dir }
24    }
25
26    /// Get the state directory path
27    pub fn state_dir(&self) -> &Path {
28        &self.state_dir
29    }
30}
31
32impl StateStore for FileStore {
33    fn save_state(&self, state: &ExecutionState) -> Result<()> {
34        state::save_state(&self.state_dir, state)
35    }
36
37    fn load_state(&self) -> Result<Option<ExecutionState>> {
38        state::load_state(&self.state_dir)
39    }
40
41    fn save_receipt(&self, receipt: &Receipt) -> Result<()> {
42        state::write_receipt(&self.state_dir, receipt)
43    }
44
45    fn load_receipt(&self) -> Result<Option<Receipt>> {
46        state::load_receipt(&self.state_dir)
47    }
48
49    fn save_events(&self, events: &EventLog) -> Result<()> {
50        let path = crate::state::events::events_path(&self.state_dir);
51        events.write_to_file(&path)
52    }
53
54    fn load_events(&self) -> Result<Option<EventLog>> {
55        let path = crate::state::events::events_path(&self.state_dir);
56        if !path.exists() {
57            return Ok(None);
58        }
59        Ok(Some(EventLog::read_from_file(&path)?))
60    }
61
62    fn clear(&self) -> Result<()> {
63        let state_path = state::state_path(&self.state_dir);
64        let receipt_path = state::receipt_path(&self.state_dir);
65        let events_path = crate::state::events::events_path(&self.state_dir);
66
67        // Remove files if they exist
68        if state_path.exists() {
69            std::fs::remove_file(&state_path)
70                .with_context(|| format!("failed to remove state file {}", state_path.display()))?;
71        }
72        if receipt_path.exists() {
73            std::fs::remove_file(&receipt_path).with_context(|| {
74                format!("failed to remove receipt file {}", receipt_path.display())
75            })?;
76        }
77        if events_path.exists() {
78            std::fs::remove_file(&events_path).with_context(|| {
79                format!("failed to remove events file {}", events_path.display())
80            })?;
81        }
82
83        Ok(())
84    }
85}