use std::sync::Arc; use anyhow::Context; use domain::ports::{ AuthService, LocalApContentQuery, MetadataClient, ObjectStorage, PasswordHasher, PosterFetcherClient, UserProfileFieldsRepository, WatchEventRepository, WebhookTokenRepository, }; pub enum DbPool { #[cfg(feature = "sqlite")] Sqlite(sqlx::SqlitePool), #[cfg(feature = "postgres")] Postgres(sqlx::PgPool), } pub struct DatabaseOutput { pub movie: Arc, pub review: Arc, pub diary: Arc, pub stats: Arc, pub user: Arc, pub import_session: Arc, pub import_profile: Arc, pub movie_profile: Arc, pub watchlist: Arc, pub watch_event: Arc, pub webhook_token: Arc, pub person_command: Arc, pub person_query: Arc, pub search_port: Arc, pub search_command: Arc, pub profile_fields: Arc, pub ap_content: Arc, pub wrapup_stats: Arc, pub wrapup_repo: Arc, pub db_pool: DbPool, } pub async fn build_database_adapters(backend: &str, url: &str) -> anyhow::Result { match backend { #[cfg(feature = "postgres")] "postgres" => { let w = postgres::wire(url) .await .context("PostgreSQL connection failed")?; let (pc, pq) = postgres::create_person_adapter(w.pool.clone()); let (sc, sp) = postgres_search::create_search_adapter(w.pool.clone()); let pf = postgres::create_profile_fields_repo(w.pool.clone()); let we: Arc = Arc::new(postgres::PostgresWatchEventRepository::new(w.pool.clone())); let wt: Arc = Arc::new( postgres::PostgresWebhookTokenRepository::new(w.pool.clone()), ); Ok(DatabaseOutput { movie: w.movie, review: w.review, diary: w.diary, stats: w.stats, user: w.user, import_session: w.import_session, import_profile: w.import_profile, movie_profile: w.movie_profile, watchlist: w.watchlist, watch_event: we, webhook_token: wt, person_command: pc, person_query: pq, search_port: sp, search_command: sc, profile_fields: pf, ap_content: w.ap_content, wrapup_stats: w.wrapup_stats, wrapup_repo: w.wrapup_repo, db_pool: DbPool::Postgres(w.pool), }) } #[cfg(feature = "sqlite")] _ => { let w = sqlite::wire(url) .await .context("SQLite connection failed")?; let (pc, pq) = sqlite::create_person_adapter(w.pool.clone()); let (sc, sp) = sqlite_search::create_search_adapter(w.pool.clone()); let pf = sqlite::create_profile_fields_repo(w.pool.clone()); let we: Arc = Arc::new(sqlite::SqliteWatchEventRepository::new(w.pool.clone())); let wt: Arc = Arc::new(sqlite::SqliteWebhookTokenRepository::new(w.pool.clone())); Ok(DatabaseOutput { movie: w.movie, review: w.review, diary: w.diary, stats: w.stats, user: w.user, import_session: w.import_session, import_profile: w.import_profile, movie_profile: w.movie_profile, watchlist: w.watchlist, watch_event: we, webhook_token: wt, person_command: pc, person_query: pq, search_port: sp, search_command: sc, profile_fields: pf, ap_content: w.ap_content, wrapup_stats: w.wrapup_stats, wrapup_repo: w.wrapup_repo, db_pool: DbPool::Sqlite(w.pool), }) } #[cfg(not(feature = "sqlite"))] _ => anyhow::bail!( "DATABASE_BACKEND={backend} is not supported by this build (enable sqlite or postgres feature)" ), } } pub fn build_auth_adapters() -> anyhow::Result<(Arc, Arc)> { auth::create() } pub fn build_metadata_client() -> anyhow::Result> { metadata::create() } pub fn build_poster_fetcher() -> anyhow::Result> { poster_fetcher::create() } pub fn build_object_storage() -> anyhow::Result> { object_storage::create() } pub fn build_profile_fields_repo( pool: &DbPool, ) -> anyhow::Result> { match pool { #[cfg(feature = "postgres")] DbPool::Postgres(pool) => Ok(postgres::create_profile_fields_repo(pool.clone())), #[cfg(feature = "sqlite")] DbPool::Sqlite(pool) => Ok(sqlite::create_profile_fields_repo(pool.clone())), #[cfg(not(feature = "sqlite"))] _ => anyhow::bail!("no profile fields repo for this backend"), } }