aphomie_db_client 0.1.1

Common DTOs for communication over network for the BMS Uni project
Documentation
use anyhow::bail;
use bms_dtos::MetadataDb;
use tokio_postgres::{Client, Config, NoTls, Row};

type Result<T> = core::result::Result<T, anyhow::Error>;

pub struct AphomieDbClient {
    db_client: Client,
}

impl AphomieDbClient {
    pub async fn new(host: Option<&str>, port: Option<u16>) -> Result<Self> {
        let host = if let Some(v) = host { v } else { "localhost" };

        let port = if let Some(v) = port { v } else { 5432 };

        let mut config = Config::new();
        config
            .user("dat7")
            .password("dat7")
            .dbname("dat7")
            .host(host)
            .port(port);

        let (db_client, connection) = config.connect(NoTls).await?;

        tokio::spawn(async move {
            if let Err(e) = connection.await {
                eprintln!("connection error: {}", e);
            }
        });

        Ok(Self { db_client })
    }

    pub async fn insert_metadata(&self, metadata: &MetadataDb) -> Result<Vec<MetadataDb>> {
        insert_metadata(
            &self.db_client,
            &metadata.log_id,
            &metadata.source,
            &metadata.unit,
        )
        .await
        .map(|v| v.iter().map(|r| MetadataDb::from(r)).collect())
    }

    pub async fn get_metadata_by_source(&self, source: &str) -> Result<Vec<MetadataDb>> {
        get_metadata_by_source(&self.db_client, source)
            .await
            .map(|v| v.iter().map(|r| MetadataDb::from(r)).collect())
    }

    pub async fn get_all_metadata(&self) -> Result<Vec<MetadataDb>> {
        get_all_metadata(&self.db_client)
            .await
            .map(|v| v.iter().map(|r| MetadataDb::from(r)).collect())
    }
}

async fn insert_metadata(
    client: &Client,
    log_id: &i64,
    source: &str,
    unit: &str,
) -> Result<Vec<Row>> {
    let stmt = "INSERT INTO metadata (log_id, source, unit) VALUES ($1, $2, $3) RETURNING *;";

    match client.query(stmt, &[log_id, &source, &unit]).await {
        Ok(v) => Ok(v),
        Err(e) => {
            bail!("error querying database: {e}");
        }
    }
}

async fn get_metadata_by_source(client: &Client, source: &str) -> Result<Vec<Row>> {
    let stmt = "SELECT * FROM metadata WHERE source = $1;";

    match client.query(stmt, &[&source]).await {
        Ok(v) => Ok(v),
        Err(e) => {
            bail!("error querying database: {e}");
        }
    }
}

async fn get_all_metadata(client: &Client) -> Result<Vec<Row>> {
    let stmt = "SELECT * FROM metadata;";

    match client.query(stmt, &[]).await {
        Ok(v) => Ok(v),
        Err(e) => {
            bail!("error querying database: {e}");
        }
    }
}