diff --git a/radicle-node/src/runtime.rs b/radicle-node/src/runtime.rs index 6a1251e1..78473508 100644 --- a/radicle-node/src/runtime.rs +++ b/radicle-node/src/runtime.rs @@ -111,7 +111,8 @@ impl Runtime { let routing = routing::Table::open(routing_db)?; log::info!(target: "node", "Opening tracking policy table {}..", tracking_db.display()); - let tracking = tracking::Config::open(tracking_db)?; + let tracking = tracking::Store::open(tracking_db)?; + let tracking = tracking::Config::new(config.policy, tracking); log::info!(target: "node", "Initializing service ({:?})..", network); let service = service::Service::new( diff --git a/radicle-node/src/service.rs b/radicle-node/src/service.rs index ef75bd05..e4af6c16 100644 --- a/radicle-node/src/service.rs +++ b/radicle-node/src/service.rs @@ -92,6 +92,8 @@ pub enum Error { Storage(#[from] storage::Error), #[error(transparent)] Routing(#[from] routing::Error), + #[error(transparent)] + Tracking(#[from] tracking::Error), } /// Function used to query internal service state. @@ -261,11 +263,13 @@ where /// Note that when untracking, we don't announce anything to the network. This is because by /// simply not announcing it anymore, it will eventually be pruned by nodes. pub fn untrack_repo(&mut self, id: &Id) -> Result { + let updated = self.tracking.untrack_repo(id)?; // 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 // and the filter is really out of date. self.filter = Filter::new(self.tracking.repo_entries()?.map(|(e, _)| e)); - self.tracking.untrack_repo(id) + + Ok(updated) } /// Check whether we are tracking a certain repository. @@ -340,6 +344,9 @@ where for id in self.storage.inventory()? { self.routing.insert(id, self.node_id(), time.as_secs())?; } + // Setup subscription filter for tracked repos. + self.filter = Filter::new(self.tracking.repo_entries()?.map(|(e, _)| e)); + Ok(()) } diff --git a/radicle-node/src/service/config.rs b/radicle-node/src/service/config.rs index 6162d164..b0d842d3 100644 --- a/radicle-node/src/service/config.rs +++ b/radicle-node/src/service/config.rs @@ -2,6 +2,7 @@ use localtime::LocalDuration; use radicle::node::Address; +use crate::service::tracking::Policy; use crate::service::NodeId; /// Peer-to-peer network. @@ -44,6 +45,8 @@ pub struct Config { pub relay: bool, /// Configured service limits. pub limits: Limits, + /// Default tracking policy. + pub policy: Policy, } impl Default for Config { @@ -54,6 +57,7 @@ impl Default for Config { network: Network::default(), relay: true, limits: Limits::default(), + policy: Policy::Block, } } } diff --git a/radicle-node/src/service/tracking.rs b/radicle-node/src/service/tracking.rs index da30f4b1..1d43cffb 100644 --- a/radicle-node/src/service/tracking.rs +++ b/radicle-node/src/service/tracking.rs @@ -1,8 +1,16 @@ mod store; +use std::ops; use std::str::FromStr; -pub use store::{Config, Error}; +use crate::prelude::Id; +use crate::service::NodeId; + +pub use store::Config as Store; +pub use store::Error; + +/// Node alias. +pub type Alias = String; /// Tracking policy. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -36,3 +44,65 @@ impl FromStr for Scope { } } } + +/// Tracking configuration. +#[derive(Debug)] +pub struct Config { + /// Default policy, if a policy for a specific node or repository was not found. + default: Policy, + /// Underlying configuration store. + store: store::Config, +} + +impl Config { + /// Create a new tracking configuration. + pub fn new(default: Policy, store: store::Config) -> Self { + Self { default, store } + } + + /// Check if a repository is tracked. + pub fn is_repo_tracked(&self, id: &Id) -> Result { + if self.default == Policy::Track { + return Ok(true); + } + self.store.is_repo_tracked(id) + } + + /// Check if a node is tracked. + pub fn is_node_tracked(&self, id: &NodeId) -> Result { + if self.default == Policy::Track { + return Ok(true); + } + self.store.is_node_tracked(id) + } + + /// Get a node's tracking information. + pub fn node_entry(&self, id: &NodeId) -> Result<(Option, Policy), Error> { + if let Some(result) = self.store.node_entry(id)? { + return Ok(result); + } + Ok((None, self.default)) + } + + /// Get a repository's tracking information. + pub fn repo_entry(&self, id: &Id) -> Result<(Scope, Policy), Error> { + if let Some(result) = self.store.repo_entry(id)? { + return Ok(result); + } + Ok((Scope::All, self.default)) + } +} + +impl ops::Deref for Config { + type Target = store::Config; + + fn deref(&self) -> &Self::Target { + &self.store + } +} + +impl ops::DerefMut for Config { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.store + } +} diff --git a/radicle-node/src/service/tracking/store.rs b/radicle-node/src/service/tracking/store.rs index c0e656b1..629ed68c 100644 --- a/radicle-node/src/service/tracking/store.rs +++ b/radicle-node/src/service/tracking/store.rs @@ -8,7 +8,7 @@ use thiserror::Error; use crate::prelude::Id; use crate::service::NodeId; -use super::{Policy, Scope}; +use super::{Alias, Policy, Scope}; #[derive(Error, Debug)] pub enum Error { @@ -20,8 +20,6 @@ pub enum Error { Internal(#[from] sql::Error), } -pub type Alias = String; - impl sqlite::BindableWithIndex for Scope { fn bind(self, stmt: &mut sql::Statement<'_>, i: I) -> sql::Result<()> { let s = match self { diff --git a/radicle-node/src/test/peer.rs b/radicle-node/src/test/peer.rs index f67f704d..245262b7 100644 --- a/radicle-node/src/test/peer.rs +++ b/radicle-node/src/test/peer.rs @@ -16,6 +16,7 @@ use crate::prelude::*; use crate::service; use crate::service::message::*; use crate::service::reactor::Io; +use crate::service::tracking::Policy; use crate::service::*; use crate::storage::git::transport::remote; use crate::storage::{RemoteId, WriteStorage}; @@ -82,6 +83,7 @@ pub struct Config { pub config: service::Config, pub addrs: address::Book, pub local_time: LocalTime, + pub policy: Policy, pub signer: G, pub rng: fastrand::Rng, } @@ -95,6 +97,7 @@ impl Default for Config { config: service::Config::default(), addrs: address::Book::memory().unwrap(), local_time: LocalTime::now(), + policy: Policy::Block, signer, rng, } @@ -113,7 +116,8 @@ where config: Config, ) -> Self { let routing = routing::Table::memory().unwrap(); - let tracking = tracking::Config::memory().unwrap(); + let tracking = tracking::Store::memory().unwrap(); + let tracking = tracking::Config::new(config.policy, tracking); let id = *config.signer.public_key(); let service = Service::new( config.config,