use anyhow::Context;
use log::debug;
use sqlx::PgPool;
use time::Duration;
pub fn get_db_url() -> anyhow::Result<String> {
const DB_ADDR: &str = "DATABASE_ADDR";
const DB_NAME: &str = "DATABASE_NAME";
const DB_USERNAME: &str = "DATABASE_USERNAME";
const DB_PASSWORD: &str = "DATABASE_PASSWORD";
let db_addr = if std::env::var(DB_ADDR).is_ok() {
std::env::var(DB_ADDR).unwrap()
} else if dotenvy::var(DB_ADDR).is_ok() {
dotenvy::var(DB_ADDR).unwrap()
} else {
"db".to_string()
};
let db_name = if std::env::var(DB_NAME).is_ok() {
std::env::var(DB_NAME).unwrap()
} else if dotenvy::var(DB_NAME).is_ok() {
dotenvy::var(DB_NAME).unwrap()
} else {
"postgres".to_string()
};
let db_username = if std::env::var(DB_USERNAME).is_ok() {
std::env::var(DB_USERNAME).unwrap()
} else if dotenvy::var(DB_NAME).is_ok() {
dotenvy::var(DB_NAME).unwrap()
} else {
"postgres".to_string()
};
let db_password = if std::env::var(DB_PASSWORD).is_ok() {
std::env::var(DB_PASSWORD).unwrap()
} else {
dotenvy::var(DB_PASSWORD).context(format!("{DB_PASSWORD} must be set"))?
};
debug!(
"Connect to the database: postgres://{}:******@{}/{}",
db_username.clone(),
db_addr.clone(),
db_name.clone()
);
Ok(format!(
"postgres://{db_username}:{db_password}@{db_addr}/{db_name}"
))
}
#[derive(impl_new::New)]
pub struct CleanupParam {
pub food_expiration_period: Duration,
pub check_food_period: Duration,
}
pub async fn cleanup(db: PgPool, food_expiration_period: Duration) -> i64 {
let req: (i64,) = sqlx::query_as(
format!(
r#"
WITH deleted_rows AS (
DELETE FROM food
WHERE expiration_date <= current_date - interval '{} days'
RETURNING *
)
SELECT count(*) as deleted_count FROM deleted_rows
"#,
food_expiration_period.whole_days()
)
.as_str(),
)
.fetch_one(&db)
.await
.unwrap();
let nb_deleted = req.0;
if nb_deleted > 0 {
debug!("{} row(s) deleted by cleanup", nb_deleted);
}
nb_deleted
}