use nodedb_types::TenantId;
use redb::ReadableTable;
use super::stats::table::{GRAPH_STATS, collection_stat_prefix};
use super::store::{EDGES, EdgeStore, REVERSE_EDGES, redb_err};
impl EdgeStore {
pub fn purge_tenant(&self, db: u64, tid: TenantId) -> crate::Result<usize> {
let t = tid.as_u64();
let write_txn = self
.db
.begin_write()
.map_err(|e| redb_err("begin_write", e))?;
let mut removed = 0;
{
let mut edges = write_txn
.open_table(EDGES)
.map_err(|e| redb_err("open edges", e))?;
let keys: Vec<String> = edges
.range((db, t, "")..(db, t + 1, ""))
.map_err(|e| redb_err("edge range", e))?
.map(|r| r.map(|(k, _)| k.value().2.to_string()))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| redb_err("range iter", e))?;
removed += keys.len();
for key in &keys {
edges
.remove((db, t, key.as_str()))
.map_err(|e| redb_err("edge remove", e))?;
}
}
{
let mut rev_t = write_txn
.open_table(REVERSE_EDGES)
.map_err(|e| redb_err("open reverse", e))?;
let keys: Vec<String> = rev_t
.range((db, t, "")..(db, t + 1, ""))
.map_err(|e| redb_err("rev range", e))?
.map(|r| r.map(|(k, _)| k.value().2.to_string()))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| redb_err("range iter", e))?;
removed += keys.len();
for key in &keys {
rev_t
.remove((db, t, key.as_str()))
.map_err(|e| redb_err("reverse remove", e))?;
}
}
{
let mut stats_t = write_txn
.open_table(GRAPH_STATS)
.map_err(|e| redb_err("open graph_stats", e))?;
let keys: Vec<String> = stats_t
.range((db, t, "")..(db, t + 1, ""))
.map_err(|e| redb_err("stats range", e))?
.map(|r| r.map(|(k, _)| k.value().2.to_string()))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| redb_err("range iter", e))?;
for key in &keys {
stats_t
.remove((db, t, key.as_str()))
.map_err(|e| redb_err("stats remove", e))?;
}
}
write_txn
.commit()
.map_err(|e| redb_err("commit tenant purge", e))?;
Ok(removed)
}
pub fn purge_collection(
&self,
db: u64,
tid: TenantId,
collection: &str,
) -> crate::Result<usize> {
let t = tid.as_u64();
let prefix = format!("{collection}\x00");
let prefix_end = format!("{collection}\x01");
let write_txn = self
.db
.begin_write()
.map_err(|e| redb_err("begin_write", e))?;
let mut removed = 0;
{
let mut edges = write_txn
.open_table(EDGES)
.map_err(|e| redb_err("open edges", e))?;
let keys: Vec<String> = edges
.range((db, t, prefix.as_str())..(db, t, prefix_end.as_str()))
.map_err(|e| redb_err("edge range", e))?
.map(|r| r.map(|(k, _)| k.value().2.to_string()))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| redb_err("range iter", e))?;
removed += keys.len();
for key in &keys {
edges
.remove((db, t, key.as_str()))
.map_err(|e| redb_err("edge remove", e))?;
}
}
{
let mut rev_t = write_txn
.open_table(REVERSE_EDGES)
.map_err(|e| redb_err("open reverse", e))?;
let keys: Vec<String> = rev_t
.range((db, t, prefix.as_str())..(db, t, prefix_end.as_str()))
.map_err(|e| redb_err("rev range", e))?
.map(|r| r.map(|(k, _)| k.value().2.to_string()))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| redb_err("range iter", e))?;
for key in &keys {
rev_t
.remove((db, t, key.as_str()))
.map_err(|e| redb_err("reverse remove", e))?;
}
}
{
let stats_prefix = collection_stat_prefix(collection);
let stats_prefix_end = format!("{collection}\x01");
let mut stats_t = write_txn
.open_table(GRAPH_STATS)
.map_err(|e| redb_err("open graph_stats", e))?;
let keys: Vec<String> = stats_t
.range((db, t, stats_prefix.as_str())..(db, t, stats_prefix_end.as_str()))
.map_err(|e| redb_err("stats range", e))?
.map(|r| r.map(|(k, _)| k.value().2.to_string()))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| redb_err("range iter", e))?;
for key in &keys {
stats_t
.remove((db, t, key.as_str()))
.map_err(|e| redb_err("stats remove", e))?;
}
}
write_txn
.commit()
.map_err(|e| redb_err("commit collection purge", e))?;
Ok(removed)
}
}