Fix filter states when adding columns

This fixes various issues with filter states when adding columns. We now
maintain multiple states per relay so that we don't lose track of
anything.

Fixes: https://github.com/damus-io/notedeck/issues/431
Fixes: https://github.com/damus-io/notedeck/issues/359
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2024-11-14 14:44:33 -08:00
parent acadc4a9d9
commit 01bedac710
7 changed files with 451 additions and 301 deletions

View File

@@ -2,6 +2,7 @@ use crate::error::{Error, FilterError};
use crate::note::NoteRef;
use crate::Result;
use nostrdb::{Filter, FilterBuilder, Note, Subscription};
use std::collections::HashMap;
use tracing::{debug, warn};
/// A unified subscription has a local and remote component. The remote subid
@@ -12,6 +13,74 @@ pub struct UnifiedSubscription {
pub remote: String,
}
/// Each relay can have a different filter state. For example, some
/// relays may have the contact list, some may not. Let's capture all of
/// these states so that some relays don't stop the states of other
/// relays.
#[derive(Debug)]
pub struct FilterStates {
pub initial_state: FilterState,
pub states: HashMap<String, FilterState>,
}
impl FilterStates {
pub fn get(&mut self, relay: &str) -> &FilterState {
// if our initial state is ready, then just use that
if let FilterState::Ready(_) = self.initial_state {
&self.initial_state
} else {
// otherwise we look at relay states
if !self.states.contains_key(relay) {
self.states
.insert(relay.to_string(), self.initial_state.clone());
}
self.states.get(relay).unwrap()
}
}
pub fn get_any_gotremote(&self) -> Option<(&str, Subscription)> {
for (k, v) in self.states.iter() {
if let FilterState::GotRemote(sub) = v {
return Some((k, *sub));
}
}
None
}
pub fn get_any_ready(&self) -> Option<&Vec<Filter>> {
if let FilterState::Ready(fs) = &self.initial_state {
Some(fs)
} else {
for (_k, v) in self.states.iter() {
if let FilterState::Ready(ref fs) = v {
return Some(fs);
}
}
None
}
}
pub fn new(initial_state: FilterState) -> Self {
Self {
initial_state,
states: HashMap::new(),
}
}
pub fn set_relay_state(&mut self, relay: String, state: FilterState) {
if self.states.contains_key(&relay) {
let current_state = self.states.get(&relay).unwrap();
warn!(
"set_relay_state: we already have the {:?} state set for {}. overriding with {:?}",
current_state, &relay, state
);
}
self.states.insert(relay, state);
}
}
/// We may need to fetch some data from relays before our filter is ready.
/// [`FilterState`] tracks this.
#[derive(Debug, Clone)]