use std::sync::Arc;
use arrow_schema::{DataType, Field, Schema, SchemaRef};
use crate::session::JammiSession;
use crate::store::mutable::definition::{MutableTableDefinitionBuilder, MutableTableId};
use super::error::AuditError;
pub const AUDIT_TABLE_NAME: &str = "_jammi_search_audit";
pub const AUDIT_TOPIC: &str = "jammi.audit.search.v1";
pub fn is_reserved_table_name(name: &str) -> bool {
name.starts_with("_jammi_")
}
pub fn audit_schema() -> SchemaRef {
Arc::new(Schema::new(vec![
Field::new("query_id", DataType::Utf8, false),
Field::new("model_id", DataType::Utf8, false),
Field::new("model_version", DataType::Utf8, false),
Field::new("query_lineage", DataType::Utf8, false),
Field::new("top_k_result_ids", DataType::Utf8, false),
Field::new("retrieval_scores", DataType::Utf8, false),
Field::new("executed_at", DataType::Int64, false),
Field::new("signature", DataType::Utf8, false),
]))
}
pub fn audit_table_id() -> Result<MutableTableId, AuditError> {
MutableTableId::new(AUDIT_TABLE_NAME)
.map_err(|e| AuditError::Storage(format!("audit table id: {e}")))
}
pub async fn ensure_table_exists(session: &JammiSession) -> Result<(), AuditError> {
let id = audit_table_id()?;
let exists = session
.mutable_tables()
.list_all()
.await
.map_err(|e| AuditError::Storage(e.to_string()))?
.iter()
.any(|def| def.id == id);
if exists {
return Ok(());
}
let def = MutableTableDefinitionBuilder::new(id, audit_schema())
.primary_key(vec!["query_id".to_string()])
.order_column("executed_at")
.build()
.map_err(|e| AuditError::Storage(e.to_string()))?;
session
.register_mutable_table_unchecked(def)
.await
.map_err(|e| AuditError::Storage(e.to_string()))?;
Ok(())
}