lib_hyper_organizator/
postgres.rs

1use crate::settings::PostgresConfig;
2use tower::ServiceBuilder;
3use tracing::info;
4
5pub use submodule::add_database;
6#[cfg(feature = "postgres")]
7pub use submodule::get_connection;
8
9#[cfg(not(feature = "postgres"))]
10mod submodule {
11    use super::*;
12    pub async fn add_database<L>(
13        service_builder: ServiceBuilder<L>,
14        _: PostgresConfig,
15    ) -> ServiceBuilder<L> {
16        info!("No database support");
17        service_builder
18    }
19}
20
21#[cfg(feature = "postgres")]
22mod submodule {
23    use super::*;
24    use crate::typedef::GenericError;
25    use deadpool_postgres::Client;
26    use deadpool_postgres::{Config, ManagerConfig, Pool, RecyclingMethod, Runtime};
27    use http::Request;
28    use tokio_postgres::NoTls;
29    use tower_http::add_extension::AddExtensionLayer;
30    use tower_layer::Stack;
31
32    pub async fn add_database<L>(
33        service_builder: ServiceBuilder<L>,
34        postgres: PostgresConfig,
35    ) -> ServiceBuilder<Stack<AddExtensionLayer<Pool>, L>> {
36        info!("Database support enabled");
37        service_builder.layer(AddExtensionLayer::new(make_database_pool(postgres).await))
38    }
39
40    async fn make_database_pool(postgres: PostgresConfig) -> Pool {
41        let config = Config {
42            host: Some(postgres.host),
43            port: Some(postgres.port),
44            user: Some(postgres.user),
45            password: Some(postgres.password),
46            dbname: Some(postgres.dbname),
47            application_name: Some(postgres.application_name),
48            manager: Some(ManagerConfig {
49                recycling_method: RecyclingMethod::Fast,
50            }),
51            ..Default::default()
52        };
53        let pool = config.create_pool(Some(Runtime::Tokio1), NoTls).unwrap();
54        // check we can connect to the Database, we abort if we can't
55        match pool.get().await {
56            Ok(_) => info!("Connected to database"),
57            Err(e) => panic!("Failed to connect to database: {e},\nusing config: {config:#?}"),
58        }
59
60        pool
61    }
62
63    pub async fn get_connection<T>(request: &Request<T>) -> Result<Client, GenericError> {
64        let pool = request
65            .extensions()
66            .get::<Pool>()
67            .ok_or(GenericError::from("No database connection pool"))?;
68        // let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
69        let connection = pool.get().await?;
70        info!("Got connection from pool");
71        Ok(connection)
72    }
73}