use crate::dal::unified::DAL;
use crate::error::ValidationError;
#[cfg(feature = "postgres")]
use diesel::prelude::*;
#[cfg(feature = "postgres")]
#[derive(Queryable)]
#[diesel(table_name = crate::database::schema::postgres::agent_capacity_limits)]
struct AgentLimitRow {
#[allow(dead_code)]
pub tenant_id: String,
pub max_agents: i32,
#[allow(dead_code)]
pub created_at: chrono::NaiveDateTime,
#[allow(dead_code)]
pub updated_at: chrono::NaiveDateTime,
}
pub struct AgentLimitsDAL<'a> {
dal: &'a DAL,
}
impl<'a> AgentLimitsDAL<'a> {
pub fn new(dal: &'a DAL) -> Self {
Self { dal }
}
#[cfg(feature = "postgres")]
pub async fn set_tenant_limit(
&self,
tenant_id: &str,
max_agents: u32,
) -> Result<(), ValidationError> {
use crate::database::schema::postgres::agent_capacity_limits as t;
let tenant = tenant_id.to_string();
let max = max_agents as i32;
let conn = self
.dal
.database
.get_postgres_connection()
.await
.map_err(|e| ValidationError::ConnectionPool(e.to_string()))?;
conn.interact(move |conn| {
diesel::insert_into(t::table)
.values((t::tenant_id.eq(&tenant), t::max_agents.eq(max)))
.on_conflict(t::tenant_id)
.do_update()
.set(t::max_agents.eq(max))
.execute(conn)
})
.await
.map_err(|e| ValidationError::ConnectionPool(e.to_string()))??;
Ok(())
}
#[cfg(feature = "postgres")]
pub async fn get_tenant_limit(&self, tenant_id: &str) -> Result<Option<u32>, ValidationError> {
use crate::database::schema::postgres::agent_capacity_limits as t;
let conn = self
.dal
.database
.get_postgres_connection()
.await
.map_err(|e| ValidationError::ConnectionPool(e.to_string()))?;
let tenant = tenant_id.to_string();
let row: Option<AgentLimitRow> = conn
.interact(move |conn| t::table.find(tenant).first(conn).optional())
.await
.map_err(|e| ValidationError::ConnectionPool(e.to_string()))??;
Ok(row.map(|r| r.max_agents.max(0) as u32))
}
#[cfg(feature = "postgres")]
pub async fn clear_tenant_limit(&self, tenant_id: &str) -> Result<bool, ValidationError> {
use crate::database::schema::postgres::agent_capacity_limits as t;
let conn = self
.dal
.database
.get_postgres_connection()
.await
.map_err(|e| ValidationError::ConnectionPool(e.to_string()))?;
let tenant = tenant_id.to_string();
let n: usize = conn
.interact(move |conn| diesel::delete(t::table.find(tenant)).execute(conn))
.await
.map_err(|e| ValidationError::ConnectionPool(e.to_string()))??;
Ok(n > 0)
}
#[cfg(feature = "postgres")]
pub async fn effective_limit(
&self,
tenant_id: &str,
default: u32,
) -> Result<u32, ValidationError> {
Ok(self.get_tenant_limit(tenant_id).await?.unwrap_or(default))
}
}