1use crate::{constants::DB_FILE, db::HmsDb, prelude::*};
2use diesel::{Connection, SqliteConnection};
3use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
4use hms_common::app_dir_client::AppDirClient;
5
6pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
7
8#[derive(Debug)]
9pub struct HmsDbManager<'a, P>
10where
11 P: AppDirClient,
12{
13 pub app_dir_client: &'a P,
14}
15
16impl<'a, P> HmsDbManager<'a, P>
17where
18 P: AppDirClient,
19{
20 pub fn new(app_dir_client: &'a P) -> HmsDbManager<P> {
21 HmsDbManager { app_dir_client }
22 }
23
24 pub fn db_exists(&self) -> Result<bool> {
25 let db_path = self.app_dir_client.get_app_dir_path()?.join(DB_FILE);
26 Ok(db_path.exists())
27 }
28
29 pub fn db_has_pending_migrations(&self) -> Result<bool> {
30 self.with_db(|db| {
31 db.conn.has_pending_migration(MIGRATIONS).map_err(|e| {
32 HmsDbError::MigrationError(format!("Unable to determine pending migrations: {}", e))
33 })
34 })
35 }
36
37 pub fn run_pending_migrations(&self) -> Result<()> {
38 self.with_db(|db| match db.conn.run_pending_migrations(MIGRATIONS) {
39 Ok(_) => Ok(()),
40 Err(e) => Err(HmsDbError::MigrationError(format!(
41 "Unable to run pending migrations: {}",
42 e
43 ))),
44 })
45 }
46
47 pub fn with_db<F, R>(&self, f: F) -> Result<R>
48 where
49 F: FnOnce(&mut HmsDb) -> Result<R>,
50 {
51 let database_path = self.app_dir_client.get_app_dir_path()?.join(DB_FILE);
52 let mut conn = SqliteConnection::establish(&database_path.to_string_lossy())?;
53
54 conn.transaction(|conn| {
55 let mut db = HmsDb { conn };
56 f(&mut db)
57 })
58 }
59}