gosh_database/
lib.rs

1// [[file:../database.note::*imports][imports:1]]
2#[macro_use]
3extern crate diesel;
4#[macro_use]
5extern crate serde;
6#[macro_use]
7extern crate diesel_migrations;
8#[macro_use]
9extern crate derivative;
10
11use std::sync::{Arc, Mutex, MutexGuard};
12
13use diesel::prelude::*;
14// imports:1 ends here
15
16// [[file:../database.note::*mods][mods:1]]
17mod checkpoint;
18mod collection;
19mod core;
20
21pub(crate) mod schema;
22// mods:1 ends here
23
24// [[file:../database.note::f2af4002][f2af4002]]
25use gosh_core::*;
26use gut::prelude::*;
27
28embed_migrations!();
29
30#[derive(Clone, Derivative)]
31#[derivative(Debug)]
32pub struct DbConnection {
33    database_url: String,
34    #[derivative(Debug = "ignore")]
35    connection: Arc<Mutex<SqliteConnection>>,
36}
37
38impl DbConnection {
39    /// Eastablish connection to database specified using env var
40    /// `GOSH_DATABASE_URL`.
41    pub fn establish() -> Result<DbConnection> {
42        // read vars from .env file
43        dotenvy::dotenv().ok();
44
45        let database_url =
46            std::env::var("GOSH_DATABASE_URL").with_context(|| format!("GOSH_DATABASE_URL var not set"))?;
47        debug!("Database: {}", database_url);
48
49        Self::connect(&database_url)
50    }
51
52    /// Connect to database specified using `database_url`.
53    pub fn connect(database_url: &str) -> Result<DbConnection> {
54        // diesel accept &str, not Path
55        let conn = SqliteConnection::establish(database_url)?;
56
57        // see: https://sqlite.org/faq.html#q19
58        //
59        // With synchronous OFF, SQLite continues without syncing as soon as
60        // it has handed data off to the operating system. If the application
61        // running SQLite crashes, the data will be safe, but the database might
62        // become corrupted if the operating system crashes or the computer
63        // loses power before that data has been written to the disk surface. On
64        // the other hand, commits can be orders of magnitude faster with
65        // synchronous OFF.
66        conn.execute("PRAGMA synchronous = OFF")?;
67
68        let conn = Arc::new(Mutex::new(conn));
69
70        let db = DbConnection {
71            database_url: database_url.into(),
72            connection: conn.clone(),
73        };
74
75        db.migrate()?;
76
77        Ok(db)
78    }
79
80    /// Show database url.
81    pub fn database_url(&self) -> &str {
82        &self.database_url
83    }
84
85    pub(crate) fn get(&self) -> MutexGuard<'_, SqliteConnection> {
86        self.connection.lock().expect("cannot lock db connection!")
87    }
88
89    // for schema migrations, sql tables initialization
90    fn migrate(&self) -> Result<()> {
91        let conn = self.get();
92
93        // This will run the necessary migrations.
94        embedded_migrations::run(&*conn)?;
95
96        Ok(())
97    }
98}
99// f2af4002 ends here
100
101// [[file:../database.note::*exports][exports:1]]
102pub mod prelude {
103    pub use crate::checkpoint::Checkpoint;
104    pub use crate::collection::Collection;
105}
106
107pub use crate::checkpoint::CheckpointDb;
108// exports:1 ends here