use mysql_async::Pool;
use mysql_async::prelude::Queryable;
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CancelOutcome {
Completed,
Interrupted,
Uncertain,
}
#[derive(Debug, Error)]
pub enum CancellationError {
#[error("statement deadline exceeded; interrupted via KILL QUERY ({0}ms)")]
Interrupted(u64),
#[error(
"statement deadline exceeded; cancellation inconclusive — connection discarded ({0}ms)"
)]
Uncertain(u64),
}
pub async fn kill_query(pool: &Pool, connection_id: u64) -> Result<(), String> {
let mut control = pool
.get_conn()
.await
.map_err(|e| format!("control connection failed: {e}"))?;
let sql = format!("KILL QUERY {connection_id}");
control
.query_drop(sql.as_str())
.await
.map_err(|e| format!("KILL QUERY failed: {e}"))
}
pub async fn verify_connection_clean(conn: &mut mysql_async::Conn) -> Result<bool, String> {
let row: Option<(i8, i8)> = conn
.exec_first::<(i8, i8), _, _>("SELECT @@autocommit, @@in_transaction", ())
.await
.map_err(|e| format!("verify query failed: {e}"))?;
match row {
Some((_, in_txn)) => Ok(in_txn == 0),
None => Ok(false),
}
}