db.rs

 1mod items;
 2mod kvp;
 3mod migrations;
 4
 5use anyhow::Result;
 6use migrations::MIGRATIONS;
 7use parking_lot::Mutex;
 8use rusqlite::Connection;
 9use std::path::Path;
10use std::sync::Arc;
11
12pub use kvp::*;
13
14pub struct Db {
15    connection: Mutex<Connection>,
16    in_memory: bool,
17}
18
19// To make a migration:
20// Add to the migrations directory, a file with the name:
21//  <NUMBER>_<DESCRIPTION>.sql. Migrations are executed in order of number
22
23impl Db {
24    /// Open or create a database at the given file path. Falls back to in memory database if the
25    /// database at the given path is corrupted
26    pub fn open(path: &Path) -> Result<Arc<Self>> {
27        let conn = Connection::open(path)?;
28
29        Self::initialize(conn, false).or_else(|_| Self::open_in_memory())
30    }
31
32    /// Open a in memory database for testing and as a fallback.
33    pub fn open_in_memory() -> Result<Arc<Self>> {
34        let conn = Connection::open_in_memory()?;
35
36        Self::initialize(conn, true)
37    }
38
39    fn initialize(mut conn: Connection, in_memory: bool) -> Result<Arc<Self>> {
40        MIGRATIONS.to_latest(&mut conn)?;
41
42        Ok(Arc::new(Self {
43            connection: Mutex::new(conn),
44            in_memory,
45        }))
46    }
47}