use NdbQueryPackage to call ndb::query multiple times
necessary to ensure we can retrieve reposts from ndb Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
filter::{self, HybridFilter},
|
filter::{self, HybridFilter, ValidKind},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use nostrdb::{Filter, Note};
|
use nostrdb::{Filter, Note};
|
||||||
@@ -15,8 +15,14 @@ pub fn hybrid_contacts_filter(
|
|||||||
add_pk: Option<&[u8; 32]>,
|
add_pk: Option<&[u8; 32]>,
|
||||||
with_hashtags: bool,
|
with_hashtags: bool,
|
||||||
) -> Result<HybridFilter, Error> {
|
) -> Result<HybridFilter, Error> {
|
||||||
let local = filter::filter_from_tags(note, add_pk, with_hashtags)?
|
let local = vec![
|
||||||
.into_filter(vec![1], filter::default_limit());
|
filter::filter_from_tags(note, add_pk, with_hashtags)?
|
||||||
|
.into_query_package(ValidKind::One, filter::default_limit()),
|
||||||
|
filter::filter_from_tags(note, add_pk, with_hashtags)?
|
||||||
|
.into_query_package(ValidKind::Six, filter::default_limit()),
|
||||||
|
filter::filter_from_tags(note, add_pk, with_hashtags)?
|
||||||
|
.into_query_package(ValidKind::Zero, filter::default_limit()),
|
||||||
|
];
|
||||||
let remote = filter::filter_from_tags(note, add_pk, with_hashtags)?
|
let remote = filter::filter_from_tags(note, add_pk, with_hashtags)?
|
||||||
.into_filter(vec![1, 0], filter::default_remote_limit());
|
.into_filter(vec![1, 0], filter::default_remote_limit());
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ pub struct FilteredTags {
|
|||||||
/// The local and remote filter are related but slightly different
|
/// The local and remote filter are related but slightly different
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SplitFilter {
|
pub struct SplitFilter {
|
||||||
pub local: Vec<Filter>,
|
pub local: Vec<NdbQueryPackage>,
|
||||||
pub remote: Vec<Filter>,
|
pub remote: Vec<Filter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,16 +230,23 @@ impl HybridFilter {
|
|||||||
HybridFilter::Unsplit(filter)
|
HybridFilter::Unsplit(filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split(local: Vec<Filter>, remote: Vec<Filter>) -> Self {
|
pub fn split(local: Vec<NdbQueryPackage>, remote: Vec<Filter>) -> Self {
|
||||||
HybridFilter::Split(SplitFilter { local, remote })
|
HybridFilter::Split(SplitFilter { local, remote })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local(&self) -> &[Filter] {
|
pub fn local(&self) -> NdbQueryPackages {
|
||||||
match self {
|
match self {
|
||||||
Self::Split(split) => &split.local,
|
Self::Split(split) => NdbQueryPackages {
|
||||||
|
packages: split.local.iter().map(NdbQueryPackage::borrow).collect(),
|
||||||
|
},
|
||||||
|
|
||||||
// local as the same as remote in unsplit
|
// local as the same as remote in unsplit
|
||||||
Self::Unsplit(local) => local,
|
Self::Unsplit(local) => NdbQueryPackages {
|
||||||
|
packages: vec![NdbQueryPackageUnowned {
|
||||||
|
filters: local,
|
||||||
|
kind: None,
|
||||||
|
}],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ impl TimelineSub {
|
|||||||
let before = self.state.clone();
|
let before = self.state.clone();
|
||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
SubState::NoSub { dependers } => {
|
SubState::NoSub { dependers } => {
|
||||||
let Some(sub) = ndb_sub(ndb, filter.local(), "") else {
|
let Some(sub) = ndb_sub(ndb, &filter.local().combined(), "") else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ impl TimelineSub {
|
|||||||
dependers: _,
|
dependers: _,
|
||||||
} => {}
|
} => {}
|
||||||
SubState::RemoteOnly { remote, dependers } => {
|
SubState::RemoteOnly { remote, dependers } => {
|
||||||
let Some(local) = ndb_sub(ndb, filter.local(), "") else {
|
let Some(local) = ndb_sub(ndb, &filter.local().combined(), "") else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.state = SubState::Unified {
|
self.state = SubState::Unified {
|
||||||
|
|||||||
@@ -134,15 +134,22 @@ impl TimelineCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let notes = if let FilterState::Ready(filters) = id.filters(txn, ndb) {
|
let notes = if let FilterState::Ready(filters) = id.filters(txn, ndb) {
|
||||||
if let Ok(results) = ndb.query(txn, filters.local(), 1000) {
|
let mut notes = Vec::new();
|
||||||
results
|
|
||||||
.into_iter()
|
for package in filters.local().packages {
|
||||||
.map(NoteRef::from_query_result)
|
if let Ok(results) = ndb.query(txn, package.filters, 1000) {
|
||||||
.collect()
|
let cur_notes: Vec<NoteRef> = results
|
||||||
} else {
|
.into_iter()
|
||||||
debug!("got no results from TimelineCache lookup for {:?}", id);
|
.map(NoteRef::from_query_result)
|
||||||
vec![]
|
.collect();
|
||||||
|
|
||||||
|
notes.extend(cur_notes);
|
||||||
|
} else {
|
||||||
|
debug!("got no results from TimelineCache lookup for {:?}", id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notes
|
||||||
} else {
|
} else {
|
||||||
// filter is not ready yet
|
// filter is not ready yet
|
||||||
vec![]
|
vec![]
|
||||||
@@ -178,12 +185,20 @@ impl TimelineCache {
|
|||||||
let (mut open_result, timeline) = match notes_resp.vitality {
|
let (mut open_result, timeline) = match notes_resp.vitality {
|
||||||
Vitality::Stale(timeline) => {
|
Vitality::Stale(timeline) => {
|
||||||
// The timeline cache is stale, let's update it
|
// The timeline cache is stale, let's update it
|
||||||
let notes = find_new_notes(
|
let notes = {
|
||||||
timeline.all_or_any_entries().latest(),
|
let mut notes = Vec::new();
|
||||||
timeline.subscription.get_filter()?.local(),
|
for package in timeline.subscription.get_filter()?.local().packages {
|
||||||
txn,
|
let cur_notes = find_new_notes(
|
||||||
ndb,
|
timeline.all_or_any_entries().latest(),
|
||||||
);
|
package.filters,
|
||||||
|
txn,
|
||||||
|
ndb,
|
||||||
|
);
|
||||||
|
notes.extend(cur_notes);
|
||||||
|
}
|
||||||
|
notes
|
||||||
|
};
|
||||||
|
|
||||||
let open_result = if notes.is_empty() {
|
let open_result = if notes.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use crate::search::SearchQuery;
|
|||||||
use crate::timeline::{Timeline, TimelineTab};
|
use crate::timeline::{Timeline, TimelineTab};
|
||||||
use enostr::{Filter, NoteId, Pubkey};
|
use enostr::{Filter, NoteId, Pubkey};
|
||||||
use nostrdb::{Ndb, Transaction};
|
use nostrdb::{Ndb, Transaction};
|
||||||
|
use notedeck::filter::{NdbQueryPackage, ValidKind};
|
||||||
use notedeck::{
|
use notedeck::{
|
||||||
contacts::{contacts_filter, hybrid_contacts_filter},
|
contacts::{contacts_filter, hybrid_contacts_filter},
|
||||||
filter::{self, default_limit, default_remote_limit, HybridFilter},
|
filter::{self, default_limit, default_remote_limit, HybridFilter},
|
||||||
@@ -728,15 +729,29 @@ fn last_per_pubkey_filter_state(ndb: &Ndb, pk: &Pubkey) -> FilterState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn profile_filter(pk: &[u8; 32]) -> HybridFilter {
|
fn profile_filter(pk: &[u8; 32]) -> HybridFilter {
|
||||||
|
let local = vec![
|
||||||
|
NdbQueryPackage {
|
||||||
|
filters: vec![Filter::new()
|
||||||
|
.authors([pk])
|
||||||
|
.kinds([1])
|
||||||
|
.limit(default_limit())
|
||||||
|
.build()],
|
||||||
|
kind: ValidKind::One,
|
||||||
|
},
|
||||||
|
NdbQueryPackage {
|
||||||
|
filters: vec![Filter::new()
|
||||||
|
.authors([pk])
|
||||||
|
.kinds([6])
|
||||||
|
.limit(default_limit())
|
||||||
|
.build()],
|
||||||
|
kind: ValidKind::Six,
|
||||||
|
},
|
||||||
|
];
|
||||||
HybridFilter::split(
|
HybridFilter::split(
|
||||||
|
local,
|
||||||
vec![Filter::new()
|
vec![Filter::new()
|
||||||
.authors([pk])
|
.authors([pk])
|
||||||
.kinds([1])
|
.kinds([1, 6, 0])
|
||||||
.limit(default_limit())
|
|
||||||
.build()],
|
|
||||||
vec![Filter::new()
|
|
||||||
.authors([pk])
|
|
||||||
.kinds([1, 0])
|
|
||||||
.limit(default_remote_limit())
|
.limit(default_remote_limit())
|
||||||
.build()],
|
.build()],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -676,18 +676,32 @@ fn setup_initial_timeline(
|
|||||||
timeline.subscription, timeline.filter
|
timeline.subscription, timeline.filter
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut lim = 0i32;
|
let notes = {
|
||||||
for filter in filters.local() {
|
let mut notes = Vec::new();
|
||||||
lim += filter.limit().unwrap_or(1) as i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("setup_initial_timeline: limit for local filter is {}", lim);
|
for package in filters.local().packages {
|
||||||
|
let mut lim = 0i32;
|
||||||
|
for filter in package.filters {
|
||||||
|
lim += filter.limit().unwrap_or(1) as i32;
|
||||||
|
}
|
||||||
|
|
||||||
let notes: Vec<NoteRef> = ndb
|
debug!("setup_initial_timeline: limit for local filter is {}", lim);
|
||||||
.query(txn, filters.local(), lim)?
|
|
||||||
.into_iter()
|
let cur_notes: Vec<NoteRef> = ndb
|
||||||
.map(NoteRef::from_query_result)
|
.query(txn, package.filters, lim)?
|
||||||
.collect();
|
.into_iter()
|
||||||
|
.map(NoteRef::from_query_result)
|
||||||
|
.collect();
|
||||||
|
tracing::debug!(
|
||||||
|
"Found {} notes for kind: {:?}",
|
||||||
|
cur_notes.len(),
|
||||||
|
package.kind
|
||||||
|
);
|
||||||
|
notes.extend(&cur_notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
notes
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(pks) = timeline.insert_new(txn, ndb, note_cache, ¬es) {
|
if let Some(pks) = timeline.insert_new(txn, ndb, note_cache, ¬es) {
|
||||||
pks.process(ndb, txn, unknown_ids);
|
pks.process(ndb, txn, unknown_ids);
|
||||||
|
|||||||
Reference in New Issue
Block a user