use crate::db::trees::Tree;
use crate::Db;
const PREFIX: &[u8] = b"tombstone:";
fn tombstone_key(subject: &str) -> Vec<u8> {
let pure = crate::Subject::from_raw(subject, None).pure_id();
let mut key = Vec::with_capacity(PREFIX.len() + pure.len());
key.extend_from_slice(PREFIX);
key.extend_from_slice(pure.as_bytes());
key
}
pub fn record_tombstone(store: &Db, subject: &str) {
let key = tombstone_key(subject);
let _ = store.kv.insert(Tree::PluginMeta, &key, &[1]);
}
pub fn is_tombstoned(store: &Db, subject: &str) -> bool {
let key = tombstone_key(subject);
store
.kv
.get(Tree::PluginMeta, &key)
.ok()
.flatten()
.is_some()
}
pub fn clear_tombstone(store: &Db, subject: &str) {
let key = tombstone_key(subject);
let _ = store.kv.remove(Tree::PluginMeta, &key);
}
#[cfg(test)]
mod key_normalization_tests {
use super::*;
#[tokio::test]
async fn drive_suffixed_and_bare_subject_share_a_tombstone() {
let db = Db::init_temp("tombstone_key_norm_query").await.unwrap();
let bare = "https://example.test/some-resource";
let drive_suffixed = "https://example.test/some-resource?drive=https://example.test/";
record_tombstone(&db, bare);
assert!(
is_tombstoned(&db, drive_suffixed),
"a `?drive=`-suffixed and bare form of the same subject must normalize to the same tombstone key"
);
}
#[tokio::test]
async fn trailing_slash_and_bare_subject_share_a_tombstone() {
let db = Db::init_temp("tombstone_key_norm_slash").await.unwrap();
let bare = "https://example.test/some-resource";
let trailing_slash = "https://example.test/some-resource/";
record_tombstone(&db, bare);
assert!(
is_tombstoned(&db, trailing_slash),
"a trailing-slash and bare form of the same subject must normalize to the same tombstone key"
);
}
}