node: Fix filter construction and policy code

This commit is contained in:
Alexis Sellier 2023-02-12 17:07:57 +01:00
parent 27d0c8f235
commit 2f1a18470e
No known key found for this signature in database
4 changed files with 64 additions and 43 deletions

View File

@ -249,6 +249,12 @@ where
} }
} }
/// Return the next i/o action to execute.
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Option<reactor::Io> {
self.reactor.next()
}
/// Track a repository. /// Track a repository.
/// Returns whether or not the tracking policy was updated. /// Returns whether or not the tracking policy was updated.
pub fn track_repo(&mut self, id: &Id, scope: tracking::Scope) -> Result<bool, tracking::Error> { pub fn track_repo(&mut self, id: &Id, scope: tracking::Scope) -> Result<bool, tracking::Error> {
@ -267,8 +273,14 @@ where
// Nb. This is potentially slow if we have lots of projects. We should probably // Nb. This is potentially slow if we have lots of projects. We should probably
// only re-compute the filter when we've untracked a certain amount of projects // only re-compute the filter when we've untracked a certain amount of projects
// and the filter is really out of date. // and the filter is really out of date.
self.filter = Filter::new(self.tracking.repo_entries()?.map(|(e, _)| e)); //
// TODO: Share this code with initialization code.
self.filter = Filter::new(
self.tracking
.repo_entries()?
.filter(|(_, _, policy)| *policy == tracking::Policy::Track)
.map(|(e, _, _)| e),
);
Ok(updated) Ok(updated)
} }
@ -345,7 +357,12 @@ where
self.routing.insert(id, self.node_id(), time.as_secs())?; self.routing.insert(id, self.node_id(), time.as_secs())?;
} }
// Setup subscription filter for tracked repos. // Setup subscription filter for tracked repos.
self.filter = Filter::new(self.tracking.repo_entries()?.map(|(e, _)| e)); self.filter = Filter::new(
self.tracking
.repo_entries()?
.filter(|(_, _, policy)| *policy == tracking::Policy::Track)
.map(|(e, _, _)| e),
);
Ok(()) Ok(())
} }
@ -586,6 +603,8 @@ where
// For outbound connections, we are the first to say "Hello". // For outbound connections, we are the first to say "Hello".
// For inbound connections, we wait for the remote to say "Hello" first. // For inbound connections, we wait for the remote to say "Hello" first.
if link.is_outbound() { if link.is_outbound() {
let filter = self.filter();
if let Some(peer) = self.sessions.get_mut(&remote) { if let Some(peer) = self.sessions.get_mut(&remote) {
self.reactor.write_all( self.reactor.write_all(
remote, remote,
@ -593,7 +612,7 @@ where
self.clock.as_secs(), self.clock.as_secs(),
&self.storage, &self.storage,
&self.signer, &self.signer,
self.filter.clone(), filter,
&self.config, &self.config,
), ),
); );
@ -833,6 +852,7 @@ where
remote: &NodeId, remote: &NodeId,
message: Message, message: Message,
) -> Result<(), session::Error> { ) -> Result<(), session::Error> {
let filter = self.filter(); // TODO: Don't call this if it's not used.
let Some(peer) = self.sessions.get_mut(remote) else { let Some(peer) = self.sessions.get_mut(remote) else {
return Err(session::Error::NotFound(*remote)); return Err(session::Error::NotFound(*remote));
}; };
@ -871,7 +891,7 @@ where
self.clock.as_secs(), self.clock.as_secs(),
&self.storage, &self.storage,
&self.signer, &self.signer,
self.filter.clone(), filter,
&self.config, &self.config,
), ),
); );
@ -1053,6 +1073,16 @@ where
false false
} }
/// Return a new filter object, based on our tracking policy.
fn filter(&self) -> Filter {
if self.config.policy == tracking::Policy::Track {
// TODO: Remove bits for blocked repos.
Filter::default()
} else {
self.filter.clone()
}
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Periodic tasks // Periodic tasks
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -1242,14 +1272,6 @@ impl fmt::Display for DisconnectReason {
} }
} }
impl<R, A, S, G> Iterator for Service<R, A, S, G> {
type Item = reactor::Io;
fn next(&mut self) -> Option<Self::Item> {
self.reactor.next()
}
}
/// Result of a project lookup. /// Result of a project lookup.
#[derive(Debug)] #[derive(Debug)]
pub struct Lookup { pub struct Lookup {

View File

@ -62,34 +62,30 @@ impl Config {
/// Check if a repository is tracked. /// Check if a repository is tracked.
pub fn is_repo_tracked(&self, id: &Id) -> Result<bool, Error> { pub fn is_repo_tracked(&self, id: &Id) -> Result<bool, Error> {
if self.default == Policy::Track { self.repo_policy(id).map(|policy| policy == Policy::Track)
return Ok(true);
}
self.store.is_repo_tracked(id)
} }
/// Check if a node is tracked. /// Check if a node is tracked.
pub fn is_node_tracked(&self, id: &NodeId) -> Result<bool, Error> { pub fn is_node_tracked(&self, id: &NodeId) -> Result<bool, Error> {
if self.default == Policy::Track { self.node_policy(id).map(|policy| policy == Policy::Track)
return Ok(true);
}
self.store.is_node_tracked(id)
} }
/// Get a node's tracking information. /// Get a node's tracking information.
pub fn node_entry(&self, id: &NodeId) -> Result<(Option<Alias>, Policy), Error> { /// Returns the default policy if the node isn't found.
if let Some(result) = self.store.node_entry(id)? { pub fn node_policy(&self, id: &NodeId) -> Result<Policy, Error> {
return Ok(result); if let Some((_, policy)) = self.store.node_entry(id)? {
return Ok(policy);
} }
Ok((None, self.default)) Ok(self.default)
} }
/// Get a repository's tracking information. /// Get a repository's tracking information.
pub fn repo_entry(&self, id: &Id) -> Result<(Scope, Policy), Error> { /// Returns the default policy if the repo isn't found.
if let Some(result) = self.store.repo_entry(id)? { pub fn repo_policy(&self, id: &Id) -> Result<Policy, Error> {
return Ok(result); if let Some((_, policy)) = self.store.repo_entry(id)? {
return Ok(policy);
} }
Ok((Scope::All, self.default)) Ok(self.default)
} }
} }

View File

@ -1,3 +1,4 @@
#![allow(clippy::type_complexity)]
use std::path::Path; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use std::{fmt, io}; use std::{fmt, io};
@ -247,35 +248,37 @@ impl Config {
} }
/// Get node tracking entries. /// Get node tracking entries.
pub fn node_entries(&self) -> Result<Box<dyn Iterator<Item = (NodeId, Alias)>>, Error> { pub fn node_entries(&self) -> Result<Box<dyn Iterator<Item = (NodeId, Alias, Policy)>>, Error> {
let mut stmt = self let mut stmt = self
.db .db
.prepare("SELECT id, alias FROM `node-policies`")? .prepare("SELECT id, alias, policy FROM `node-policies`")?
.into_iter(); .into_iter();
let mut entries = Vec::new(); let mut entries = Vec::new();
while let Some(Ok(row)) = stmt.next() { while let Some(Ok(row)) = stmt.next() {
let id = row.read("id"); let id = row.read("id");
let alias = row.read::<&str, _>("alias"); let alias = row.read::<&str, _>("alias");
let policy = row.read::<Policy, _>("policy");
entries.push((id, alias.to_owned())); entries.push((id, alias.to_owned(), policy));
} }
Ok(Box::new(entries.into_iter())) Ok(Box::new(entries.into_iter()))
} }
/// Get repository tracking entries. /// Get repository tracking entries.
pub fn repo_entries(&self) -> Result<Box<dyn Iterator<Item = (Id, Scope)>>, Error> { pub fn repo_entries(&self) -> Result<Box<dyn Iterator<Item = (Id, Scope, Policy)>>, Error> {
let mut stmt = self let mut stmt = self
.db .db
.prepare("SELECT id, scope FROM `repo-policies`")? .prepare("SELECT id, scope, policy FROM `repo-policies`")?
.into_iter(); .into_iter();
let mut entries = Vec::new(); let mut entries = Vec::new();
while let Some(Ok(row)) = stmt.next() { while let Some(Ok(row)) = stmt.next() {
let id = row.read("id"); let id = row.read("id");
let scope = row.read("scope"); let scope = row.read("scope");
let policy = row.read::<Policy, _>("policy");
entries.push((id, scope)); entries.push((id, scope, policy));
} }
Ok(Box::new(entries.into_iter())) Ok(Box::new(entries.into_iter()))
} }
@ -321,9 +324,9 @@ mod test {
assert!(db.track_node(id, None).unwrap()); assert!(db.track_node(id, None).unwrap());
} }
let mut entries = db.node_entries().unwrap(); let mut entries = db.node_entries().unwrap();
assert_matches!(entries.next(), Some((id, _)) if id == ids[0]); assert_matches!(entries.next(), Some((id, _, _)) if id == ids[0]);
assert_matches!(entries.next(), Some((id, _)) if id == ids[1]); assert_matches!(entries.next(), Some((id, _, _)) if id == ids[1]);
assert_matches!(entries.next(), Some((id, _)) if id == ids[2]); assert_matches!(entries.next(), Some((id, _, _)) if id == ids[2]);
} }
#[test] #[test]
@ -335,9 +338,9 @@ mod test {
assert!(db.track_repo(id, Scope::All).unwrap()); assert!(db.track_repo(id, Scope::All).unwrap());
} }
let mut entries = db.repo_entries().unwrap(); let mut entries = db.repo_entries().unwrap();
assert_matches!(entries.next(), Some((id, _)) if id == ids[0]); assert_matches!(entries.next(), Some((id, _, _)) if id == ids[0]);
assert_matches!(entries.next(), Some((id, _)) if id == ids[1]); assert_matches!(entries.next(), Some((id, _, _)) if id == ids[1]);
assert_matches!(entries.next(), Some((id, _)) if id == ids[2]); assert_matches!(entries.next(), Some((id, _, _)) if id == ids[2]);
} }
#[test] #[test]

View File

@ -346,7 +346,7 @@ impl<S: WriteStorage + 'static, G: Signer> Simulation<S, G> {
for peer in nodes.values_mut() { for peer in nodes.values_mut() {
let id = peer.id(); let id = peer.id();
for o in peer.by_ref() { while let Some(o) = peer.next() {
self.schedule(&id, o); self.schedule(&id, o);
} }
} }
@ -417,7 +417,7 @@ impl<S: WriteStorage + 'static, G: Signer> Simulation<S, G> {
p.fetched(f, result); p.fetched(f, result);
} }
} }
for o in p.by_ref() { while let Some(o) = p.next() {
self.schedule(&node, o); self.schedule(&node, o);
} }
} else { } else {