Compare commits

...

1 Commits

Author SHA1 Message Date
Tomáš Mládek e5e314186b wip: hier walker
ci/woodpecker/push/woodpecker Pipeline failed Details
2023-10-31 19:10:21 +01:00
3 changed files with 62 additions and 0 deletions

7
Cargo.lock generated
View File

@ -1042,6 +1042,12 @@ dependencies = [
"libc",
]
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fastrand"
version = "2.0.0"
@ -3202,6 +3208,7 @@ dependencies = [
"chrono",
"diesel",
"diesel_migrations",
"fallible-iterator",
"filebuffer",
"lazy_static",
"lexpr",

View File

@ -59,6 +59,7 @@ tree_magic_mini = { version = "3.0.2", features = ["with-gpl-data"] }
nonempty = "0.6.0"
shadow-rs = { version = "0.23", default-features = false }
fallible-iterator = "0.3.0"
[build-dependencies]
shadow-rs = { version = "0.23", default-features = false }

View File

@ -1,7 +1,10 @@
use std::collections::HashSet;
use std::convert::TryFrom;
use std::iter::{self, FromIterator};
use std::sync::{Arc, Mutex};
use anyhow::{anyhow, Result};
use fallible_iterator::FallibleIterator;
use lru::LruCache;
use tracing::trace;
use uuid::Uuid;
@ -82,6 +85,57 @@ pub fn list_roots(connection: &UpEndConnection) -> Result<Vec<Address>> {
.collect())
}
pub type AddressPath = (Vec<Address>, Address);
pub struct HierWalker {
connection: UpEndConnection,
current: Vec<AddressPath>,
seen: HashSet<Address>,
}
impl HierWalker {
pub fn new(connection: UpEndConnection, start: Address) -> Self {
Self {
connection,
current: vec![(vec![], start.clone())],
seen: HashSet::from_iter(iter::once(start)),
}
}
}
impl FallibleIterator for HierWalker {
type Item = AddressPath;
type Error = anyhow::Error;
fn next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
while let Some((path, address)) = self.current.pop() {
let children: Vec<Address> = self
.connection
.query(Query::SingleQuery(QueryPart::Matches(PatternQuery {
entity: QueryComponent::Variable(None),
attribute: QueryComponent::Exact(ATTR_IN.into()),
value: QueryComponent::Exact(address.clone().into()),
})))?
.into_iter()
.map(|e| e.entity)
.collect();
let path: Vec<Address> = path.into_iter().chain(iter::once(address.clone())).collect();
for child in children {
if !self.seen.contains(&child) {
self.seen.insert(child.clone());
self.current.push((path.clone(), child));
}
}
return Ok(Some((path, address)));
}
Ok(None)
}
}
lazy_static! {
static ref FETCH_CREATE_LOCK: Mutex<()> = Mutex::new(());
}