use nodedb_types::error::{NodeDbError, NodeDbResult};
use super::NodeDbLite;
use crate::storage::engine::StorageEngine;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LiteStoredFunction {
pub name: String,
pub parameters: Vec<LiteFunctionParam>,
pub return_type: String,
pub body_sql: String,
pub owner: String,
pub created_at: u64,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LiteFunctionParam {
pub name: String,
pub data_type: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LiteStoredTrigger {
pub name: String,
pub collection: String,
pub timing: String,
pub events: Vec<String>,
pub granularity: String,
pub when_condition: Option<String>,
pub body_sql: String,
pub priority: i32,
pub enabled: bool,
pub execution_mode: String,
pub owner: String,
pub created_at: u64,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LiteStoredProcedure {
pub name: String,
pub parameters: Vec<LiteProcedureParam>,
pub body_sql: String,
pub max_iterations: u64,
pub timeout_secs: u64,
pub owner: String,
pub created_at: u64,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LiteProcedureParam {
pub name: String,
pub data_type: String,
pub direction: String,
}
impl<S: StorageEngine> NodeDbLite<S> {
async fn put_definition(
&self,
prefix: &str,
name: &str,
def: &impl serde::Serialize,
) -> NodeDbResult<()> {
let key = format!("{prefix}:{name}");
let bytes = sonic_rs::to_vec(def).map_err(|e| NodeDbError::storage(e.to_string()))?;
self.storage
.put(nodedb_types::Namespace::Meta, key.as_bytes(), &bytes)
.await?;
Ok(())
}
async fn get_definition<T: serde::de::DeserializeOwned>(
&self,
prefix: &str,
name: &str,
) -> NodeDbResult<Option<T>> {
let key = format!("{prefix}:{name}");
let bytes = self
.storage
.get(nodedb_types::Namespace::Meta, key.as_bytes())
.await?;
match bytes {
Some(b) => {
let def: T =
sonic_rs::from_slice(&b).map_err(|e| NodeDbError::storage(e.to_string()))?;
Ok(Some(def))
}
None => Ok(None),
}
}
async fn list_definitions<T: serde::de::DeserializeOwned>(
&self,
prefix: &str,
) -> NodeDbResult<Vec<T>> {
let scan_prefix = format!("{prefix}:");
let pairs = self
.storage
.scan_prefix(nodedb_types::Namespace::Meta, scan_prefix.as_bytes())
.await?;
let mut defs = Vec::with_capacity(pairs.len());
for (_key, value) in pairs {
if let Ok(d) = sonic_rs::from_slice::<T>(&value) {
defs.push(d);
}
}
Ok(defs)
}
async fn delete_definition(&self, prefix: &str, name: &str) -> NodeDbResult<()> {
let key = format!("{prefix}:{name}");
self.storage
.delete(nodedb_types::Namespace::Meta, key.as_bytes())
.await?;
Ok(())
}
}
impl<S: StorageEngine> NodeDbLite<S> {
pub async fn put_function(&self, func: &LiteStoredFunction) -> NodeDbResult<()> {
self.put_definition("function", &func.name, func).await
}
pub async fn get_function(&self, name: &str) -> NodeDbResult<Option<LiteStoredFunction>> {
self.get_definition("function", name).await
}
pub async fn list_functions(&self) -> NodeDbResult<Vec<LiteStoredFunction>> {
self.list_definitions("function").await
}
pub async fn delete_function(&self, name: &str) -> NodeDbResult<()> {
self.delete_definition("function", name).await
}
pub async fn put_trigger(&self, trigger: &LiteStoredTrigger) -> NodeDbResult<()> {
self.put_definition("trigger", &trigger.name, trigger).await
}
pub async fn get_trigger(&self, name: &str) -> NodeDbResult<Option<LiteStoredTrigger>> {
self.get_definition("trigger", name).await
}
pub async fn list_triggers(&self) -> NodeDbResult<Vec<LiteStoredTrigger>> {
self.list_definitions("trigger").await
}
pub async fn list_triggers_for_collection(
&self,
collection: &str,
) -> NodeDbResult<Vec<LiteStoredTrigger>> {
let all = self.list_triggers().await?;
Ok(all
.into_iter()
.filter(|t| t.collection == collection)
.collect())
}
pub async fn delete_trigger(&self, name: &str) -> NodeDbResult<()> {
self.delete_definition("trigger", name).await
}
pub async fn put_procedure(&self, proc: &LiteStoredProcedure) -> NodeDbResult<()> {
self.put_definition("procedure", &proc.name, proc).await
}
pub async fn get_procedure(&self, name: &str) -> NodeDbResult<Option<LiteStoredProcedure>> {
self.get_definition("procedure", name).await
}
pub async fn list_procedures(&self) -> NodeDbResult<Vec<LiteStoredProcedure>> {
self.list_definitions("procedure").await
}
pub async fn delete_procedure(&self, name: &str) -> NodeDbResult<()> {
self.delete_definition("procedure", name).await
}
}