feat(infra): add SqliteAppSettingsRepository

This commit is contained in:
2026-03-20 00:17:05 +01:00
parent a3a421c0ac
commit 6732576d06
2 changed files with 86 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
//! SQLite implementation of IAppSettingsRepository.
use async_trait::async_trait;
use sqlx::SqlitePool;
use domain::{DomainError, DomainResult, IAppSettingsRepository};
pub struct SqliteAppSettingsRepository {
pool: SqlitePool,
}
impl SqliteAppSettingsRepository {
pub fn new(pool: SqlitePool) -> Self {
Self { pool }
}
}
#[async_trait]
impl IAppSettingsRepository for SqliteAppSettingsRepository {
async fn get(&self, key: &str) -> DomainResult<Option<String>> {
sqlx::query_scalar::<_, String>("SELECT value FROM app_settings WHERE key = ?")
.bind(key)
.fetch_optional(&self.pool)
.await
.map_err(|e| DomainError::InfrastructureError(e.to_string()))
}
async fn set(&self, key: &str, value: &str) -> DomainResult<()> {
sqlx::query("INSERT OR REPLACE INTO app_settings (key, value) VALUES (?, ?)")
.bind(key)
.bind(value)
.execute(&self.pool)
.await
.map(|_| ())
.map_err(|e| DomainError::InfrastructureError(e.to_string()))
}
async fn get_all(&self) -> DomainResult<Vec<(String, String)>> {
sqlx::query_as::<_, (String, String)>("SELECT key, value FROM app_settings ORDER BY key")
.fetch_all(&self.pool)
.await
.map_err(|e| DomainError::InfrastructureError(e.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use sqlx::SqlitePool;
use domain::IAppSettingsRepository;
async fn setup() -> SqlitePool {
let pool = SqlitePool::connect(":memory:").await.unwrap();
sqlx::query(
"CREATE TABLE app_settings (key TEXT PRIMARY KEY, value TEXT NOT NULL)"
).execute(&pool).await.unwrap();
sqlx::query("INSERT INTO app_settings VALUES ('library_sync_interval_hours', '6')")
.execute(&pool).await.unwrap();
pool
}
#[tokio::test]
async fn get_returns_seeded_value() {
let repo = SqliteAppSettingsRepository::new(setup().await);
let val = repo.get("library_sync_interval_hours").await.unwrap();
assert_eq!(val, Some("6".to_string()));
}
#[tokio::test]
async fn set_then_get() {
let repo = SqliteAppSettingsRepository::new(setup().await);
repo.set("library_sync_interval_hours", "12").await.unwrap();
let val = repo.get("library_sync_interval_hours").await.unwrap();
assert_eq!(val, Some("12".to_string()));
}
#[tokio::test]
async fn get_all_returns_all_keys() {
let repo = SqliteAppSettingsRepository::new(setup().await);
let all = repo.get_all().await.unwrap();
assert!(!all.is_empty());
assert!(all.iter().any(|(k, _)| k == "library_sync_interval_hours"));
}
}

View File

@@ -18,6 +18,7 @@ pub mod db;
pub mod factory;
pub mod jellyfin;
pub mod provider_registry;
mod app_settings_repository;
mod activity_log_repository;
mod channel_repository;
mod library_repository;
@@ -33,6 +34,8 @@ pub mod local_files;
pub use db::run_migrations;
pub use provider_registry::ProviderRegistry;
#[cfg(feature = "sqlite")]
pub use app_settings_repository::SqliteAppSettingsRepository;
#[cfg(feature = "sqlite")]
pub use activity_log_repository::SqliteActivityLogRepository;
#[cfg(feature = "sqlite")]