Feed: switch to anchor method

This commit is contained in:
Mike Dilger 2024-06-07 14:09:39 +12:00
parent c1c76b2706
commit 3b43df443f
4 changed files with 63 additions and 58 deletions

View File

@ -164,7 +164,7 @@ pub enum ToOverlordMessage {
SetDmChannel(DmChannel),
/// internal
SetPersonFeed(PublicKey),
SetPersonFeed(PublicKey, Unixtime),
/// internal
SetThreadFeed {

View File

@ -50,6 +50,7 @@ pub enum ErrorKind {
ListIsNotEmpty,
ListIsWellKnown,
ListNotFound,
LoadMoreFailed,
NostrConnectNotSetup,
Offline,
ParseInt(std::num::ParseIntError),
@ -147,6 +148,7 @@ impl std::fmt::Display for Error {
ListIsNotEmpty => write!(f, "List is not empty"),
ListIsWellKnown => write!(f, "List is well known and cannot be deallocated"),
ListNotFound => write!(f, "List was not found"),
LoadMoreFailed => write!(f, "Load more failed"),
NostrConnectNotSetup => write!(f, "NostrConnect not setup, cannot connect"),
Offline => write!(f, "Offline"),
ParseInt(e) => write!(f, "Bad integer: {e}"),

View File

@ -2,7 +2,7 @@ mod feed_kind;
pub use feed_kind::FeedKind;
use crate::comms::{ToMinionMessage, ToMinionPayload, ToMinionPayloadDetail, ToOverlordMessage};
use crate::error::Error;
use crate::error::{Error, ErrorKind};
use crate::globals::GLOBALS;
use crate::people::PersonList;
use nostr_types::{
@ -21,7 +21,7 @@ pub struct Feed {
current_feed_kind: RwLock<FeedKind>,
current_feed_events: RwLock<Vec<Id>>,
current_feed_start: RwLock<Unixtime>,
current_feed_anchor: RwLock<Unixtime>,
// We only recompute the feed at specified intervals (or when they switch)
interval_ms: RwLock<u32>,
@ -42,28 +42,35 @@ impl Feed {
recompute_lock: AtomicBool::new(false),
current_feed_kind: RwLock::new(FeedKind::List(PersonList::Followed, false)),
current_feed_events: RwLock::new(Vec::new()),
current_feed_start: RwLock::new(Unixtime::now().unwrap()),
current_feed_anchor: RwLock::new(Unixtime::now().unwrap()),
interval_ms: RwLock::new(10000), // Every 10 seconds, until we load from settings
last_computed: RwLock::new(None),
thread_parent: RwLock::new(None),
}
}
/// This only looks further back in stored events, it doesn't deal with minion subscriptions.
pub(crate) fn load_more(&self) -> Unixtime {
let mut start = *self.current_feed_start.read();
let kindstr = self.current_feed_kind.read().simple_string();
let dur = if kindstr == "person" {
60 * 60 * 24 * 15
} else if kindstr == "inbox" {
60 * 60 * 24 * 7
/// This changes the window where the feed pulls its events from by backing up the
/// anchor time to the time of the earliest event currently in the feed.
//
/// This doesn't deal with minion subscriptions.
pub(crate) fn load_more(&self) -> Result<Unixtime, Error> {
// Load the timestamp of the earliest event in the feed so far
if let Some(earliest_id) = self.current_feed_events.read().iter().next_back() {
let earliest_event = GLOBALS.storage.read_event(*earliest_id)?;
if let Some(event) = earliest_event {
// Move the anchor back to the earliest event we have so far
*self.current_feed_anchor.write() = event.created_at;
Ok(event.created_at)
} else {
Err(ErrorKind::LoadMoreFailed.into())
}
} else {
60 * 60 * 4
};
start = start - Duration::from_secs(dur);
*self.current_feed_start.write() = start;
start
Err(ErrorKind::LoadMoreFailed.into())
}
}
pub(crate) fn current_anchor(&self) -> Unixtime {
*self.current_feed_anchor.read()
}
fn unlisten(&self) {
@ -95,21 +102,13 @@ impl Feed {
}
pub fn switch_feed(&self, feed_kind: FeedKind) {
let kindstr = feed_kind.simple_string();
// NOTE: do not clear the feed here, or the UI will get an empty feed momentarily
// and the scroll bar "memory" will be reset to the top. Let recompute rebuild
// the feed (called down below)
// Reset the feed start
let dur = if kindstr == "person" {
60 * 60 * 24 * 15
} else if kindstr == "inbox" {
60 * 60 * 24 * 7
} else {
60 * 60 * 4
};
*self.current_feed_start.write() = Unixtime::now().unwrap() - Duration::from_secs(dur);
// Reset the feed anchor
let anchor = Unixtime::now().unwrap();
*self.current_feed_anchor.write() = anchor;
// Reset the feed thread
*self.thread_parent.write() = if let FeedKind::Thread {
@ -151,7 +150,7 @@ impl Feed {
// Listen for Person events
let _ = GLOBALS
.to_overlord
.send(ToOverlordMessage::SetPersonFeed(*pubkey));
.send(ToOverlordMessage::SetPersonFeed(*pubkey, anchor));
}
FeedKind::DmChat(ref dm_channel) => {
// Listen for DmChat channel events
@ -235,7 +234,7 @@ impl Feed {
// ok because it is more reactive to changes to the setting.
*self.interval_ms.write() = feed_recompute_interval_ms;
let since: Unixtime = *self.current_feed_start.read();
let anchor: Unixtime = *self.current_feed_anchor.read();
let current_feed_kind = self.current_feed_kind.read().to_owned();
match current_feed_kind {
@ -255,7 +254,7 @@ impl Feed {
let events = if filter.authors.is_empty() {
Default::default()
} else {
Self::load_event_range(since, filter, with_replies, false, |_| true).await?
Self::load_event_range(anchor, filter, with_replies, false, |_| true).await?
};
*self.current_feed_events.write() = events;
@ -274,6 +273,10 @@ impl Feed {
let dismissed = GLOBALS.dismissed.read().await.clone();
let my_pubkeyhex: PublicKeyHex = my_pubkey.into();
// FIXME, we can't use 'anchor' which is usually 'now'.
// We have to use a timewindow (instead of a limit)
let since = anchor - Duration::from_secs(43200);
let screen = |e: &Event| {
e.created_at >= since
&& kinds_with_dms.contains(&e.kind)
@ -335,7 +338,7 @@ impl Feed {
filter
};
let events = Self::load_event_range(since, filter, true, false, |_| true).await?;
let events = Self::load_event_range(anchor, filter, true, false, |_| true).await?;
*self.current_feed_events.write() = events;
}
@ -362,18 +365,17 @@ impl Feed {
F: Fn(&Event) -> bool,
{
let now = Unixtime::now().unwrap();
//let limit = GLOBALS.storage.read_setting_load_more_count() as usize;
let limit = GLOBALS.storage.read_setting_load_more_count() as usize;
let dismissed = GLOBALS.dismissed.read().await.clone();
let outer_screen =
|e: &Event| basic_screen(e, include_replies, include_dms, &dismissed) && screen(e);
//let mut before_filter = filter;
//let mut after_filter = before_filter.clone();
let mut after_filter = filter;
let mut before_filter = filter;
let mut after_filter = before_filter.clone();
//before_filter.until = Some(since);
//before_filter.limit = Some(limit);
before_filter.until = Some(since);
before_filter.limit = Some(limit);
after_filter.since = Some(since);
after_filter.until = Some(now);
@ -394,15 +396,13 @@ impl Feed {
.find_events_by_filter(&after_filter, outer_screen)?
.iter()
.map(|e| e.id)
/* Once we do anchor, we want to add this chain
.chain(
GLOBALS
.storage
.find_events_by_filter(&before_filter, outer_screen)?
.iter()
.map(|e| e.id),
)
*/
GLOBALS
.storage
.find_events_by_filter(&before_filter, outer_screen)?
.iter()
.map(|e| e.id),
)
.collect())
}
}

View File

@ -272,11 +272,13 @@ impl Overlord {
}
async fn apply_relay_assignment(&mut self, assignment: RelayAssignment) -> Result<(), Error> {
let anchor = GLOBALS.feed.current_anchor();
let mut jobs = vec![RelayJob {
reason: RelayConnectionReason::Follow,
payload: ToMinionPayload {
job_id: rand::random::<u64>(),
detail: ToMinionPayloadDetail::SubscribeGeneralFeed(assignment.pubkeys.clone()),
detail: ToMinionPayloadDetail::SubscribeGeneralFeed(assignment.pubkeys.clone(), anchor),
},
}];
@ -297,7 +299,7 @@ impl Overlord {
reason: RelayConnectionReason::FetchInbox,
payload: ToMinionPayload {
job_id: rand::random::<u64>(),
detail: ToMinionPayloadDetail::SubscribeInbox,
detail: ToMinionPayloadDetail::SubscribeInbox(anchor),
},
});
}
@ -741,8 +743,8 @@ impl Overlord {
ToOverlordMessage::SetDmChannel(dmchannel) => {
self.set_dm_channel(dmchannel).await?;
}
ToOverlordMessage::SetPersonFeed(pubkey) => {
self.set_person_feed(pubkey).await?;
ToOverlordMessage::SetPersonFeed(pubkey, anchor) => {
self.set_person_feed(pubkey, anchor).await?;
}
ToOverlordMessage::SetThreadFeed {
id,
@ -1649,7 +1651,7 @@ impl Overlord {
pub async fn load_more(&mut self) -> Result<(), Error> {
// Change the feed range:
let earliest = GLOBALS.feed.load_more();
let anchor = GLOBALS.feed.load_more()?;
// Fetch more based on that feed range
match GLOBALS.feed.get_feed_kind() {
@ -1661,7 +1663,7 @@ impl Overlord {
target: relay_assignment.relay_url.as_str().to_owned(),
payload: ToMinionPayload {
job_id: 0,
detail: ToMinionPayloadDetail::TempSubscribeGeneralFeedChunk(earliest),
detail: ToMinionPayloadDetail::TempSubscribeGeneralFeedChunk(anchor),
},
});
}
@ -1683,7 +1685,7 @@ impl Overlord {
payload: ToMinionPayload {
job_id: rand::random::<u64>(),
detail: ToMinionPayloadDetail::TempSubscribeInboxFeedChunk(
earliest,
anchor
),
},
}],
@ -1712,7 +1714,7 @@ impl Overlord {
job_id: rand::random::<u64>(),
detail: ToMinionPayloadDetail::TempSubscribePersonFeedChunk {
pubkey,
start: earliest,
anchor,
},
},
}],
@ -2375,7 +2377,7 @@ impl Overlord {
Ok(())
}
async fn set_person_feed(&mut self, pubkey: PublicKey) -> Result<(), Error> {
async fn set_person_feed(&mut self, pubkey: PublicKey, anchor: Unixtime) -> Result<(), Error> {
let num_relays_per_person = GLOBALS.storage.read_setting_num_relays_per_person();
let relays: Vec<RelayUrl> = GLOBALS
@ -2394,7 +2396,7 @@ impl Overlord {
reason: RelayConnectionReason::SubscribePerson,
payload: ToMinionPayload {
job_id: rand::random::<u64>(),
detail: ToMinionPayloadDetail::SubscribePersonFeed(pubkey),
detail: ToMinionPayloadDetail::SubscribePersonFeed(pubkey, anchor),
},
}],
)
@ -2757,6 +2759,7 @@ impl Overlord {
/// Subscribe to the user's configuration events from the given relay
pub async fn subscribe_inbox(&mut self, relays: Option<Vec<RelayUrl>>) -> Result<(), Error> {
let now = Unixtime::now().unwrap();
let mention_relays: Vec<RelayUrl> = match relays {
Some(r) => r,
None => GLOBALS
@ -2773,7 +2776,7 @@ impl Overlord {
reason: RelayConnectionReason::FetchInbox,
payload: ToMinionPayload {
job_id: rand::random::<u64>(),
detail: ToMinionPayloadDetail::SubscribeInbox,
detail: ToMinionPayloadDetail::SubscribeInbox(now),
},
}],
)