node: Start implementing fetch control
Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
parent
d273cd0247
commit
c4c0e0413f
|
|
@ -111,6 +111,16 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
|
checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.11.0"
|
version = "3.11.0"
|
||||||
|
|
@ -356,6 +366,19 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "git-url"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9fcc88c679f3dc55e1e4fe0324142abec612cafaafae1bf6a951c324c9d96f8"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"home",
|
||||||
|
"quick-error",
|
||||||
|
"serde",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "git2"
|
name = "git2"
|
||||||
version = "0.13.25"
|
version = "0.13.25"
|
||||||
|
|
@ -392,6 +415,15 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "home"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.48"
|
version = "0.1.48"
|
||||||
|
|
@ -526,6 +558,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multibase"
|
name = "multibase"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
|
|
@ -689,6 +727,12 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quickcheck"
|
name = "quickcheck"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
|
@ -740,9 +784,11 @@ dependencies = [
|
||||||
"bs58",
|
"bs58",
|
||||||
"chrono",
|
"chrono",
|
||||||
"colored",
|
"colored",
|
||||||
|
"crossbeam-channel",
|
||||||
"ed25519-consensus",
|
"ed25519-consensus",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"git-ref-format",
|
"git-ref-format",
|
||||||
|
"git-url",
|
||||||
"git2",
|
"git2",
|
||||||
"log",
|
"log",
|
||||||
"multibase",
|
"multibase",
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ impl<R: Reactor> Client<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new handle to communicate with the client.
|
/// Create a new handle to communicate with the client.
|
||||||
pub fn handle(&self) -> handle::Handle<R> {
|
pub fn handle(&self) -> handle::Handle<R::Waker> {
|
||||||
handle::Handle {
|
handle::Handle {
|
||||||
waker: self.reactor.waker(),
|
waker: self.reactor.waker(),
|
||||||
commands: self.handle.clone(),
|
commands: self.handle.clone(),
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use std::net;
|
use std::net;
|
||||||
|
|
||||||
use crossbeam_channel as chan;
|
use crossbeam_channel as chan;
|
||||||
use nakamoto_net::Reactor;
|
use nakamoto_net::Waker;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::identity::ProjId;
|
use crate::identity::ProjId;
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
use crate::protocol::CommandError;
|
use crate::protocol::{CommandError, FetchLookup};
|
||||||
|
|
||||||
/// An error resulting from a handle method.
|
/// An error resulting from a handle method.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -46,17 +46,19 @@ impl<T> From<chan::SendError<T>> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Handle<R: Reactor> {
|
pub struct Handle<W: Waker> {
|
||||||
pub(crate) commands: chan::Sender<protocol::Command>,
|
pub(crate) commands: chan::Sender<protocol::Command>,
|
||||||
pub(crate) waker: R::Waker,
|
|
||||||
pub(crate) shutdown: chan::Sender<()>,
|
pub(crate) shutdown: chan::Sender<()>,
|
||||||
pub(crate) listening: chan::Receiver<net::SocketAddr>,
|
pub(crate) listening: chan::Receiver<net::SocketAddr>,
|
||||||
|
pub(crate) waker: W,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Reactor> traits::Handle for Handle<R> {
|
impl<W: Waker> traits::Handle for Handle<W> {
|
||||||
/// Retrieve or update the project from network.
|
/// Retrieve or update the given project from the network.
|
||||||
fn fetch(&self, _id: ProjId) -> Result<(), Error> {
|
fn fetch(&self, id: ProjId) -> Result<FetchLookup, Error> {
|
||||||
todo!()
|
let (sender, receiver) = chan::bounded(1);
|
||||||
|
self.commands.send(protocol::Command::Fetch(id, sender))?;
|
||||||
|
receiver.recv().map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start tracking the given project. Doesn't do anything if the project is already tracked.
|
/// Start tracking the given project. Doesn't do anything if the project is already tracked.
|
||||||
|
|
@ -81,7 +83,7 @@ impl<R: Reactor> traits::Handle for Handle<R> {
|
||||||
/// Send a command to the command channel, and wake up the event loop.
|
/// Send a command to the command channel, and wake up the event loop.
|
||||||
fn command(&self, cmd: protocol::Command) -> Result<(), Error> {
|
fn command(&self, cmd: protocol::Command) -> Result<(), Error> {
|
||||||
self.commands.send(cmd)?;
|
self.commands.send(cmd)?;
|
||||||
R::wake(&self.waker)?;
|
self.waker.wake()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +91,7 @@ impl<R: Reactor> traits::Handle for Handle<R> {
|
||||||
/// Ask the client to shutdown.
|
/// Ask the client to shutdown.
|
||||||
fn shutdown(self) -> Result<(), Error> {
|
fn shutdown(self) -> Result<(), Error> {
|
||||||
self.shutdown.send(())?;
|
self.shutdown.send(())?;
|
||||||
R::wake(&self.waker)?;
|
self.waker.wake()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +102,7 @@ pub mod traits {
|
||||||
|
|
||||||
pub trait Handle {
|
pub trait Handle {
|
||||||
/// Retrieve or update the project from network.
|
/// Retrieve or update the project from network.
|
||||||
fn fetch(&self, id: ProjId) -> Result<(), Error>;
|
fn fetch(&self, id: ProjId) -> Result<FetchLookup, Error>;
|
||||||
/// Start tracking the given project. Doesn't do anything if the project is already
|
/// Start tracking the given project. Doesn't do anything if the project is already
|
||||||
/// tracked.
|
/// tracked.
|
||||||
fn track(&self, id: ProjId) -> Result<bool, Error>;
|
fn track(&self, id: ProjId) -> Result<bool, Error>;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
//! Client control socket implementation.
|
//! Client control socket implementation.
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
use std::io::LineWriter;
|
||||||
use std::os::unix::net::UnixListener;
|
use std::os::unix::net::UnixListener;
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
@ -8,6 +9,9 @@ use std::{fs, io, net};
|
||||||
|
|
||||||
use crate::client;
|
use crate::client;
|
||||||
use crate::client::handle::traits::Handle;
|
use crate::client::handle::traits::Handle;
|
||||||
|
use crate::identity::ProjId;
|
||||||
|
use crate::protocol::FetchLookup;
|
||||||
|
use crate::protocol::FetchResult;
|
||||||
|
|
||||||
/// Default name for control socket file.
|
/// Default name for control socket file.
|
||||||
pub const DEFAULT_SOCKET_NAME: &str = "radicle.sock";
|
pub const DEFAULT_SOCKET_NAME: &str = "radicle.sock";
|
||||||
|
|
@ -55,6 +59,8 @@ enum DrainError {
|
||||||
InvalidCommand,
|
InvalidCommand,
|
||||||
#[error("client error: {0}")]
|
#[error("client error: {0}")]
|
||||||
Client(#[from] client::handle::Error),
|
Client(#[from] client::handle::Error),
|
||||||
|
#[error("i/o error: {0}")]
|
||||||
|
Io(#[from] io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drain<H: Handle>(stream: &UnixStream, handle: &H) -> Result<(), DrainError> {
|
fn drain<H: Handle>(stream: &UnixStream, handle: &H) -> Result<(), DrainError> {
|
||||||
|
|
@ -65,9 +71,7 @@ fn drain<H: Handle>(stream: &UnixStream, handle: &H) -> Result<(), DrainError> {
|
||||||
match line.split_once(' ') {
|
match line.split_once(' ') {
|
||||||
Some(("fetch", arg)) => {
|
Some(("fetch", arg)) => {
|
||||||
if let Ok(id) = arg.parse() {
|
if let Ok(id) = arg.parse() {
|
||||||
if let Err(e) = handle.fetch(id) {
|
fetch(id, LineWriter::new(stream), handle)?;
|
||||||
return Err(DrainError::Client(e));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Err(DrainError::InvalidCommandArg(arg.to_owned()));
|
return Err(DrainError::InvalidCommandArg(arg.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
@ -106,6 +110,47 @@ fn drain<H: Handle>(stream: &UnixStream, handle: &H) -> Result<(), DrainError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fetch<W: Write, H: Handle>(id: ProjId, mut writer: W, handle: &H) -> Result<(), DrainError> {
|
||||||
|
match handle.fetch(id.clone()) {
|
||||||
|
Err(e) => {
|
||||||
|
return Err(DrainError::Client(e));
|
||||||
|
}
|
||||||
|
Ok(FetchLookup::Found { providers, results }) => {
|
||||||
|
let providers = Vec::from(providers);
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
writer,
|
||||||
|
"ok: found {} providers for {} ({:?})",
|
||||||
|
providers.len(),
|
||||||
|
&id,
|
||||||
|
&providers,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
for result in results.iter() {
|
||||||
|
match result {
|
||||||
|
FetchResult::Fetched { from } => {
|
||||||
|
writeln!(writer, "ok: {} fetched from {}", &id, from)?;
|
||||||
|
}
|
||||||
|
FetchResult::Error { from, error } => {
|
||||||
|
writeln!(
|
||||||
|
writer,
|
||||||
|
"error: {} failed to fetch from {}: {}",
|
||||||
|
&id, from, error
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(FetchLookup::NotFound) => {
|
||||||
|
writeln!(writer, "error: {} was not found", &id)?;
|
||||||
|
}
|
||||||
|
Ok(FetchLookup::Error(err)) => {
|
||||||
|
writeln!(writer, "error: {}", err)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use crate::client::handle::traits;
|
||||||
use crate::client::handle::Error;
|
use crate::client::handle::Error;
|
||||||
use crate::identity::ProjId;
|
use crate::identity::ProjId;
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
|
use crate::protocol::FetchLookup;
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Handle {
|
pub struct Handle {
|
||||||
|
|
@ -11,8 +12,8 @@ pub struct Handle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Handle for Handle {
|
impl traits::Handle for Handle {
|
||||||
fn fetch(&self, _id: ProjId) -> Result<(), Error> {
|
fn fetch(&self, _id: ProjId) -> Result<FetchLookup, Error> {
|
||||||
Ok(())
|
Ok(FetchLookup::NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn track(&self, _id: ProjId) -> Result<bool, Error> {
|
fn track(&self, _id: ProjId) -> Result<bool, Error> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue