Store.find_events()

This commit is contained in:
Mike Dilger 2024-02-14 09:49:17 +13:00
parent 8ae3bc2b6b
commit 88f609c962
2 changed files with 152 additions and 1 deletions

View File

@ -59,6 +59,10 @@ pub enum Error {
#[error("LMDB: {0}")]
Lmdb(#[from] heed::Error),
// Filter is underspecified
#[error("Filter is underspecified. Scrapers are not allowed")]
Scraper,
// UTF-8
#[error("UTF-8: {0}")]
Utf8(#[from] std::str::Utf8Error),

View File

@ -2,10 +2,11 @@ pub mod event_store;
pub use event_store::EventStore;
use crate::error::Error;
use crate::types::{Event, Id, Kind, Pubkey, Time};
use crate::types::{Event, Filter, Id, Kind, Pubkey, Time};
use heed::types::{OwnedType, UnalignedSlice};
use heed::{Database, Env, EnvFlags, EnvOpenOptions};
use std::fs;
use std::ops::Bound;
#[derive(Debug)]
pub struct Store {
@ -153,6 +154,152 @@ impl Store {
}
}
pub fn find_events(&self, filter: Filter) -> Result<Vec<Event>, Error> {
let mut output: Vec<Event> = Vec::new();
if filter.num_ids() > 0 {
// Fetch by id
for id in filter.ids() {
if let Some(event) = self.get_event_by_id(id)? {
// and check each against the rest of the filter
if filter.event_matches(&event)? {
output.push(event);
}
}
// Stop if limited
if output.len() >= filter.limit() as usize {
return Ok(output);
}
}
} else if filter.num_authors() > 0 && filter.num_kinds() > 0 {
for author in filter.authors() {
for kind in filter.kinds() {
let start_prefix = Self::key_akci(
author,
kind,
filter.until(), // scan goes backwards in time
Id([0; 32]),
);
let end_prefix = Self::key_akci(
author,
kind,
filter.since(), // scan goes backwards in time
Id([255; 32]),
);
let range = (
Bound::Included(&*start_prefix),
Bound::Excluded(&*end_prefix),
);
let txn = self.env.read_txn()?;
let iter = self.akci.range(&txn, &range)?;
for result in iter {
let (_key, offset) = result?;
if let Some(event) = self.events.get_event_by_offset(offset)? {
// check against the rest of the filter
if filter.event_matches(&event)? {
output.push(event);
}
}
// Stop if limited
if output.len() >= filter.limit() as usize {
return Ok(output);
}
}
}
}
} else if filter.num_authors() > 0 && !filter.tags()?.is_empty() {
for author in filter.authors() {
let tags = filter.tags()?;
for mut tag in tags.iter() {
if let Some(tag0) = tag.next() {
if let Some(tagvalue) = tag.next() {
let start_prefix = Self::key_atci(
author,
tag0[0],
tagvalue,
filter.until(), // scan goes backwards in time
Id([0; 32]),
);
let end_prefix = Self::key_atci(
author,
tag0[0],
tagvalue,
filter.since(), // scan goes backwards in time
Id([255; 32]),
);
let range = (
Bound::Included(&*start_prefix),
Bound::Excluded(&*end_prefix),
);
let txn = self.env.read_txn()?;
let iter = self.akci.range(&txn, &range)?;
for result in iter {
let (_key, offset) = result?;
if let Some(event) = self.events.get_event_by_offset(offset)? {
// check against the rest of the filter
if filter.event_matches(&event)? {
output.push(event);
}
}
// Stop if limited
if output.len() >= filter.limit() as usize {
return Ok(output);
}
}
}
}
}
}
} else if filter.num_kinds() > 0 && !filter.tags()?.is_empty() {
for kind in filter.kinds() {
let tags = filter.tags()?;
for mut tag in tags.iter() {
if let Some(tag0) = tag.next() {
if let Some(tagvalue) = tag.next() {
let start_prefix = Self::key_ktci(
kind,
tag0[0],
tagvalue,
filter.until(), // scan goes backwards in time
Id([0; 32]),
);
let end_prefix = Self::key_ktci(
kind,
tag0[0],
tagvalue,
filter.since(), // scan goes backwards in time
Id([255; 32]),
);
let range = (
Bound::Included(&*start_prefix),
Bound::Excluded(&*end_prefix),
);
let txn = self.env.read_txn()?;
let iter = self.akci.range(&txn, &range)?;
for result in iter {
let (_key, offset) = result?;
if let Some(event) = self.events.get_event_by_offset(offset)? {
// check against the rest of the filter
if filter.event_matches(&event)? {
output.push(event);
}
}
// Stop if limited
if output.len() >= filter.limit() as usize {
return Ok(output);
}
}
}
}
}
}
} else {
return Err(Error::Scraper);
}
Ok(output)
}
// For looking up event by Author and Kind
// author(32) + kind(2) + reversecreatedat(8) + id(32)
#[allow(dead_code)]