From f9596fd743b4519de075bc7d44250562653afa9f Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 23 Jan 2021 22:03:39 -0600 Subject: [PATCH] Profiles: notify followers on submission publish Expose API for paging notifications --- profiles/src/apub/actions/submission.rs | 18 ++++++++ profiles/src/store/profile.rs | 1 + profiles/src/store/view/notif.rs | 59 +++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/profiles/src/apub/actions/submission.rs b/profiles/src/apub/actions/submission.rs index 48f2d2d..ca0d8ad 100644 --- a/profiles/src/apub/actions/submission.rs +++ b/profiles/src/apub/actions/submission.rs @@ -146,6 +146,24 @@ impl Action for UpdateSubmission { let newly_published = !initial_published && submission.published().is_some(); let profile_id = submission.profile_id(); + + if newly_published { + if let Some(published) = submission.published() { + let ctx_clone = ctx.clone(); + ctx.spawn_blocking(move || { + for follower_id in ctx_clone.store.view.follows.forward_iter(profile_id) { + if let Ok(Some(true)) = ctx_clone.store.profiles.is_local(follower_id) { + ctx_clone.store.view.submissions.new( + follower_id, + submission_id, + published, + ); + } + } + }); + } + } + if ctx.is_local(profile_id)? { if newly_published { return Ok(Some(Box::new(crate::apub::results::SubmissionCreated { diff --git a/profiles/src/store/profile.rs b/profiles/src/store/profile.rs index 0ccde68..3bb0bed 100644 --- a/profiles/src/store/profile.rs +++ b/profiles/src/store/profile.rs @@ -330,6 +330,7 @@ impl Store { let range_end = range_end.as_bytes().to_vec(); this.date_range(..range_end) }) + .rev() } pub fn is_local(&self, id: Uuid) -> Result, StoreError> { diff --git a/profiles/src/store/view/notif.rs b/profiles/src/store/view/notif.rs index 555c6dd..bd04d78 100644 --- a/profiles/src/store/view/notif.rs +++ b/profiles/src/store/view/notif.rs @@ -301,6 +301,60 @@ impl NotificationStore { .values() .filter_map(|res| res.ok()) .filter_map(uuid_from_ivec) + .rev() + } + + pub fn older_than_for_profile<'a>( + &'a self, + profile_id: Uuid, + notification_id: Uuid, + ) -> impl DoubleEndedIterator + 'a { + let keys = self.keys(); + + self.dates + .get(keys.date_key(profile_id, notification_id)) + .ok() + .and_then(|opt| opt) + .and_then(date_from_ivec) + .into_iter() + .flat_map(move |date| { + let keys = keys.clone(); + self.notifications + .range( + ..keys + .notification_key(profile_id, date, notification_id) + .as_bytes(), + ) + .values() + .filter_map(|res| res.ok()) + .filter_map(uuid_from_ivec) + }) + .rev() + } + + pub fn newer_than_for_profile<'a>( + &'a self, + profile_id: Uuid, + notification_id: Uuid, + ) -> impl DoubleEndedIterator + 'a { + let keys = self.keys(); + + self.dates + .get(keys.date_key(profile_id, notification_id)) + .ok() + .and_then(|opt| opt) + .and_then(date_from_ivec) + .into_iter() + .flat_map(move |date| { + self.notifications + .range( + keys.notification_key(profile_id, date, notification_id) + .as_bytes().., + ) + .values() + .filter_map(|res| res.ok()) + .filter_map(uuid_from_ivec) + }) } fn notification_keys(&self, profile_id: Uuid) -> impl DoubleEndedIterator { @@ -337,3 +391,8 @@ fn uuid_from_ivec(ivec: sled::IVec) -> Option { .map_err(|e| log::warn!("Failed to parse ivec {}", e)) .ok() } + +fn date_from_ivec(ivec: sled::IVec) -> Option> { + let s = String::from_utf8_lossy(&ivec); + s.parse().ok() +}