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 std::ffi::OsString;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
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 as term;
|
||||||
use crate::terminal::args::{Args, Error, Help};
|
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)?
|
control::connect(&mut node, nid, addr)?
|
||||||
}
|
}
|
||||||
Operation::Routing => {
|
Operation::Routing => {
|
||||||
let node = Node::new(profile.socket());
|
let store =
|
||||||
routing::run(&node)?;
|
radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?;
|
||||||
|
routing::run(&store)?;
|
||||||
}
|
}
|
||||||
Operation::Start => control::start()?,
|
Operation::Start => control::start()?,
|
||||||
Operation::Status => {
|
Operation::Status => {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use radicle::{node::Handle as _, Node};
|
use radicle::node;
|
||||||
|
|
||||||
use crate::terminal as term;
|
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());
|
let mut t = term::Table::new(term::table::TableOptions::default());
|
||||||
t.push(["RID", "NID"]);
|
t.push(["RID", "NID"]);
|
||||||
t.push(["---", "---"]);
|
t.push(["---", "---"]);
|
||||||
for (id, node) in node.routing()? {
|
for (id, node) in routing.entries()? {
|
||||||
t.push([
|
t.push([
|
||||||
term::format::highlight(id).to_string(),
|
term::format::highlight(id).to_string(),
|
||||||
term::format::node(&node),
|
term::format::node(&node),
|
||||||
|
|
|
||||||
|
|
@ -187,14 +187,6 @@ fn command<H: Handle<Error = runtime::HandleError>>(
|
||||||
CommandName::Status => {
|
CommandName::Status => {
|
||||||
CommandResult::ok().to_writer(writer).ok();
|
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() {
|
CommandName::Inventory => match handle.inventory() {
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
for id in c.iter() {
|
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> {
|
impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
||||||
type Sessions = Sessions;
|
type Sessions = Sessions;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Routing = chan::Receiver<(Id, NodeId)>;
|
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
true
|
true
|
||||||
|
|
@ -171,23 +170,6 @@ impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
||||||
receiver.recv().map_err(Error::from)
|
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> {
|
fn sessions(&self) -> Result<Self::Sessions, Error> {
|
||||||
let (sender, receiver) = chan::unbounded();
|
let (sender, receiver) = chan::unbounded();
|
||||||
let query: Arc<QueryState> = Arc::new(move |state| {
|
let query: Arc<QueryState> = Arc::new(move |state| {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use radicle::crypto::{KeyPair, Seed, Signer};
|
||||||
use radicle::git;
|
use radicle::git;
|
||||||
use radicle::git::refname;
|
use radicle::git::refname;
|
||||||
use radicle::identity::Id;
|
use radicle::identity::Id;
|
||||||
|
use radicle::node::routing::Store;
|
||||||
use radicle::node::Handle as _;
|
use radicle::node::Handle as _;
|
||||||
use radicle::profile::Home;
|
use radicle::profile::Home;
|
||||||
use radicle::profile::Profile;
|
use radicle::profile::Profile;
|
||||||
|
|
@ -156,6 +157,14 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
|
||||||
self
|
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.
|
/// Wait until this node's routing table matches the remotes.
|
||||||
pub fn converge<'a>(
|
pub fn converge<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
|
@ -176,7 +185,7 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
|
||||||
|
|
||||||
let mut remaining: BTreeSet<_> = routes.iter().collect();
|
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)) {
|
if !remaining.remove(&(rid, nid)) {
|
||||||
panic!(
|
panic!(
|
||||||
"Node::routes_to: unexpected route for {}: ({rid}, {nid})",
|
"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.
|
// First build the set of all routes.
|
||||||
for node in &nodes {
|
for node in &nodes {
|
||||||
// Routes from the routing table.
|
// 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));
|
all_routes.insert((rid, seed_id));
|
||||||
}
|
}
|
||||||
// Routes from the local inventory.
|
// 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.
|
// its routing table has all routes. If so, remove it from the remaining nodes.
|
||||||
while !remaining.is_empty() {
|
while !remaining.is_empty() {
|
||||||
remaining.retain(|_, node| {
|
remaining.retain(|_, node| {
|
||||||
let routing = node.handle.routing().unwrap();
|
let routing = node.routing();
|
||||||
let routes = BTreeSet::from_iter(routing.try_iter());
|
let routes = BTreeSet::from_iter(routing);
|
||||||
|
|
||||||
if routes == all_routes {
|
if routes == all_routes {
|
||||||
log::debug!(target: "test", "Node {} has converged", node.id);
|
log::debug!(target: "test", "Node {} has converged", node.id);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ pub struct Handle {
|
||||||
impl radicle::node::Handle for Handle {
|
impl radicle::node::Handle for Handle {
|
||||||
type Error = HandleError;
|
type Error = HandleError;
|
||||||
type Sessions = service::Sessions;
|
type Sessions = service::Sessions;
|
||||||
type Routing = Vec<(Id, NodeId)>;
|
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
true
|
true
|
||||||
|
|
@ -68,10 +67,6 @@ impl radicle::node::Handle for Handle {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn routing(&self) -> Result<Self::Routing, Self::Error> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sessions(&self) -> Result<Self::Sessions, Self::Error> {
|
fn sessions(&self) -> Result<Self::Sessions, Self::Error> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,6 @@ pub enum CommandName {
|
||||||
UntrackNode,
|
UntrackNode,
|
||||||
/// Get the node's inventory.
|
/// Get the node's inventory.
|
||||||
Inventory,
|
Inventory,
|
||||||
/// Get the node's routing table.
|
|
||||||
Routing,
|
|
||||||
/// Get the node's status.
|
/// Get the node's status.
|
||||||
Status,
|
Status,
|
||||||
/// Shutdown the node.
|
/// Shutdown the node.
|
||||||
|
|
@ -385,8 +383,6 @@ pub trait Handle {
|
||||||
/// The error returned by all methods.
|
/// The error returned by all methods.
|
||||||
type Error: std::error::Error + Send + Sync + 'static;
|
type Error: std::error::Error + Send + Sync + 'static;
|
||||||
|
|
||||||
type Routing: IntoIterator<Item = (Id, NodeId)>;
|
|
||||||
|
|
||||||
/// Check if the node is running. to a peer.
|
/// Check if the node is running. to a peer.
|
||||||
fn is_running(&self) -> bool;
|
fn is_running(&self) -> bool;
|
||||||
/// Connect to a peer.
|
/// Connect to a peer.
|
||||||
|
|
@ -412,8 +408,6 @@ pub trait Handle {
|
||||||
fn sync_inventory(&mut self) -> Result<bool, Self::Error>;
|
fn sync_inventory(&mut self) -> Result<bool, Self::Error>;
|
||||||
/// Ask the service to shutdown.
|
/// Ask the service to shutdown.
|
||||||
fn shutdown(self) -> Result<(), Self::Error>;
|
fn shutdown(self) -> Result<(), Self::Error>;
|
||||||
/// Query the routing table entries.
|
|
||||||
fn routing(&self) -> Result<Self::Routing, Self::Error>;
|
|
||||||
/// Query the peer session state.
|
/// Query the peer session state.
|
||||||
fn sessions(&self) -> Result<Self::Sessions, Self::Error>;
|
fn sessions(&self) -> Result<Self::Sessions, Self::Error>;
|
||||||
/// Query the inventory.
|
/// Query the inventory.
|
||||||
|
|
@ -464,7 +458,6 @@ impl Node {
|
||||||
impl Handle for Node {
|
impl Handle for Node {
|
||||||
type Sessions = ();
|
type Sessions = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Routing = Vec<(Id, NodeId)>;
|
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
let Ok(mut lines) = self.call::<&str, CommandResult>(CommandName::Status, []) else {
|
let Ok(mut lines) = self.call::<&str, CommandResult>(CommandName::Status, []) else {
|
||||||
|
|
@ -573,15 +566,6 @@ impl Handle for Node {
|
||||||
response.into()
|
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> {
|
fn sessions(&self) -> Result<Self::Sessions, Error> {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::{fmt, time};
|
||||||
|
|
||||||
use sqlite as sql;
|
use sqlite as sql;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
@ -10,6 +10,9 @@ use crate::{
|
||||||
prelude::{Id, NodeId},
|
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.
|
/// An error occuring in peer-to-peer networking code.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
@ -44,6 +47,17 @@ impl Table {
|
||||||
Ok(Self { db })
|
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.
|
/// Create a new in-memory routing table.
|
||||||
pub fn memory() -> Result<Self, Error> {
|
pub fn memory() -> Result<Self, Error> {
|
||||||
let db = sql::Connection::open(":memory:")?;
|
let db = sql::Connection::open(":memory:")?;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue