whos_your_daddy_common 0.1.2

Common source code for the Who's Your Daddy projects, like the Enumerator and Presenter.
Documentation
//! Database-related shared utilities and types.
//!
//! This module is reserved for common database helpers shared across crates.
//! It may include connection helpers or query abstractions in the future.

// Custom crates.
use crate::config::{self, DatabaseConfig};
use crate::error::Error;
use crate::official::Official;


#[cfg(feature = "postgres")]
use sqlx::{Postgres, Pool, PgPool};


// Public crates.
use tracing::{debug, error};

/// The `build_pgsql_url` function constructs a properly formatted URL for
/// connecting to a PostgreSQL server using the given parameters.
///
/// # Parameters
/// ## `host`
/// The `host` parameter specifies the host name that the PostgreSQL servier
/// is running on.
///
/// ## `port`
/// The `port` parameter specifies the network port the PostgreSQL server is
/// listening on.
///
/// ## `user`
/// The `user` parameter specifies the user name for the account to interact
/// with the PostgreSQL server with.
///
/// ## `password`
/// The `password` parameter specifies the password for the account to interact
/// with the PostgreSQL server with.
///
/// ## `db`
/// The `db` parameter specifies the name of the database within the PostgreSQL
/// server to interact with.
///
/// # Returns
/// This function returns a String object representing the PostgreSQL connection
/// URL.
pub fn build_pgsql_url(host: &str, port: i32, user: &str, password: &str, db: &str) -> String {
    format!("postgres://{user}:{password}@{host}:{port}/{db}")
}

/// The `PgClient` struct maintains data needed to easily interact with a
/// PostgreSQL database.
#[cfg(feature = "postgres")]
pub struct PgClient {
    /// The `conn_pool` member manages the available connections to the
    /// PostgreSQL server.
    pub conn_pool: Pool<Postgres>,

    /// The `url` member indicates the PostgreSQL database to connect to.
    pub url: String
}

#[cfg(feature = "postgres")]
impl PgClient {
    /// This function constructs a `PgClient` struct for interacting with a
    /// PostgreSQL database.
    ///
    /// # Returns
    /// This function returns a Result variant:
    /// - `Ok()` containing the `PgClient` struct.
    /// - `Err()` describing the error.
    pub async fn new() -> Result<Self, Error> {

        // Obtain database configuration from the environment.
        let config = DatabaseConfig::from_env()?;

        PgClient::from_config(config).await
    } // new

    /// The `from_config` function attempts to construct a `PgClient` struct
    /// from the data within the provided `DatabaseConfig` struct.
    ///
    /// # Parameters
    /// ## `config`
    /// A `DatabaseConfig` struct containing data for interacting with a
    /// PostgreSQL database.
    ///
    /// # Returns
    /// This function returns a `Result` variant:
    /// - `Ok()` containing a `PgClient` struct.
    /// - `Err()` describing the error.
    pub async fn from_config(config: DatabaseConfig) -> Result<Self, Error> {

        // Construct the database URL.
        let db_url = build_pgsql_url(
            &config.host,
            config.port,
            &config.user,
            &config.password,
            &config.name
        );

        // Construct the Postgres connection pool, which will allow use to
        // connect to the server and make requests.
        let connection_pool = match PgPool::connect(&db_url).await {
            Ok(new_pool) => new_pool,
            Err(e) => {
                error!(
                    "Failed to obtain a connection pool for the PostgreSQL database server: {e}"
                );
    
                return Err(Error::PgConnectError(e.to_string()));
            }
        };

        Ok(PgClient {
            conn_pool: connection_pool,
            url: db_url
        })
    } // from_config
} // PgClient