From 17c4ad00db17a983edcac971db08151ccc7c1230 Mon Sep 17 00:00:00 2001 From: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Date: Sat, 1 Aug 2026 15:36:45 -0400 Subject: [PATCH] fix(db): delete SQLite discovery events Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> --- crates/buzz-db/src/lib.rs | 9 +++++ crates/buzz-db/src/sqlite.rs | 66 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/crates/buzz-db/src/lib.rs b/crates/buzz-db/src/lib.rs index 8c96f22a2..d4c76b2cc 100644 --- a/crates/buzz-db/src/lib.rs +++ b/crates/buzz-db/src/lib.rs @@ -5976,6 +5976,15 @@ impl Db { channel_id: Uuid, relay_pubkey: &[u8], ) -> Result { + if let DbBackend::SQLite(pool) = &self.backend { + return sqlite::soft_delete_discovery_events( + pool, + community_id, + channel_id, + relay_pubkey, + ) + .await; + } let result = sqlx::query( "UPDATE events SET deleted_at = NOW() \ WHERE community_id = $1 AND channel_id = $2 AND pubkey = $3 AND deleted_at IS NULL AND kind IN (39000, 39001, 39002)", diff --git a/crates/buzz-db/src/sqlite.rs b/crates/buzz-db/src/sqlite.rs index 52602adeb..c392924fc 100644 --- a/crates/buzz-db/src/sqlite.rs +++ b/crates/buzz-db/src/sqlite.rs @@ -551,6 +551,21 @@ pub(crate) async fn ensure_configured_community( }) } +pub(crate) async fn soft_delete_discovery_events( + pool: &SqlitePool, + community: CommunityId, + channel_id: Uuid, + relay_pubkey: &[u8], +) -> Result { + Ok(sqlx::query("DELETE FROM events WHERE community_id = ?1 AND channel_id = ?2 AND pubkey = ?3 AND kind IN (39000,39001,39002)") + .bind(community.as_uuid().to_string()) + .bind(channel_id.to_string()) + .bind(relay_pubkey) + .execute(pool) + .await? + .rows_affected()) +} + pub(crate) async fn insert_event( pool: &SqlitePool, community: CommunityId, @@ -4782,6 +4797,57 @@ mod tests { ); } + #[tokio::test] + async fn discovery_delete_is_channel_relay_kind_and_tenant_scoped() { + let pool = connect("sqlite::memory:").await.unwrap(); + let a = ensure_configured_community(&pool, "discovery-a.example") + .await + .unwrap() + .id; + let b = ensure_configured_community(&pool, "discovery-b.example") + .await + .unwrap() + .id; + let relay = Keys::generate(); + let other = Keys::generate(); + let channel = Uuid::new_v4(); + let other_channel = Uuid::new_v4(); + let mut events = Vec::new(); + for (index, kind, keys, channel_id, community) in [ + (0, 39000, &relay, channel, a), + (1, 39001, &relay, channel, a), + (2, 39002, &relay, channel, a), + (3, 9, &relay, channel, a), + (4, 39000, &relay, other_channel, a), + (5, 39000, &other, channel, a), + (6, 39000, &relay, channel, b), + ] { + let event = EventBuilder::new(Kind::Custom(kind), format!("discovery-{index}")) + .custom_created_at(Timestamp::from(100 + index as u64)) + .sign_with_keys(keys) + .unwrap(); + insert_event(&pool, community, &event, Some(channel_id)) + .await + .unwrap(); + events.push((community, event)); + } + assert_eq!( + soft_delete_discovery_events(&pool, a, channel, &relay.public_key().to_bytes()) + .await + .unwrap(), + 3 + ); + for (index, (community, event)) in events.iter().enumerate() { + assert_eq!( + get_event_by_id(&pool, *community, event.id.as_bytes()) + .await + .unwrap() + .is_some(), + index >= 3 + ); + } + } + #[tokio::test] async fn direct_event_helpers_match_count_order_scope_and_delete_contracts() { let pool = connect("sqlite::memory:").await.unwrap();