use sqlx::PgPool;
use tracing::instrument;
use std::collections::HashMap;
use cala_types::velocity::VelocityContextAccountValues;
use crate::primitives::{AccountId, VelocityControlId};
use super::{super::error::*, value::*};
#[derive(Debug, Clone)]
pub struct AccountControlRepo {
_pool: PgPool,
}
impl AccountControlRepo {
pub fn new(pool: &PgPool) -> Self {
Self {
_pool: pool.clone(),
}
}
#[instrument(name = "account_control.create_in_op", skip_all, err(level = "warn"))]
pub async fn create_in_op(
&self,
op: &mut impl es_entity::AtomicOperation,
control: AccountVelocityControl,
) -> Result<(), VelocityError> {
sqlx::query!(
r#"INSERT INTO cala_velocity_account_controls (account_id, velocity_control_id, values)
VALUES ($1, $2, $3)"#,
control.account_id as AccountId,
control.control_id as VelocityControlId,
serde_json::to_value(control).expect("Failed to serialize control values"),
)
.execute(op.as_executor())
.await?;
Ok(())
}
#[instrument(
name = "account_control.find_for_enforcement",
skip_all,
err(level = "warn")
)]
pub async fn find_for_enforcement(
&self,
op: impl es_entity::IntoOneTimeExecutor<'_>,
account_ids: &[AccountId],
) -> Result<
HashMap<AccountId, (VelocityContextAccountValues, Vec<AccountVelocityControl>)>,
VelocityError,
> {
let rows = op
.into_executor()
.fetch_all(sqlx::query!(
r#"SELECT values, velocity_context_values as "velocity_context_values!: VelocityContextAccountValues"
FROM cala_velocity_account_controls v
JOIN cala_accounts a
ON v.account_id = a.id
WHERE account_id = ANY($1)"#,
account_ids as &[AccountId],
))
.await?;
let mut res: HashMap<AccountId, (VelocityContextAccountValues, Vec<_>)> = HashMap::new();
for row in rows {
let values: AccountVelocityControl =
serde_json::from_value(row.values).expect("Failed to deserialize control values");
res.entry(values.account_id)
.or_insert_with(|| (row.velocity_context_values, Vec::new()))
.1
.push(values);
}
Ok(res)
}
}