lib.rs (2991B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024-2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 17 use std::{ 18 path::Path, 19 str::FromStr, 20 sync::{ 21 OnceLock, 22 atomic::{AtomicUsize, Ordering}, 23 }, 24 }; 25 26 use sqlx::{ 27 PgPool, 28 postgres::{PgConnectOptions, PgPoolOptions}, 29 }; 30 31 use taler_api::config::DbCfg; 32 use taler_common::{ 33 config::{Config, parser::ConfigSource}, 34 db::{dbinit, pool}, 35 log::taler_logger, 36 }; 37 use tracing_subscriber::util::SubscriberInitExt; 38 39 pub use axum::Router; 40 pub mod json; 41 pub mod routine; 42 pub mod server; 43 44 pub async fn db_test_setup(src: ConfigSource) -> PgPool { 45 let cfg = Config::from_file(src, None::<&str>).unwrap(); 46 let name = format!("{}db-postgres", src.component_name); 47 let sect = cfg.section(&name); 48 let db_cfg = DbCfg::parse(sect).unwrap(); 49 db_test_setup_manual(db_cfg.sql_dir.as_ref(), src.component_name).await 50 } 51 52 pub async fn db_test_setup_manual(sql_dir: &Path, component_name: &str) -> PgPool { 53 println!("{sql_dir:?} {component_name}"); 54 setup_tracing(); 55 let cfg = test_db().await; 56 let pool = pool(cfg, &component_name.replace("-", "_")).await.unwrap(); 57 let mut conn = pool.acquire().await.unwrap(); 58 59 dbinit(&mut conn, sql_dir, component_name, true) 60 .await 61 .unwrap(); 62 pool 63 } 64 65 static MASTER_POOL: OnceLock<PgPool> = OnceLock::new(); 66 67 const DB: &str = "postgres:///taler_rust_check"; 68 static NB_DB: AtomicUsize = AtomicUsize::new(0); 69 70 async fn test_db() -> PgConnectOptions { 71 let master = MASTER_POOL.get_or_init(|| { 72 PgPoolOptions::new() 73 .max_connections(20) 74 .test_before_acquire(false) 75 .after_release(|_conn, _| Box::pin(async move { Ok(false) })) 76 .connect_lazy(DB) 77 .expect("pg pool") 78 }); 79 let idx = NB_DB.fetch_add(1, Ordering::Relaxed); 80 // Cleanup test db 81 let name = format!("taler_rust_test_{idx}"); 82 let mut conn = master.acquire().await.unwrap(); 83 sqlx::raw_sql(&format!("DROP DATABASE IF EXISTS {name}")) 84 .execute(&mut *conn) 85 .await 86 .unwrap(); 87 sqlx::raw_sql(&format!("CREATE DATABASE {name}")) 88 .execute(&mut *conn) 89 .await 90 .unwrap(); 91 drop(conn); 92 PgConnectOptions::from_str(&format!("postgresql:/{name}")).unwrap() 93 } 94 95 fn setup_tracing() { 96 taler_logger(None).try_init().ok(); 97 }