From 8ea63f0b275248a2871440e30ca5935a5d7f171b Mon Sep 17 00:00:00 2001 From: Greg Heartsfield Date: Fri, 17 Feb 2023 11:15:06 -0600 Subject: [PATCH] feat(NIP-40): sqlite support for event expiration --- src/event.rs | 9 +++++ src/info.rs | 2 +- src/repo/sqlite.rs | 70 +++++++++++++++++++++++++++++++----- src/repo/sqlite_migration.rs | 26 +++++++++++++- src/server.rs | 16 +++++++-- 5 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/event.rs b/src/event.rs index 772b31d..0aff15f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -137,6 +137,15 @@ impl Event { self.kind >= 20000 && self.kind < 30000 } + /// Is this event currently expired? + pub fn is_expired(&self) -> bool { + if let Some(exp) = self.expiration() { + exp <= unix_time() + } else { + false + } + } + /// Determine the time at which this event should expire pub fn expiration(&self) -> Option { let default = "".to_string(); diff --git a/src/info.rs b/src/info.rs index 4ce4b72..ab62f77 100644 --- a/src/info.rs +++ b/src/info.rs @@ -29,7 +29,7 @@ pub struct RelayInfo { /// Convert an Info configuration into public Relay Info impl From for RelayInfo { fn from(c: Settings) -> Self { - let mut supported_nips = vec![1, 2, 9, 11, 12, 15, 16, 20, 22, 33]; + let mut supported_nips = vec![1, 2, 9, 11, 12, 15, 16, 20, 22, 33, 40]; if c.authorization.nip42_auth { supported_nips.push(42); diff --git a/src/repo/sqlite.rs b/src/repo/sqlite.rs index 150269d..256a6a8 100644 --- a/src/repo/sqlite.rs +++ b/src/repo/sqlite.rs @@ -6,7 +6,7 @@ use crate::event::{single_char_tagname, Event}; use crate::hexrange::hex_range; use crate::hexrange::HexSearch; use crate::repo::sqlite_migration::{STARTUP_SQL,upgrade_db}; -use crate::utils::{is_hex}; +use crate::utils::{is_hex,unix_time}; use crate::nip05::{Nip05Name, VerificationRecord}; use crate::subscription::{ReqFilter, Subscription}; use crate::server::NostrMetrics; @@ -135,8 +135,8 @@ impl SqliteRepo { } // ignore if the event hash is a duplicate. let mut ins_count = tx.execute( - "INSERT OR IGNORE INTO event (event_hash, created_at, kind, author, delegated_by, content, first_seen, hidden) VALUES (?1, ?2, ?3, ?4, ?5, ?6, strftime('%s','now'), FALSE);", - params![id_blob, e.created_at, e.kind, pubkey_blob, delegator_blob, event_str] + "INSERT OR IGNORE INTO event (event_hash, created_at, expires_at, kind, author, delegated_by, content, first_seen, hidden) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, strftime('%s','now'), FALSE);", + params![id_blob, e.created_at, e.expiration(), e.kind, pubkey_blob, delegator_blob, event_str] )? as u64; if ins_count == 0 { // if the event was a duplicate, no need to insert event or @@ -251,7 +251,8 @@ impl SqliteRepo { impl NostrRepo for SqliteRepo { async fn start(&self) -> Result<()> { - db_checkpoint_task(self.maint_pool.clone(), Duration::from_secs(60), self.checkpoint_in_progress.clone()).await + db_checkpoint_task(self.maint_pool.clone(), Duration::from_secs(60), self.checkpoint_in_progress.clone()).await?; + cleanup_expired(self.maint_pool.clone(), Duration::from_secs(5), self.write_in_progress.clone()).await } async fn migrate_up(&self) -> Result { @@ -280,10 +281,10 @@ impl NostrRepo for SqliteRepo { let wr = SqliteRepo::persist_event(&mut conn, &e); match wr { Err(SqlError(rusqlite::Error::SqliteFailure(e,_))) => { - // this basically means that NIP-05 was - // writing to the database between us reading - // and promoting the connection to a write - // lock. + // this basically means that NIP-05 or another + // writer was using the database between us + // reading and promoting the connection to a + // write lock. info!("event write failed, DB locked (attempt: {}); sqlite err: {}", attempts, e.extended_code); }, @@ -375,7 +376,7 @@ impl NostrRepo for SqliteRepo { let mut last_successful_send = Instant::now(); // execute the query. // make the actual SQL query (with parameters inserted) available - conn.trace(Some(|x| {trace!("SQL trace: {:?}", x)})); + conn.trace(Some(|x| {info!("SQL trace: {:?}", x)})); let mut stmt = conn.prepare_cached(&q)?; let mut event_rows = stmt.query(rusqlite::params_from_iter(p))?; @@ -854,6 +855,9 @@ fn query_from_filter(f: &ReqFilter) -> (String, Vec>, Option