//! Storage and persistence logic. use std::str::FromStr; use std::sync::Arc; use serde::Deserialize; use sqlx::sqlite::SqliteConnectOptions; use sqlx::{ConnectOptions, Connection, SqliteConnection}; use tokio::sync::Mutex; use crate::prelude::*; mod auth; mod dialog; mod room; mod user; #[derive(Deserialize, Debug, Clone)] pub struct StorageConfig { pub db_path: String, } #[derive(Clone)] pub struct Storage { conn: Arc>, } impl Storage { pub async fn open(config: StorageConfig) -> Result { let opts = SqliteConnectOptions::from_str(&*config.db_path)?.create_if_missing(true); let mut conn = opts.connect().await?; let migrator = sqlx::migrate!(); migrator.run(&mut conn).await?; log::info!("Migrations passed"); let conn = Arc::new(Mutex::new(conn)); Ok(Storage { conn }) } pub async fn close(self) { let res = match Arc::try_unwrap(self.conn) { Ok(e) => e, Err(_) => { tracing::error!("failed to acquire DB ownership on shutdown"); return; } }; let res = res.into_inner(); match res.close().await { Ok(_) => {} Err(e) => { tracing::error!("Failed to close the DB connection: {e:?}"); } } } }