executor work

This commit is contained in:
John Smith
2022-06-27 23:46:29 -04:00
parent ebea72c9db
commit fdbb4c6397
59 changed files with 726 additions and 640 deletions

View File

@@ -10,6 +10,11 @@ license = "LGPL-2.0-or-later OR MPL-2.0 OR (MIT AND BSD-3-Clause)"
name = "veilid-cli"
path = "src/main.rs"
[features]
default = [ "rt-tokio" ]
rt-async-std = [ "async-std", "veilid-core/rt-async-std" ]
rt-tokio = [ "tokio", "tokio-util", "veilid-core/rt-tokio" ]
[target.'cfg(unix)'.dependencies]
cursive = { path = "../external/cursive/cursive", default-features = false, features = ["ncurses-backend", "toml", "rt-async-std"]}
@@ -17,9 +22,10 @@ cursive = { path = "../external/cursive/cursive", default-features = false, feat
cursive = { path = "../external/cursive/cursive", default-features = false, features = ["crossterm-backend", "toml", "rt-async-std"]}
[dependencies]
async-std = { version = "^1.9", features = ["unstable", "attributes"] }
async-tungstenite = { version = "^0.8", features = ["async-std-runtime"] }
async_executors = { version = "^0", default-features = false, features = [ "async_std" ]}
async-std = { version = "^1.9", features = ["unstable", "attributes"], optional = true }
tokio = { version = "^1", features = ["full"], optional = true }
tokio-util = { version = "^0", features = ["compat"], optional = true}
async-tungstenite = { version = "^0.8" }
cursive-flexi-logger-view = { path = "../external/cursive-flexi-logger-view" }
cursive_buffered_backend = { path = "../external/cursive_buffered_backend" }
# cursive-multiplex = "0.4.0"
@@ -41,7 +47,7 @@ bugsalot = "^0"
flexi_logger = { version = "^0", features = ["use_chrono_for_offset"] }
thiserror = "^1"
crossbeam-channel = "^0"
veilid-core = { path = "../veilid-core" }
veilid-core = { path = "../veilid-core", default_features = false}
[dev-dependencies]
serial_test = "^0"

View File

@@ -1,9 +1,8 @@
use crate::command_processor::*;
use crate::tools::*;
use crate::veilid_client_capnp::*;
use async_executors::{AsyncStd, LocalSpawnHandleExt};
use capnp::capability::Promise;
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, Disconnector, RpcSystem};
use futures::io::AsyncReadExt;
use std::cell::RefCell;
use std::net::SocketAddr;
use std::rc::Rc;
@@ -140,9 +139,7 @@ impl ClientApiConnection {
));
}
let rpc_jh = AsyncStd
.spawn_handle_local(rpc_system)
.map_err(|e| format!("failed to spawn rpc system: {}", e))?;
let rpc_jh = spawn_local(rpc_system);
// Send the request and get the state object and the registration object
let response = request
@@ -173,23 +170,43 @@ impl ClientApiConnection {
// object mapping from the server which we need for the update backchannel
// Wait until rpc system completion or disconnect was requested
rpc_jh
.await
.map_err(|e| format!("client RPC system error: {}", e))
cfg_if! {
if #[cfg(feature="rt-async-std")] {
rpc_jh
.await
.map_err(|e| format!("client RPC system error: {}", e))
} else if #[cfg(feature="rt-tokio")] {
rpc_jh
.await
.map_err(|e| format!("join error: {}", e))?
.map_err(|e| format!("client RPC system error: {}", e))
}
}
}
async fn handle_connection(&mut self) -> Result<(), String> {
trace!("ClientApiConnection::handle_connection");
let connect_addr = self.inner.borrow().connect_addr.unwrap();
// Connect the TCP socket
let stream = async_std::net::TcpStream::connect(connect_addr)
let stream = TcpStream::connect(connect_addr)
.await
.map_err(map_to_string)?;
// If it succeed, disable nagle algorithm
stream.set_nodelay(true).map_err(map_to_string)?;
// Create the VAT network
let (reader, writer) = stream.split();
cfg_if! {
if #[cfg(feature="rt-async-std")] {
let (reader, writer) = stream.split();
} else if #[cfg(feature="rt-tokio")] {
let (reader, writer) = stream.into_split();
let reader = reader.compat();
let writer = writer.compat_write();
}
}
let rpc_network = Box::new(twoparty::VatNetwork::new(
reader,
writer,

View File

@@ -1,7 +1,7 @@
use crate::client_api_connection::*;
use crate::settings::Settings;
use crate::tools::*;
use crate::ui::*;
use async_std::prelude::FutureExt;
use log::*;
use std::cell::*;
use std::net::SocketAddr;
@@ -116,7 +116,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_shutdown");
let mut capi = self.capi();
let ui = self.ui();
async_std::task::spawn_local(async move {
spawn_detached_local(async move {
if let Err(e) = capi.server_shutdown().await {
error!("Server command 'shutdown' failed to execute: {}", e);
}
@@ -129,7 +129,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_attach");
let mut capi = self.capi();
let ui = self.ui();
async_std::task::spawn_local(async move {
spawn_detached_local(async move {
if let Err(e) = capi.server_attach().await {
error!("Server command 'attach' failed to execute: {}", e);
}
@@ -142,7 +142,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_detach");
let mut capi = self.capi();
let ui = self.ui();
async_std::task::spawn_local(async move {
spawn_detached_local(async move {
if let Err(e) = capi.server_detach().await {
error!("Server command 'detach' failed to execute: {}", e);
}
@@ -155,7 +155,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_disconnect");
let mut capi = self.capi();
let ui = self.ui();
async_std::task::spawn_local(async move {
spawn_detached_local(async move {
capi.disconnect().await;
ui.send_callback(callback);
});
@@ -166,7 +166,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::cmd_debug");
let mut capi = self.capi();
let ui = self.ui();
async_std::task::spawn_local(async move {
spawn_detached_local(async move {
match capi.server_debug(rest.unwrap_or_default()).await {
Ok(output) => ui.display_string_dialog("Debug Output", output, callback),
Err(e) => {
@@ -248,9 +248,7 @@ debug - send a debugging command to the Veilid server
debug!("Connection lost, retrying in 2 seconds");
{
let waker = self.inner_mut().connection_waker.instance_clone(());
waker
.race(async_std::task::sleep(Duration::from_millis(2000)))
.await;
let _ = timeout(Duration::from_millis(2000), waker).await;
}
self.inner_mut().connection_waker.reset();
first = false;
@@ -306,7 +304,7 @@ debug - send a debugging command to the Veilid server
// pub fn stop_connection(&mut self) {
// self.inner_mut().reconnect = false;
// let mut capi = self.capi().clone();
// async_std::task::spawn_local(async move {
// spawn_detached(async move {
// capi.disconnect().await;
// });
// }
@@ -327,7 +325,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::attach");
let mut capi = self.capi();
async_std::task::spawn_local(async move {
spawn_detached_local(async move {
if let Err(e) = capi.server_attach().await {
error!("Server command 'attach' failed to execute: {}", e);
}
@@ -338,7 +336,7 @@ debug - send a debugging command to the Veilid server
trace!("CommandProcessor::detach");
let mut capi = self.capi();
async_std::task::spawn_local(async move {
spawn_detached_local(async move {
if let Err(e) = capi.server_detach().await {
error!("Server command 'detach' failed to execute: {}", e);
}

View File

@@ -3,16 +3,17 @@
use veilid_core::xx::*;
use async_std::prelude::*;
use clap::{Arg, ColorChoice, Command};
use flexi_logger::*;
use std::ffi::OsStr;
use std::net::ToSocketAddrs;
use std::path::Path;
use tools::*;
mod client_api_connection;
mod command_processor;
mod settings;
mod tools;
mod ui;
#[allow(clippy::all)]
@@ -60,8 +61,7 @@ fn parse_command_line(default_config_path: &OsStr) -> Result<clap::ArgMatches, S
Ok(matches)
}
#[async_std::main]
async fn main() -> Result<(), String> {
fn main() -> Result<(), String> {
// Get command line options
let default_config_path = settings::Settings::get_default_config_path();
let matches = parse_command_line(default_config_path.as_os_str())?;
@@ -170,17 +170,29 @@ async fn main() -> Result<(), String> {
comproc.set_server_address(server_addr);
let mut comproc2 = comproc.clone();
let connection_future = comproc.connection_manager();
// Start UI
let ui_future = async_std::task::spawn_local(async move {
sivui.run_async().await;
// When UI quits, close connection and command processor cleanly
comproc2.quit();
capi.disconnect().await;
// Start async
block_on(async move {
// Start UI
let ui_future = async move {
sivui.run_async().await;
// When UI quits, close connection and command processor cleanly
comproc2.quit();
capi.disconnect().await;
};
cfg_if! {
if #[cfg(feature="rt-async-std")] {
use async_std::prelude::*;
// Wait for ui and connection to complete
let _ = ui_future.join(connection_future).await;
} else if #[cfg(feature="rt-tokio")] {
// Wait for ui and connection to complete
let _ = tokio::join!(ui_future, connection_future);
}
}
});
// Wait for ui and connection to complete
ui_future.join(connection_future).await;
Ok(())
}

40
veilid-cli/src/tools.rs Normal file
View File

@@ -0,0 +1,40 @@
use cfg_if::*;
use core::future::Future;
cfg_if! {
if #[cfg(feature="rt-async-std")] {
pub use async_std::task::JoinHandle;
pub use async_std::net::TcpStream;
pub use async_std::future::TimeoutError;
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(f: F) -> JoinHandle<T> {
async_std::task::spawn_local(f)
}
pub fn spawn_detached_local<F: Future<Output = T> + 'static, T: 'static>(f: F) {
let _ = async_std::task::spawn_local(f);
}
pub use async_std::task::sleep;
pub use async_std::future::timeout;
pub fn block_on<F: Future<Output = T>, T>(f: F) -> T {
async_std::task::block_on(f)
}
} else if #[cfg(feature="rt-tokio")] {
pub use tokio::task::JoinHandle;
pub use tokio::net::TcpStream;
pub use tokio_util::compat::*;
pub use tokio::time::error::Elapsed as TimeoutError;
pub fn spawn_local<F: Future<Output = T> + 'static, T: 'static>(f: F) -> JoinHandle<T> {
tokio::task::spawn_local(f)
}
pub fn spawn_detached_local<F: Future<Output = T> + 'static, T: 'static>(f: F) {
let _ = tokio::task::spawn_local(f);
}
pub use tokio::time::sleep;
pub use tokio::time::timeout;
pub fn block_on<F: Future<Output = T>, T>(f: F) -> T {
let rt = tokio::runtime::Runtime::new().unwrap();
let local = tokio::task::LocalSet::new();
local.block_on(&rt, f)
}
}
}