Skip to main content

memory_core/store/
mod.rs

1pub mod schema;
2pub mod memory;
3pub mod metrics;
4pub mod session;
5pub mod scope;
6pub mod dedup;
7pub mod privacy;
8pub mod relations;
9
10use rusqlite::Connection;
11
12use crate::config::Config;
13use crate::Error;
14
15pub struct Store {
16    conn: Connection,
17    config: Config,
18}
19
20impl Store {
21    pub fn open(path: &str, config: Config) -> crate::Result<Self> {
22        let mut conn = Connection::open(path)?;
23        configure_connection(&conn, &config)?;
24        schema::check_version(&conn)?;
25        run_migrations(&mut conn)?;
26        Ok(Self { conn, config })
27    }
28
29    pub fn open_in_memory() -> crate::Result<Self> {
30        Self::open_in_memory_with_config(Config::default())
31    }
32
33    pub fn open_in_memory_with_config(config: Config) -> crate::Result<Self> {
34        let mut conn = Connection::open_in_memory()?;
35        configure_connection(&conn, &config)?;
36        run_migrations(&mut conn)?;
37        Ok(Self { conn, config })
38    }
39
40    pub fn config(&self) -> &Config {
41        &self.config
42    }
43
44    pub(crate) fn conn(&self) -> &Connection {
45        &self.conn
46    }
47
48    pub fn get_metadata(&self, key: &str) -> crate::Result<Option<String>> {
49        match self.conn.query_row(
50            "SELECT value FROM _metadata WHERE key = ?1",
51            rusqlite::params![key],
52            |row| row.get::<_, String>(0),
53        ) {
54            Ok(val) => Ok(Some(val)),
55            Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
56            Err(e) => Err(e.into()),
57        }
58    }
59
60    pub fn set_metadata(&self, key: &str, value: &str) -> crate::Result<()> {
61        self.conn.execute(
62            "INSERT INTO _metadata (key, value) VALUES (?1, ?2)
63             ON CONFLICT(key) DO UPDATE SET value = excluded.value",
64            rusqlite::params![key, value],
65        )?;
66        Ok(())
67    }
68
69    pub fn schema_version(&self) -> crate::Result<i64> {
70        Ok(self
71            .conn
72            .pragma_query_value(None, "user_version", |r| r.get(0))?)
73    }
74}
75
76fn configure_connection(conn: &Connection, config: &Config) -> rusqlite::Result<()> {
77    conn.execute_batch(&format!(
78        "PRAGMA journal_mode = WAL;
79         PRAGMA busy_timeout = {};
80         PRAGMA synchronous = NORMAL;
81         PRAGMA foreign_keys = ON;
82         PRAGMA cache_size = -{};",
83        config.storage.busy_timeout_ms,
84        config.storage.cache_size_kb
85    ))?;
86    Ok(())
87}
88
89fn run_migrations(conn: &mut Connection) -> crate::Result<()> {
90    let migrations = schema::migrations();
91    migrations
92        .to_latest(conn)
93        .map_err(|e| Error::Migration(e.to_string()))?;
94    Ok(())
95}