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