1use hoprd_migration::{MigratorMetadata, MigratorTrait};
2use sea_orm::SqlxSqliteConnector;
3use sqlx::pool::PoolOptions;
4use sqlx::sqlite::{SqliteAutoVacuum, SqliteConnectOptions, SqliteJournalMode, SqliteSynchronous};
5use sqlx::{ConnectOptions, SqlitePool};
6use std::path::Path;
7use std::time::Duration;
8use tracing::log::LevelFilter;
9
10use crate::HoprdDbAllOperations;
11
12#[derive(Debug, Clone)]
13pub struct HoprdDb {
14 pub(crate) metadata: sea_orm::DatabaseConnection,
15}
16
17pub const SQL_DB_METADATA_FILE_NAME: &str = "hopr_metadata.db";
18
19impl HoprdDb {
20 pub async fn new(directory: String) -> Result<Self, anyhow::Error> {
21 let dir = Path::new(&directory);
22 std::fs::create_dir_all(dir)
23 .map_err(|e| anyhow::anyhow!("Cannot create main database directory {}: {}", dir.display(), e))?;
24
25 let cfg_template = SqliteConnectOptions::default()
28 .create_if_missing(true)
29 .log_slow_statements(LevelFilter::Warn, Duration::from_millis(150))
30 .log_statements(LevelFilter::Debug)
31 .journal_mode(SqliteJournalMode::Wal)
32 .synchronous(SqliteSynchronous::Normal)
33 .auto_vacuum(SqliteAutoVacuum::Full)
34 .page_size(4096)
36 .pragma("cache_size", "-30000") .pragma("busy_timeout", "1000"); let metadata = PoolOptions::new()
41 .min_connections(0) .acquire_timeout(Duration::from_secs(60)) .idle_timeout(Some(Duration::from_secs(10 * 60))) .max_lifetime(Some(Duration::from_secs(30 * 60))) .max_connections(50) .connect_with(cfg_template.filename(dir.join(SQL_DB_METADATA_FILE_NAME)))
47 .await?;
48
49 Self::new_sqlx_sqlite(metadata).await
50 }
51
52 pub async fn new_in_memory() -> Self {
53 Self::new_sqlx_sqlite(SqlitePool::connect(":memory:").await.unwrap())
54 .await
55 .unwrap()
56 }
57
58 async fn new_sqlx_sqlite(metadata_db: SqlitePool) -> Result<Self, anyhow::Error> {
59 let metadata_db = SqlxSqliteConnector::from_sqlx_sqlite_pool(metadata_db);
60
61 MigratorMetadata::up(&metadata_db, None)
62 .await
63 .expect("cannot apply database migration");
64
65 Ok(Self { metadata: metadata_db })
66 }
67}
68
69impl HoprdDbAllOperations for HoprdDb {}
70
71#[cfg(test)]
72mod tests {
73 use crate::db::HoprdDb;
74 use hoprd_migration::{MigratorMetadata, MigratorTrait};
75
76 #[async_std::test]
77 async fn test_basic_db_init() {
78 let db = HoprdDb::new_in_memory().await;
79
80 MigratorMetadata::status(&db.metadata).await.expect("status must be ok");
81 }
82}