use nodedb_types::DatabaseId;
use crate::control::security::identity::AuthenticatedIdentity;
use crate::control::state::SharedState;
use super::super::super::result::{DdlError, DdlResult};
use super::super::auth_support::{require_tenant_admin, status};
const ALERT_RULES_CRDT_COLLECTION: &str = "_alert_rules";
fn err(sqlstate: &str, message: String) -> DdlError {
DdlError {
sqlstate: sqlstate.to_string(),
message,
}
}
pub fn alert_exists(
state: &SharedState,
identity: &AuthenticatedIdentity,
database_id: DatabaseId,
name: &str,
) -> bool {
let tid = identity.tenant_id.as_u64();
state
.alert_registry
.get(database_id.as_u64(), tid, name)
.is_some()
}
pub fn drop_alert(
state: &SharedState,
identity: &AuthenticatedIdentity,
database_id: DatabaseId,
parts: &[&str],
) -> Result<Vec<DdlResult>, DdlError> {
require_tenant_admin(identity, "drop alerts")?;
if parts.len() < 3 {
return Err(err("42601", "syntax: DROP ALERT <name>".to_string()));
}
let name = parts[2].to_lowercase();
let tenant_id = identity.tenant_id.as_u64();
if state
.alert_registry
.get(database_id.as_u64(), tenant_id, &name)
.is_none()
{
return Err(err("42704", format!("alert '{name}' does not exist")));
}
let catalog = state.credentials.catalog();
catalog
.delete_alert_rule(database_id.as_u64(), tenant_id, &name)
.map_err(|e| err("XX000", format!("catalog delete: {e}")))?;
{
let delta = crate::event::crdt_sync::types::OutboundDelta {
collection: ALERT_RULES_CRDT_COLLECTION.into(),
document_id: name.clone(),
payload: Vec::new(),
op: crate::event::crdt_sync::types::DeltaOp::Delete,
lsn: 0,
tenant_id,
peer_id: state.node_id,
sequence: 0,
};
state.crdt_sync_delivery.enqueue(tenant_id, delta);
}
state.alert_hysteresis.remove_alert(tenant_id, &name);
state
.alert_registry
.unregister(database_id.as_u64(), tenant_id, &name);
state.audit_record(
crate::control::security::audit::AuditEvent::AdminAction,
Some(identity.tenant_id),
&identity.username,
&format!("DROP ALERT {name}"),
);
tracing::info!(name, "alert rule dropped");
Ok(status("DROP ALERT"))
}