taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

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 }