node: Add ability to have default tracking policy

When a specific tracking policy isn't found, we allow setting a default.
To preserve existing behavior, the default is `Block`, ie. if a node
isn't tracked explicitly, it is blocked.

However, this change allows for using `Track` as the default, which
is a way to track everything without having to know the entities in
advance.
This commit is contained in:
Alexis Sellier 2023-02-10 16:00:19 +01:00
parent bdc0ab9881
commit bd7c5a0daa
No known key found for this signature in database
6 changed files with 91 additions and 7 deletions

View File

@ -111,7 +111,8 @@ impl<G: Signer + EcSign + 'static> Runtime<G> {
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(

View File

@ -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<bool, tracking::Error> {
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(())
}

View File

@ -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,
}
}
}

View File

@ -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<bool, Error> {
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<bool, Error> {
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<Alias>, 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
}
}

View File

@ -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<I: sql::ParameterIndex>(self, stmt: &mut sql::Statement<'_>, i: I) -> sql::Result<()> {
let s = match self {

View File

@ -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<G: Signer + 'static> {
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<MockSigner> {
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<G>,
) -> 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,