Skip to main content

confium_log_monitor/
store.rs

1//! Persistent state for the monitor.
2//!
3//! Stores the last-seen tree head so we can detect tree-size
4//! regression and verify consistency between cycles. Backed by
5//! sled for simplicity; production deployments might use Postgres
6//! or LevelDB.
7
8use std::path::Path;
9
10use anyhow::Result;
11use sled::Db;
12
13use crate::client::TreeHead;
14
15pub struct StateStore {
16    db: Db,
17}
18
19impl StateStore {
20    pub fn open(path: &Path) -> Result<Self> {
21        std::fs::create_dir_all(path)?;
22        let db = sled::open(path)?;
23        Ok(StateStore { db })
24    }
25
26    pub fn last_tree_size(&self) -> Result<u64> {
27        Ok(self
28            .db
29            .get("last_size")?
30            .map(|v| {
31                let mut arr = [0u8; 8];
32                if v.len() == 8 {
33                    arr.copy_from_slice(&v);
34                }
35                u64::from_be_bytes(arr)
36            })
37            .unwrap_or(0))
38    }
39
40    pub fn last_root(&self) -> Result<String> {
41        Ok(self
42            .db
43            .get("last_root")?
44            .map(|v| String::from_utf8(v.to_vec()).unwrap_or_default())
45            .unwrap_or_default())
46    }
47
48    pub fn put_head(&self, head: &TreeHead) -> Result<()> {
49        self.db
50            .insert("last_size", head.tree_size.to_be_bytes().as_slice())?;
51        self.db.insert("last_root", head.root.as_bytes())?;
52        self.db
53            .insert("last_timestamp", head.timestamp.as_bytes())?;
54        self.db.flush()?;
55        Ok(())
56    }
57}