node: Remove `Routing` command
Replaced by direct DB access.
This commit is contained in:
parent
40c58b45ed
commit
caaa7581e6
|
|
@ -1,7 +1,7 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use radicle::node::{Address, Node, NodeId, TRACKING_DB_FILE};
|
||||
use radicle::node::{Address, Node, NodeId, ROUTING_DB_FILE, TRACKING_DB_FILE};
|
||||
|
||||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
@ -139,8 +139,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
control::connect(&mut node, nid, addr)?
|
||||
}
|
||||
Operation::Routing => {
|
||||
let node = Node::new(profile.socket());
|
||||
routing::run(&node)?;
|
||||
let store =
|
||||
radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?;
|
||||
routing::run(&store)?;
|
||||
}
|
||||
Operation::Start => control::start()?,
|
||||
Operation::Status => {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use radicle::{node::Handle as _, Node};
|
||||
use radicle::node;
|
||||
|
||||
use crate::terminal as term;
|
||||
|
||||
pub fn run(node: &Node) -> anyhow::Result<()> {
|
||||
pub fn run<S: node::routing::Store>(routing: &S) -> anyhow::Result<()> {
|
||||
let mut t = term::Table::new(term::table::TableOptions::default());
|
||||
t.push(["RID", "NID"]);
|
||||
t.push(["---", "---"]);
|
||||
for (id, node) in node.routing()? {
|
||||
for (id, node) in routing.entries()? {
|
||||
t.push([
|
||||
term::format::highlight(id).to_string(),
|
||||
term::format::node(&node),
|
||||
|
|
|
|||
|
|
@ -187,14 +187,6 @@ fn command<H: Handle<Error = runtime::HandleError>>(
|
|||
CommandName::Status => {
|
||||
CommandResult::ok().to_writer(writer).ok();
|
||||
}
|
||||
CommandName::Routing => match handle.routing() {
|
||||
Ok(c) => {
|
||||
for route in c.into_iter() {
|
||||
serde_json::to_writer(&mut writer, &route)?;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(CommandError::Runtime(e)),
|
||||
},
|
||||
CommandName::Inventory => match handle.inventory() {
|
||||
Ok(c) => {
|
||||
for id in c.iter() {
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ impl<G: Signer + Ecdh + 'static> Handle<G> {
|
|||
impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
||||
type Sessions = Sessions;
|
||||
type Error = Error;
|
||||
type Routing = chan::Receiver<(Id, NodeId)>;
|
||||
|
||||
fn is_running(&self) -> bool {
|
||||
true
|
||||
|
|
@ -171,23 +170,6 @@ impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
|||
receiver.recv().map_err(Error::from)
|
||||
}
|
||||
|
||||
fn routing(&self) -> Result<Self::Routing, Error> {
|
||||
let (sender, receiver) = chan::unbounded();
|
||||
let query: Arc<QueryState> = Arc::new(move |state| {
|
||||
for (id, node) in state.routing().entries()? {
|
||||
if sender.send((id, node)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
let (err_sender, err_receiver) = chan::bounded(1);
|
||||
self.command(service::Command::QueryState(query, err_sender))?;
|
||||
err_receiver.recv()??;
|
||||
|
||||
Ok(receiver)
|
||||
}
|
||||
|
||||
fn sessions(&self) -> Result<Self::Sessions, Error> {
|
||||
let (sender, receiver) = chan::unbounded();
|
||||
let query: Arc<QueryState> = Arc::new(move |state| {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use radicle::crypto::{KeyPair, Seed, Signer};
|
|||
use radicle::git;
|
||||
use radicle::git::refname;
|
||||
use radicle::identity::Id;
|
||||
use radicle::node::routing::Store;
|
||||
use radicle::node::Handle as _;
|
||||
use radicle::profile::Home;
|
||||
use radicle::profile::Profile;
|
||||
|
|
@ -156,6 +157,14 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Get routing table entries.
|
||||
pub fn routing(&self) -> impl Iterator<Item = (Id, NodeId)> {
|
||||
radicle::node::routing::Table::reader(self.home.node().join(radicle::node::ROUTING_DB_FILE))
|
||||
.unwrap()
|
||||
.entries()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Wait until this node's routing table matches the remotes.
|
||||
pub fn converge<'a>(
|
||||
&'a self,
|
||||
|
|
@ -176,7 +185,7 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
|
|||
|
||||
let mut remaining: BTreeSet<_> = routes.iter().collect();
|
||||
|
||||
for (rid, nid) in self.handle.routing().unwrap() {
|
||||
for (rid, nid) in self.routing() {
|
||||
if !remaining.remove(&(rid, nid)) {
|
||||
panic!(
|
||||
"Node::routes_to: unexpected route for {}: ({rid}, {nid})",
|
||||
|
|
@ -347,7 +356,7 @@ pub fn converge<'a, G: Signer + cyphernet::Ecdh + 'static>(
|
|||
// First build the set of all routes.
|
||||
for node in &nodes {
|
||||
// Routes from the routing table.
|
||||
for (rid, seed_id) in node.handle.routing().unwrap() {
|
||||
for (rid, seed_id) in node.routing() {
|
||||
all_routes.insert((rid, seed_id));
|
||||
}
|
||||
// Routes from the local inventory.
|
||||
|
|
@ -360,8 +369,8 @@ pub fn converge<'a, G: Signer + cyphernet::Ecdh + 'static>(
|
|||
// its routing table has all routes. If so, remove it from the remaining nodes.
|
||||
while !remaining.is_empty() {
|
||||
remaining.retain(|_, node| {
|
||||
let routing = node.handle.routing().unwrap();
|
||||
let routes = BTreeSet::from_iter(routing.try_iter());
|
||||
let routing = node.routing();
|
||||
let routes = BTreeSet::from_iter(routing);
|
||||
|
||||
if routes == all_routes {
|
||||
log::debug!(target: "test", "Node {} has converged", node.id);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ pub struct Handle {
|
|||
impl radicle::node::Handle for Handle {
|
||||
type Error = HandleError;
|
||||
type Sessions = service::Sessions;
|
||||
type Routing = Vec<(Id, NodeId)>;
|
||||
|
||||
fn is_running(&self) -> bool {
|
||||
true
|
||||
|
|
@ -68,10 +67,6 @@ impl radicle::node::Handle for Handle {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn routing(&self) -> Result<Self::Routing, Self::Error> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn sessions(&self) -> Result<Self::Sessions, Self::Error> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,6 @@ pub enum CommandName {
|
|||
UntrackNode,
|
||||
/// Get the node's inventory.
|
||||
Inventory,
|
||||
/// Get the node's routing table.
|
||||
Routing,
|
||||
/// Get the node's status.
|
||||
Status,
|
||||
/// Shutdown the node.
|
||||
|
|
@ -385,8 +383,6 @@ pub trait Handle {
|
|||
/// The error returned by all methods.
|
||||
type Error: std::error::Error + Send + Sync + 'static;
|
||||
|
||||
type Routing: IntoIterator<Item = (Id, NodeId)>;
|
||||
|
||||
/// Check if the node is running. to a peer.
|
||||
fn is_running(&self) -> bool;
|
||||
/// Connect to a peer.
|
||||
|
|
@ -412,8 +408,6 @@ pub trait Handle {
|
|||
fn sync_inventory(&mut self) -> Result<bool, Self::Error>;
|
||||
/// Ask the service to shutdown.
|
||||
fn shutdown(self) -> Result<(), Self::Error>;
|
||||
/// Query the routing table entries.
|
||||
fn routing(&self) -> Result<Self::Routing, Self::Error>;
|
||||
/// Query the peer session state.
|
||||
fn sessions(&self) -> Result<Self::Sessions, Self::Error>;
|
||||
/// Query the inventory.
|
||||
|
|
@ -464,7 +458,6 @@ impl Node {
|
|||
impl Handle for Node {
|
||||
type Sessions = ();
|
||||
type Error = Error;
|
||||
type Routing = Vec<(Id, NodeId)>;
|
||||
|
||||
fn is_running(&self) -> bool {
|
||||
let Ok(mut lines) = self.call::<&str, CommandResult>(CommandName::Status, []) else {
|
||||
|
|
@ -573,15 +566,6 @@ impl Handle for Node {
|
|||
response.into()
|
||||
}
|
||||
|
||||
fn routing(&self) -> Result<Self::Routing, Error> {
|
||||
let mut routes = Vec::new();
|
||||
for result in self.call::<&str, _>(CommandName::Routing, [])? {
|
||||
let route = result?;
|
||||
routes.push(route);
|
||||
}
|
||||
Ok(routes)
|
||||
}
|
||||
|
||||
fn sessions(&self) -> Result<Self::Sessions, Error> {
|
||||
todo!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
use std::{fmt, time};
|
||||
|
||||
use sqlite as sql;
|
||||
use thiserror::Error;
|
||||
|
|
@ -10,6 +10,9 @@ use crate::{
|
|||
prelude::{Id, NodeId},
|
||||
};
|
||||
|
||||
/// How long to wait for the database lock to be released before failing a read.
|
||||
const DB_READ_TIMEOUT: time::Duration = time::Duration::from_secs(1);
|
||||
|
||||
/// An error occuring in peer-to-peer networking code.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
|
|
@ -44,6 +47,17 @@ impl Table {
|
|||
Ok(Self { db })
|
||||
}
|
||||
|
||||
/// Same as [`Self::open`], but in read-only mode. This is useful to have multiple
|
||||
/// open databases, as no locking is required.
|
||||
pub fn reader<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
|
||||
let mut db =
|
||||
sql::Connection::open_with_flags(path, sqlite::OpenFlags::new().set_read_only())?;
|
||||
db.set_busy_timeout(DB_READ_TIMEOUT.as_millis() as usize)?;
|
||||
db.execute(Self::SCHEMA)?;
|
||||
|
||||
Ok(Self { db })
|
||||
}
|
||||
|
||||
/// Create a new in-memory routing table.
|
||||
pub fn memory() -> Result<Self, Error> {
|
||||
let db = sql::Connection::open(":memory:")?;
|
||||
|
|
|
|||
Loading…
Reference in New Issue