nostr-rs-relay

My dev fork of nostr-rs-relay
git clone git://jb55.com/nostr-rs-relay
Log | Files | Refs | README | LICENSE

commit 4ad483090edc45aaf971217779202976495b4bde
parent 9b351aab9bd78308841a9eb929c330ec1966c1f8
Author: William Casarin <jb55@jb55.com>
Date:   Mon,  9 May 2022 13:39:49 -0700

feat(NIP-01): Implement limit

This was quickly sneaked in by fiatjaf per my request[0], it makes many
queries more efficient and allows for paging when combined with until.

It is a bit weird to have multiple limits on each filter... for now we
just choose any or the last limit seen.

[0]: https://github.com/nostr-protocol/nips/commit/a4aea5337fe6b93e55f9dae1974ead962c1997e8

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Msrc/db.rs | 12+++++++++++-
Msrc/subscription.rs | 5+++++
2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/db.rs b/src/db.rs @@ -385,6 +385,7 @@ fn query_from_sub(sub: &Subscription) -> (String, Vec<Box<dyn ToSql>>) { // (sqli-safe), or a string that is filtered to only contain // hexadecimal characters. Strings that require escaping (tag // names/values) use parameters. + let mut limit: Option<u32> = None; let mut query = "SELECT DISTINCT(e.content) FROM event e LEFT JOIN tag t ON e.id=t.event_id ".to_owned(); // parameters @@ -422,6 +423,9 @@ fn query_from_sub(sub: &Subscription) -> (String, Vec<Box<dyn ToSql>>) { let authors_clause = format!("({})", auth_searches.join(" OR ")); filter_components.push(authors_clause); } + if let Some(lim) = f.limit { + limit = Some(lim) + } // Query for Kind if let Some(ks) = &f.kinds { // kind is number, no escaping needed @@ -513,7 +517,13 @@ fn query_from_sub(sub: &Subscription) -> (String, Vec<Box<dyn ToSql>>) { query.push_str(") "); } // add order clause - query.push_str(" ORDER BY created_at ASC"); + query.push_str(&format!( + " ORDER BY created_at {}", + limit.map_or("ASC", |_| "DESC") + )); + if let Some(lim) = limit { + query.push_str(&format!(" LIMIT {}", lim)) + } debug!("query string: {}", query); (query, params) } diff --git a/src/subscription.rs b/src/subscription.rs @@ -31,6 +31,8 @@ pub struct ReqFilter { pub until: Option<u64>, /// List of author public keys pub authors: Option<Vec<String>>, + /// Limit number of results + pub limit: Option<u32>, /// Set of tags #[serde(skip)] pub tags: Option<HashMap<String, HashSet<String>>>, @@ -54,6 +56,7 @@ impl<'de> Deserialize<'de> for ReqFilter { since: None, until: None, authors: None, + limit: None, tags: None, }; let mut ts = None; @@ -68,6 +71,8 @@ impl<'de> Deserialize<'de> for ReqFilter { rf.since = Deserialize::deserialize(val).ok(); } else if key == "until" { rf.until = Deserialize::deserialize(val).ok(); + } else if key == "limit" { + rf.limit = Deserialize::deserialize(val).ok(); } else if key == "authors" { rf.authors = Deserialize::deserialize(val).ok(); } else if key.starts_with('#') && key.len() > 1 && val.is_array() {