From ea0923b5c7925983a949d9f297a94314216b02d7 Mon Sep 17 00:00:00 2001 From: Stan Date: Mon, 13 Jan 2020 19:11:03 +0200 Subject: [PATCH] Using futures 0.3.x and tokio 0.2.9 - Latest stable version for futures and tokio - Updated code and tests where applicable - Removed yamux submodule - Updated rust to nightly-2020-01-08 --- .circleci/config.yml | 2 +- Cargo.toml | 2 - .../console_text_messenger/Cargo.toml | 4 +- applications/grpc_wallet/Cargo.toml | 2 +- applications/tari_base_node/Cargo.toml | 5 +- applications/tari_base_node/src/builder.rs | 16 +- applications/tari_base_node/src/main.rs | 31 ++- applications/tari_testnet_miner/Cargo.toml | 5 +- base_layer/core/Cargo.toml | 6 +- base_layer/core/src/base_node/backoff.rs | 10 +- .../chain_metadata_service/initializer.rs | 4 +- .../chain_metadata_service/service.rs | 8 +- .../comms_interface/inbound_handlers.rs | 2 +- .../core/src/base_node/service/initializer.rs | 4 +- .../core/src/base_node/service/service.rs | 16 +- base_layer/core/src/chain_storage/async_db.rs | 206 +++++++++--------- base_layer/core/src/chain_storage/error.rs | 2 + .../core/src/mempool/service/initializer.rs | 4 +- .../core/src/mempool/service/service.rs | 14 +- base_layer/core/tests/helpers/nodes.rs | 38 ++-- base_layer/core/tests/mempool.rs | 22 +- base_layer/core/tests/node_service.rs | 72 +++--- base_layer/core/tests/node_state_machine.rs | 12 +- base_layer/p2p/Cargo.toml | 4 +- base_layer/p2p/examples/pingpong.rs | 9 +- .../src/comms_connector/inbound_connector.rs | 4 +- base_layer/p2p/src/comms_connector/pubsub.rs | 4 +- base_layer/p2p/src/initialization.rs | 6 +- base_layer/p2p/src/services/comms_outbound.rs | 4 +- base_layer/p2p/src/services/liveness/mod.rs | 4 +- .../p2p/src/services/liveness/service.rs | 120 +++++----- base_layer/p2p/tests/services/liveness.rs | 16 +- .../p2p/tests/support/comms_and_services.rs | 4 +- base_layer/service_framework/Cargo.toml | 4 +- .../service_framework/src/handles/future.rs | 2 +- .../src/handles/lazy_service.rs | 12 +- .../service_framework/src/initializer.rs | 18 +- .../service_framework/src/reply_channel.rs | 3 +- base_layer/service_framework/src/stack.rs | 16 +- .../src/tower/service_ext.rs | 4 +- .../service_framework/src/tower/service_fn.rs | 3 +- base_layer/wallet/Cargo.toml | 5 +- base_layer/wallet/src/contacts_service/mod.rs | 4 +- .../wallet/src/output_manager_service/mod.rs | 4 +- .../wallet/src/text_message_service/mod.rs | 4 +- .../wallet/src/transaction_service/mod.rs | 4 +- base_layer/wallet/src/wallet.rs | 10 +- .../wallet/tests/contacts_service/mod.rs | 8 +- .../tests/output_manager_service/service.rs | 40 ++-- .../tests/support/comms_and_services.rs | 4 +- .../transaction_service/callback_handler.rs | 8 +- .../tests/transaction_service/service.rs | 51 +++-- base_layer/wallet/tests/wallet/mod.rs | 4 +- base_layer/wallet_ffi/Cargo.toml | 4 +- comms/Cargo.toml | 10 +- comms/dht/Cargo.toml | 11 +- comms/dht/src/actor.rs | 25 ++- comms/dht/src/builder.rs | 6 +- comms/dht/src/dht.rs | 34 +-- comms/dht/src/discovery/requester.rs | 8 +- comms/dht/src/inbound/decryption.rs | 4 +- comms/dht/src/inbound/dedup.rs | 6 +- comms/dht/src/inbound/deserialize.rs | 4 +- .../dht/src/inbound/dht_handler/middleware.rs | 4 +- comms/dht/src/lib.rs | 1 + comms/dht/src/outbound/broadcast.rs | 9 +- comms/dht/src/outbound/encryption.rs | 4 +- comms/dht/src/outbound/serialize.rs | 4 +- comms/dht/src/store_forward/error.rs | 2 + comms/dht/src/store_forward/forward.rs | 6 +- .../store_forward/saf_handler/middleware.rs | 4 +- .../dht/src/store_forward/saf_handler/task.rs | 11 +- comms/dht/src/store_forward/store.rs | 4 +- comms/dht/src/test_utils/service.rs | 6 +- comms/dht/src/utils.rs | 30 +++ comms/dht/tests/dht.rs | 28 +-- comms/middleware/Cargo.toml | 8 +- comms/middleware/src/pipeline.rs | 39 ++-- comms/middleware/src/sink.rs | 4 +- comms/middleware/src/test_utils.rs | 3 +- comms/middleware/tower-filter/Cargo.toml | 13 +- comms/middleware/tower-filter/tests/filter.rs | 22 +- comms/src/builder/builder.rs | 16 +- comms/src/builder/mod.rs | 3 +- comms/src/builder/null_sink.rs | 4 +- .../connection_manager/deprecated/actor.rs | 8 +- .../connection_manager/deprecated/error.rs | 1 + .../connection_manager/deprecated/manager.rs | 10 +- comms/src/connection_manager/dialer.rs | 10 +- comms/src/connection_manager/listener.rs | 8 +- comms/src/connection_manager/manager.rs | 12 +- .../src/connection_manager/peer_connection.rs | 4 +- comms/src/connection_manager/protocol.rs | 2 +- comms/src/macros.rs | 2 +- comms/src/multiplexing/yamux.rs | 6 +- comms/src/noise/config.rs | 2 +- comms/src/noise/socket.rs | 8 +- comms/src/outbound_message_service/service.rs | 16 +- comms/src/peer_manager/async_peer_manager.rs | 6 +- comms/src/peer_manager/error.rs | 2 + comms/src/test_utils/tcp.rs | 2 +- comms/src/test_utils/test_node.rs | 2 +- comms/src/transports/tcp.rs | 48 ++-- comms/tests/connection_manager/actor.rs | 4 +- comms/tests/inbound_message_service/mod.rs | 18 +- comms/yamux | 1 - infrastructure/broadcast_channel/Cargo.toml | 4 +- .../broadcast_channel/src/async_channel.rs | 3 +- infrastructure/pubsub/Cargo.toml | 2 +- infrastructure/shutdown/Cargo.toml | 4 +- infrastructure/shutdown/src/lib.rs | 4 - infrastructure/test_utils/Cargo.toml | 7 +- .../src/futures/async_assert_eventually.rs | 2 +- infrastructure/test_utils/src/futures/mod.rs | 2 +- infrastructure/test_utils/src/runtime.rs | 78 +++++-- infrastructure/test_utils/src/streams/mod.rs | 16 +- rust-toolchain | 2 +- 117 files changed, 794 insertions(+), 709 deletions(-) create mode 100644 comms/dht/src/utils.rs delete mode 160000 comms/yamux diff --git a/.circleci/config.yml b/.circleci/config.yml index 6ccd535dd8..3033405382 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 defaults: - rust_image: &rust_image quay.io/tarilabs/rust_tari-build-with-deps:nightly-2019-10-04 + rust_image: &rust_image quay.io/tarilabs/rust_tari-build-with-deps:nightly-2020-01-08 jobs: test-docs: diff --git a/Cargo.toml b/Cargo.toml index 41103647da..68a7dce0f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,6 @@ members = [ "comms", "comms/dht", "comms/middleware", - # TODO: Remove this once tower filter (0.3.0-alpha.3) is released - "comms/middleware/tower-filter", "digital_assets_layer/core", "infrastructure/broadcast_channel", "infrastructure/crypto", diff --git a/applications/console_text_messenger/Cargo.toml b/applications/console_text_messenger/Cargo.toml index 90b04fa3ed..d5f2505aa1 100644 --- a/applications/console_text_messenger/Cargo.toml +++ b/applications/console_text_messenger/Cargo.toml @@ -19,11 +19,11 @@ clap = "2.33.0" config = { version = "0.9.3" } crossbeam-channel = "0.3.8" ctrlc = "3.1.3" -futures = { version = "=0.3.0-alpha.19", package = "futures-preview", features =["compat", "std"]} +futures = { version = "^0.3.1", features =["compat", "std"]} log = { version = "0.4.0", features = ["std"] } log4rs = {version ="0.8.3",features = ["console_appender", "file_appender", "file", "yaml_format"]} pnet = "0.22.0" serde = "1.0.90" serde_derive = "1.0.90" simple_logger = "1.2.0" -tokio = "0.2.0-alpha.6" \ No newline at end of file +tokio = "0.2.9" \ No newline at end of file diff --git a/applications/grpc_wallet/Cargo.toml b/applications/grpc_wallet/Cargo.toml index 0dd8987dcd..e57fa16ebf 100644 --- a/applications/grpc_wallet/Cargo.toml +++ b/applications/grpc_wallet/Cargo.toml @@ -17,7 +17,7 @@ crossbeam-channel = "0.3.8" bytes = "0.4" derive-error = "0.0.4" futures = "0.1" -futures03 = { version = "=0.3.0-alpha.18", package = "futures-preview", features =["compat", "std"]} +futures03 = { version = "^0.3.1", features =["compat", "std"]} http = "0.1" log = { version = "0.4.0", features = ["std"] } prost = "0.5" diff --git a/applications/tari_base_node/Cargo.toml b/applications/tari_base_node/Cargo.toml index ab41fa9985..97082cf7ab 100644 --- a/applications/tari_base_node/Cargo.toml +++ b/applications/tari_base_node/Cargo.toml @@ -21,10 +21,9 @@ tari_mmr = { path = "../../base_layer/mmr", version = "^0.0" } clap = "2.33.0" config = { version = "0.9.3" } dirs = "2.0.2" -futures-preview = { version = "=0.3.0-alpha.19", default-features = false, features = ["alloc"]} +futures = { version = "^0.3.1", default-features = false, features = ["alloc"]} log = { version = "0.4.8", features = ["std"] } log4rs = { version = "0.8.3", features = ["toml_format"] } rand = "0.5.5" serde_json = "1.0" -tokio = { version="=0.2.0-alpha.6", features = ["signal"] } -tokio-executor = { version ="=0.2.0-alpha.6", features = ["threadpool"] } \ No newline at end of file +tokio = { version="0.2.9", features = ["signal"] } diff --git a/applications/tari_base_node/src/builder.rs b/applications/tari_base_node/src/builder.rs index 4d2eb17828..fdc7064164 100644 --- a/applications/tari_base_node/src/builder.rs +++ b/applications/tari_base_node/src/builder.rs @@ -89,7 +89,7 @@ impl NodeType { NodeType::Memory(n) => n.run().await, } } - .await; + .await; } } @@ -161,7 +161,7 @@ pub fn create_and_save_id(path: &Path, control_addr: &str) -> Result Result<(CommsNode, NodeType), String> { let id = Arc::new(id); @@ -181,7 +181,7 @@ pub fn configure_and_initialize_node( let diff_adj_manager = DiffAdjManager::new(db.clone()).map_err(|e| e.to_string())?; rules.set_diff_manager(diff_adj_manager).map_err(|e| e.to_string())?; let (comms, handles) = - setup_comms_services(&rt, id.clone(), peers, &config.peer_db_path, db.clone(), mempool, rules); + setup_comms_services(rt, id.clone(), peers, &config.peer_db_path, db.clone(), mempool, rules); let outbound_interface = handles.get_handle::().unwrap(); ( comms, @@ -209,7 +209,7 @@ pub fn configure_and_initialize_node( let diff_adj_manager = DiffAdjManager::new(db.clone()).map_err(|e| e.to_string())?; rules.set_diff_manager(diff_adj_manager).map_err(|e| e.to_string())?; let (comms, handles) = - setup_comms_services(&rt, id.clone(), peers, &config.peer_db_path, db.clone(), mempool, rules); + setup_comms_services(rt, id.clone(), peers, &config.peer_db_path, db.clone(), mempool, rules); let outbound_interface = handles.get_handle::().unwrap(); ( comms, @@ -281,7 +281,7 @@ fn assign_peers(seeds: &[String]) -> Vec { } fn setup_comms_services( - rt: &Runtime, + rt: &mut Runtime, id: Arc, peers: Vec, peer_db_path: &str, @@ -293,7 +293,7 @@ where T: BlockchainBackend + 'static, { let node_config = BaseNodeServiceConfig::default(); // TODO - make this configurable - let (publisher, subscription_factory) = pubsub_connector(rt.executor(), 100); + let (publisher, subscription_factory) = pubsub_connector(rt.handle().clone(), 100); let subscription_factory = Arc::new(subscription_factory); let comms_config = CommsConfig { node_identity: id.clone(), @@ -314,14 +314,14 @@ where dht: Default::default(), // TODO - make this configurable }; - let (comms, dht) = initialize_comms(rt.executor(), comms_config, publisher).unwrap(); + let (comms, dht) = initialize_comms(rt.handle().clone(), comms_config, publisher).unwrap(); for p in peers { debug!(target: LOG_TARGET, "Adding seed peer [{}]", p.node_id); comms.peer_manager().add_peer(p).unwrap(); } - let fut = StackBuilder::new(rt.executor(), comms.shutdown_signal()) + let fut = StackBuilder::new(rt.handle().clone(), comms.shutdown_signal()) .add_initializer(CommsOutboundServiceInitializer::new(dht.outbound_requester())) .add_initializer(BaseNodeServiceInitializer::new( subscription_factory, diff --git a/applications/tari_base_node/src/main.rs b/applications/tari_base_node/src/main.rs index 3e9bc853ef..418e2ef68c 100644 --- a/applications/tari_base_node/src/main.rs +++ b/applications/tari_base_node/src/main.rs @@ -29,7 +29,6 @@ mod cli; mod consts; use crate::builder::{create_and_save_id, load_identity}; -use futures::{future, StreamExt}; use log::*; use std::sync::{ atomic::{AtomicBool, Ordering}, @@ -37,7 +36,7 @@ use std::sync::{ }; use tari_common::{load_configuration, GlobalConfig}; use tari_utilities::hex::Hex; -use tokio::{net::signal, runtime::Runtime}; +use tokio::{runtime::Runtime, signal, task}; const LOG_TARGET: &str = "base_node::app"; @@ -111,7 +110,7 @@ fn main() { }; // Set up the Tokio runtime - let rt = match setup_runtime(&node_config) { + let mut rt = match setup_runtime(&node_config) { Ok(rt) => rt, Err(s) => { error!(target: LOG_TARGET, "{}", s); @@ -120,7 +119,7 @@ fn main() { }; // Build, node, build! - let (comms, node) = match builder::configure_and_initialize_node(&node_config, node_id, &rt) { + let (comms, node) = match builder::configure_and_initialize_node(&node_config, node_id, &mut rt) { Ok(n) => n, Err(e) => { error!(target: LOG_TARGET, "Could not instantiate node instance. {}", e); @@ -130,10 +129,7 @@ fn main() { // Configure the shutdown daemon to listen for CTRL-C let flag = node.get_flag(); - if let Err(e) = handle_ctrl_c(&rt, flag) { - error!(target: LOG_TARGET, "Could not configure Ctrl-C handling. {}", e); - return; - }; + handle_ctrl_c(&rt, flag); // Run, node, run! let main = async move { @@ -151,8 +147,7 @@ fn main() { ), } }; - rt.spawn(main); - rt.shutdown_on_idle(); + rt.block_on(main); println!("Goodbye!"); } @@ -167,23 +162,23 @@ fn setup_runtime(config: &GlobalConfig) -> Result { num_blocking_threads ); tokio::runtime::Builder::new() - .blocking_threads(num_blocking_threads) + .threaded_scheduler() + .enable_all() + .max_threads(num_core_threads + num_blocking_threads) .core_threads(num_core_threads) .build() .map_err(|e| format!("There was an error while building the node runtime. {}", e.to_string())) } /// Set the interrupt flag on the node when Ctrl-C is entered -fn handle_ctrl_c(rt: &Runtime, flag: Arc) -> Result<(), String> { - let ctrl_c = signal::ctrl_c().map_err(|e| e.to_string())?; - let s = ctrl_c.take(1).for_each(move |_| { +fn handle_ctrl_c(rt: &Runtime, flag: Arc) -> task::JoinHandle> { + rt.spawn(async move { + signal::ctrl_c().await.map_err(|e| e.to_string())?; info!( target: LOG_TARGET, "Termination signal received from user. Shutting node down." ); flag.store(true, Ordering::SeqCst); - future::ready(()) - }); - rt.spawn(s); - Ok(()) + Ok(()) + }) } diff --git a/applications/tari_testnet_miner/Cargo.toml b/applications/tari_testnet_miner/Cargo.toml index 9ef4206b9b..fc2f9ae2e2 100644 --- a/applications/tari_testnet_miner/Cargo.toml +++ b/applications/tari_testnet_miner/Cargo.toml @@ -9,11 +9,10 @@ edition = "2018" [dependencies] log = { version = "0.4.8", features = ["std"] } tonic = "0.1.0-alpha.3" -tokio-executor= "=0.2.0-alpha.6" bytes = "0.4" prost = "0.5" -tokio = "=0.2.0-alpha.6" -futures-preview = { version = "=0.3.0-alpha.19", default-features = false, features = ["alloc"]} +tokio = "0.2.9" +futures= { version = "^0.3.1", default-features = false, features = ["alloc"]} async-stream = "0.1.2" http = "0.1" tower = "=0.3.0-alpha.2" diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index eb51c856d7..d2ff18706d 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -45,9 +45,8 @@ blake2 = "^0.8.0" bigint = "^4.4.1" ttl_cache = "0.5.1" croaring = "=0.3.9" -tokio = { version="^0.2.0-alpha.6" } -tokio-executor = { version ="^0.2.0-alpha.6", features = ["threadpool"] } -futures-preview = {version = "0.3.0-alpha.19", features = ["async-await"] } +tokio = { version="^0.2" } +futures = {version = "^0.3.1", features = ["async-await"] } lmdb-zero = "0.4.4" tower-service = { version="0.3.0-alpha.2" } crossbeam-channel = "0.3.8" @@ -60,6 +59,7 @@ tari_p2p = {path = "../../base_layer/p2p", version = "^0.0", features=["test-moc tari_test_utils = { path = "../../infrastructure/test_utils", version = "^0.0" } env_logger = "0.7.0" tempdir = "0.3.7" +tokio-macros = "0.2.3" [build-dependencies] tari_protobuf_build = { version = "^0.0", path="../../infrastructure/protobuf_build"} diff --git a/base_layer/core/src/base_node/backoff.rs b/base_layer/core/src/base_node/backoff.rs index 31d56c6fb5..dba83d3125 100644 --- a/base_layer/core/src/base_node/backoff.rs +++ b/base_layer/core/src/base_node/backoff.rs @@ -21,8 +21,8 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -use std::time::{Duration, Instant}; -use tokio::timer; +use std::time::Duration; +use tokio::time; /// A simple back-off strategy. `BackOff` is typically used in situations where you want to retry an operation a /// number of times, with an increasing delay between attempts @@ -105,9 +105,7 @@ impl BackOff { if self.is_finished() { return; } - let deadline = Instant::now() + self.delay; - let delay = timer::delay(deadline); - delay.await; + time::delay_for(self.delay).await; self.current_attempts += 1; self.delay = self.delay.mul_f64(self.backoff); } @@ -118,7 +116,7 @@ mod test { use crate::base_node::BackOff; use std::time::Duration; - #[tokio::test] + #[tokio_macros::test] async fn retry() { let mut retry = BackOff::new(3, Duration::from_millis(100), 1.5); assert_eq!(retry.attempts(), 0); diff --git a/base_layer/core/src/base_node/chain_metadata_service/initializer.rs b/base_layer/core/src/base_node/chain_metadata_service/initializer.rs index ea0dcd74bb..d77a83bfa6 100644 --- a/base_layer/core/src/base_node/chain_metadata_service/initializer.rs +++ b/base_layer/core/src/base_node/chain_metadata_service/initializer.rs @@ -29,7 +29,7 @@ use tari_broadcast_channel as broadcast_channel; use tari_p2p::services::liveness::LivenessHandle; use tari_service_framework::{handles::ServiceHandlesFuture, ServiceInitializationError, ServiceInitializer}; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const BROADCAST_EVENT_BUFFER_SIZE: usize = 10; @@ -40,7 +40,7 @@ impl ServiceInitializer for ChainMetadataServiceInitializer { fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/core/src/base_node/chain_metadata_service/service.rs b/base_layer/core/src/base_node/chain_metadata_service/service.rs index dba780c5d9..3fa0ce5fbc 100644 --- a/base_layer/core/src/base_node/chain_metadata_service/service.rs +++ b/base_layer/core/src/base_node/chain_metadata_service/service.rs @@ -306,7 +306,7 @@ mod test { }); } - #[tokio::test] + #[tokio_macros::test] async fn handle_liveness_event_ok() { let (liveness_handle, _) = create_p2p_liveness_mock(1); let mut metadata = Metadata::new(); @@ -344,7 +344,7 @@ mod test { ); } - #[tokio::test] + #[tokio_macros::test] async fn handle_liveness_event_no_metadata() { let (liveness_handle, _) = create_p2p_liveness_mock(1); let metadata = Metadata::new(); @@ -367,7 +367,7 @@ mod test { assert_eq!(service.peer_chain_metadata.len(), 0); } - #[tokio::test] + #[tokio_macros::test] async fn handle_liveness_event_not_neighbour() { let (liveness_handle, _) = create_p2p_liveness_mock(1); let metadata = Metadata::new(); @@ -389,7 +389,7 @@ mod test { assert_eq!(service.peer_chain_metadata.len(), 0); } - #[tokio::test] + #[tokio_macros::test] async fn handle_liveness_event_bad_metadata() { let (liveness_handle, _) = create_p2p_liveness_mock(1); let mut metadata = Metadata::new(); diff --git a/base_layer/core/src/base_node/comms_interface/inbound_handlers.rs b/base_layer/core/src/base_node/comms_interface/inbound_handlers.rs index 39269e18b4..ae8434b292 100644 --- a/base_layer/core/src/base_node/comms_interface/inbound_handlers.rs +++ b/base_layer/core/src/base_node/comms_interface/inbound_handlers.rs @@ -64,7 +64,7 @@ where T: BlockchainBackend } impl InboundNodeCommsHandlers -where T: BlockchainBackend +where T: BlockchainBackend + 'static { /// Construct a new InboundNodeCommsInterface. pub fn new( diff --git a/base_layer/core/src/base_node/service/initializer.rs b/base_layer/core/src/base_node/service/initializer.rs index 270aa6e862..acb316aec8 100644 --- a/base_layer/core/src/base_node/service/initializer.rs +++ b/base_layer/core/src/base_node/service/initializer.rs @@ -51,7 +51,7 @@ use tari_service_framework::{ ServiceInitializer, }; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &'static str = "base_node::service::initializer"; @@ -149,7 +149,7 @@ where T: BlockchainBackend + 'static fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/core/src/base_node/service/service.rs b/base_layer/core/src/base_node/service/service.rs index 159baaa2c4..29f47a0d73 100644 --- a/base_layer/core/src/base_node/service/service.rs +++ b/base_layer/core/src/base_node/service/service.rs @@ -51,11 +51,7 @@ use futures::{ Stream, }; use log::*; -use std::{ - collections::HashMap, - convert::TryInto, - time::{Duration, Instant}, -}; +use std::{collections::HashMap, convert::TryInto, time::Duration}; use tari_comms::types::CommsPublicKey; use tari_comms_dht::{ domain_message::OutboundDomainMessage, @@ -64,7 +60,7 @@ use tari_comms_dht::{ }; use tari_p2p::{domain_message::DomainMessage, tari_message::TariMessageType}; use tari_service_framework::RequestContext; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &'static str = "tari_core::base_node::base_node_service::service"; @@ -137,7 +133,7 @@ where /// The Base Node Service is responsible for handling inbound requests and responses and for sending new requests to /// remote Base Node Services. pub struct BaseNodeService { - executor: TaskExecutor, + executor: runtime::Handle, outbound_message_service: OutboundMessageRequester, inbound_nch: InboundNodeCommsHandlers, waiting_requests: HashMap, @@ -147,10 +143,10 @@ pub struct BaseNodeService { } impl BaseNodeService -where B: BlockchainBackend +where B: BlockchainBackend + 'static { pub fn new( - executor: TaskExecutor, + executor: runtime::Handle, outbound_message_service: OutboundMessageRequester, inbound_nch: InboundNodeCommsHandlers, config: BaseNodeServiceConfig, @@ -470,7 +466,7 @@ where B: BlockchainBackend async fn spawn_request_timeout(&self, request_key: RequestKey, timeout: Duration) { let mut timeout_sender = self.timeout_sender.clone(); self.executor.spawn(async move { - tokio::timer::delay(Instant::now() + timeout).await; + tokio::time::delay_for(timeout).await; let _ = timeout_sender.send(request_key).await; }); } diff --git a/base_layer/core/src/chain_storage/async_db.rs b/base_layer/core/src/chain_storage/async_db.rs index 3356e5bce2..77e703aabe 100644 --- a/base_layer/core/src/chain_storage/async_db.rs +++ b/base_layer/core/src/chain_storage/async_db.rs @@ -32,122 +32,126 @@ use crate::{ MmrTree, }, }; -use futures::future::poll_fn; -use std::task::Poll; use tari_mmr::MerkleProof; use tari_transactions::{ transaction::{TransactionKernel, TransactionOutput}, types::HashOutput, }; -use tokio_executor::threadpool::blocking; macro_rules! make_async { ($fn:ident() -> $rtype:ty) => { pub async fn $fn(db: BlockchainDatabase) -> Result<$rtype, ChainStorageError> - where T: BlockchainBackend { - poll_fn(move |_| { - let db = db.clone(); - match blocking(move || db.$fn()) { - Poll::Pending => Poll::Pending, - // Map BlockingError -> ChainStorageError - Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( - "Could not find a blocking thread to execute DB query. {}", - e.to_string() - )))), - // Unwrap and lift ChainStorageError - Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), - // Unwrap and return result - Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), - } - }) - .await + where T: BlockchainBackend + 'static { + tokio::task::spawn_blocking(move || { + db.$fn() + }) + // poll_fn(move |_| { + // match blocking(move || db.$fn()) { + // Poll::Pending => Poll::Pending, + // Map BlockingError -> ChainStorageError + // Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( + // "Could not find a blocking thread to execute DB query. {}", + // e.to_string() + // )))), + // Unwrap and lift ChainStorageError + // Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), + // Unwrap and return result + // Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), + // } + // }) + .await + .or_else(|err| Err(ChainStorageError::BlockingTaskSpawnError(err.to_string()))) + .and_then(|inner_result| inner_result) } }; - ($fn:ident($param:ident:$ptype:ty) -> $rtype:ty) => { - pub async fn $fn(db: BlockchainDatabase, $param: $ptype) -> Result<$rtype, ChainStorageError> - where T: BlockchainBackend { - poll_fn(move |_| { - let db = db.clone(); - let hash = $param.clone(); - match blocking(move || db.$fn(hash)) { - Poll::Pending => Poll::Pending, - // Map BlockingError -> ChainStorageError - Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( - "Could not find a blocking thread to execute DB query. {}", - e.to_string() - )))), - // Unwrap and lift ChainStorageError - Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), - // Unwrap and return result - Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), - } - }) - .await + ($fn:ident($($param:ident:$ptype:ty),+) -> $rtype:ty) => { + pub async fn $fn(db: BlockchainDatabase, $($param: $ptype),+) -> Result<$rtype, ChainStorageError> + where T: BlockchainBackend + 'static { + tokio::task::spawn_blocking(move || db.$fn($($param),+)) + .await + .or_else(|err| Err(ChainStorageError::BlockingTaskSpawnError(err.to_string()))) + .and_then(|inner_result| inner_result) + // poll_fn(move |_| { + // let db = db.clone(); + // match blocking(move || db.$fn(hash)) { + // Poll::Pending => Poll::Pending, + // // Map BlockingError -> ChainStorageError + // Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( + // "Could not find a blocking thread to execute DB query. {}", + // e.to_string() + // )))), + // // Unwrap and lift ChainStorageError + // Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), + // // Unwrap and return result + // Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), + // } + // }) + // .await } }; - ($fn:ident($param1:ident:$ptype1:ty,$param2:ident:$ptype2:ty) -> $rtype:ty) => { - pub async fn $fn( - db: BlockchainDatabase, - $param1: $ptype1, - $param2: $ptype2, - ) -> Result<$rtype, ChainStorageError> - where - T: BlockchainBackend, - { - poll_fn(move |_| { - let db = db.clone(); - let p1 = $param1.clone(); - let p2 = $param2.clone(); - match blocking(move || db.$fn(p1, p2)) { - Poll::Pending => Poll::Pending, - // Map BlockingError -> ChainStorageError - Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( - "Could not find a blocking thread to execute DB query. {}", - e.to_string() - )))), - // Unwrap and lift ChainStorageError - Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), - // Unwrap and return result - Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), - } - }) - .await - } - }; - - ($fn:ident($param1:ident:$ptype1:ty,$param2:ident:$ptype2:ty,$param3:ident:$ptype3:ty) -> $rtype:ty) => { - pub async fn $fn( - db: BlockchainDatabase, - $param1: $ptype1, - $param2: $ptype2, - $param3: $ptype3, - ) -> Result<$rtype, ChainStorageError> - where - T: BlockchainBackend, - { - poll_fn(move |_| { - let db = db.clone(); - let p1 = $param1.clone(); - let p2 = $param2.clone(); - let p3 = $param3.clone(); - match blocking(move || db.$fn(p1, p2, p3)) { - Poll::Pending => Poll::Pending, - // Map BlockingError -> ChainStorageError - Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( - "Could not find a blocking thread to execute DB query. {}", - e.to_string() - )))), - // Unwrap and lift ChainStorageError - Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), - // Unwrap and return result - Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), - } - }) - .await - } - }; +// ($fn:ident($param1:ident:$ptype1:ty,$param2:ident:$ptype2:ty) -> $rtype:ty) => { +// pub async fn $fn( +// db: BlockchainDatabase, +// $param1: $ptype1, +// $param2: $ptype2, +// ) -> Result<$rtype, ChainStorageError> +// where +// T: BlockchainBackend, +// { +// poll_fn(move |_| { +// let db = db.clone(); +// let p1 = $param1.clone(); +// let p2 = $param2.clone(); +// match blocking(move || db.$fn(p1, p2)) { +// Poll::Pending => Poll::Pending, +// // Map BlockingError -> ChainStorageError +// Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( +// "Could not find a blocking thread to execute DB query. {}", +// e.to_string() +// )))), +// // Unwrap and lift ChainStorageError +// Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), +// // Unwrap and return result +// Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), +// } +// }) +// .await +// } +// }; +// +// ($fn:ident($param1:ident:$ptype1:ty,$param2:ident:$ptype2:ty,$param3:ident:$ptype3:ty) -> $rtype:ty) => { +// pub async fn $fn( +// db: BlockchainDatabase, +// $param1: $ptype1, +// $param2: $ptype2, +// $param3: $ptype3, +// ) -> Result<$rtype, ChainStorageError> +// where +// T: BlockchainBackend, +// { +// poll_fn(move |_| { +// let db = db.clone(); +// let p1 = $param1.clone(); +// let p2 = $param2.clone(); +// let p3 = $param3.clone(); +// match blocking(move || db.$fn(p1, p2, p3)) { +// Poll::Pending => Poll::Pending, +// // Map BlockingError -> ChainStorageError +// Poll::Ready(Err(e)) => Poll::Ready(Err(ChainStorageError::AccessError(format!( +// "Could not find a blocking thread to execute DB query. {}", +// e.to_string() +// )))), +// // Unwrap and lift ChainStorageError +// Poll::Ready(Ok(Err(e))) => Poll::Ready(Err(e)), +// // Unwrap and return result +// Poll::Ready(Ok(Ok(v))) => Poll::Ready(Ok(v)), +// } +// }) +// .await +// } +// }; } make_async!(get_metadata() -> ChainMetadata); diff --git a/base_layer/core/src/chain_storage/error.rs b/base_layer/core/src/chain_storage/error.rs index 557937222f..ccfe365ec7 100644 --- a/base_layer/core/src/chain_storage/error.rs +++ b/base_layer/core/src/chain_storage/error.rs @@ -66,4 +66,6 @@ pub enum ChainStorageError { MismatchedMmrRoot(MmrTree), // An invalid block was submitted to the database InvalidBlock, + #[error(msg_embedded, non_std, no_from)] + BlockingTaskSpawnError(String), } diff --git a/base_layer/core/src/mempool/service/initializer.rs b/base_layer/core/src/mempool/service/initializer.rs index 4fdc867769..d81e66b2e5 100644 --- a/base_layer/core/src/mempool/service/initializer.rs +++ b/base_layer/core/src/mempool/service/initializer.rs @@ -51,7 +51,7 @@ use tari_service_framework::{ }; use tari_shutdown::ShutdownSignal; use tari_transactions::{proto::types::Transaction as ProtoTransaction, transaction::Transaction}; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &'static str = "base_node::mempool_service::initializer"; @@ -143,7 +143,7 @@ where T: BlockchainBackend + 'static fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/core/src/mempool/service/service.rs b/base_layer/core/src/mempool/service/service.rs index 4ba37e8f4d..a0685b1a9a 100644 --- a/base_layer/core/src/mempool/service/service.rs +++ b/base_layer/core/src/mempool/service/service.rs @@ -45,11 +45,7 @@ use futures::{ Stream, }; use log::*; -use std::{ - collections::HashMap, - convert::TryInto, - time::{Duration, Instant}, -}; +use std::{collections::HashMap, convert::TryInto, time::Duration}; use tari_comms_dht::{ domain_message::OutboundDomainMessage, envelope::NodeDestination, @@ -58,7 +54,7 @@ use tari_comms_dht::{ use tari_p2p::{domain_message::DomainMessage, tari_message::TariMessageType}; use tari_service_framework::RequestContext; use tari_transactions::{proto::types::Transaction as ProtoTransaction, transaction::Transaction}; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &'static str = "tari_core::base_node::mempool::service"; @@ -111,7 +107,7 @@ where /// The Mempool Service is responsible for handling inbound requests and responses and for sending new requests to the /// Mempools of remote Base nodes. pub struct MempoolService { - executor: TaskExecutor, + executor: runtime::Handle, outbound_message_service: OutboundMessageRequester, inbound_handlers: MempoolInboundHandlers, waiting_requests: HashMap>>>, @@ -124,7 +120,7 @@ impl MempoolService where B: BlockchainBackend { pub fn new( - executor: TaskExecutor, + executor: runtime::Handle, outbound_message_service: OutboundMessageRequester, inbound_handlers: MempoolInboundHandlers, config: MempoolServiceConfig, @@ -381,7 +377,7 @@ where B: BlockchainBackend async fn spawn_request_timeout(&self, request_key: RequestKey, timeout: Duration) { let mut timeout_sender = self.timeout_sender.clone(); self.executor.spawn(async move { - tokio::timer::delay(Instant::now() + timeout).await; + tokio::time::delay_for(timeout).await; let _ = timeout_sender.send(request_key).await; }); } diff --git a/base_layer/core/tests/helpers/nodes.rs b/base_layer/core/tests/helpers/nodes.rs index 4c7c8a42a6..4fe7c593b9 100644 --- a/base_layer/core/tests/helpers/nodes.rs +++ b/base_layer/core/tests/helpers/nodes.rs @@ -57,7 +57,7 @@ use tari_p2p::{ use tari_service_framework::StackBuilder; use tari_test_utils::address::get_next_local_address; use tari_transactions::types::HashDigest; -use tokio::runtime::{Runtime, TaskExecutor}; +use tokio::runtime::{self, Runtime}; /// The NodeInterfaces is used as a container for providing access to all the services and interfaces of a single node. pub struct NodeInterfaces { @@ -145,7 +145,7 @@ impl BaseNodeBuilder { } /// Build the test base node and start its services. - pub fn start(self, runtime: &Runtime, data_path: &str) -> NodeInterfaces { + pub fn start(self, runtime: &mut Runtime, data_path: &str) -> NodeInterfaces { let mct_config = self.mct_config.unwrap_or(MerkleChangeTrackerConfig { min_history_len: 10, max_history_len: 20, @@ -166,7 +166,7 @@ impl BaseNodeBuilder { let node_identity = self.node_identity.unwrap_or(random_node_identity()); let (outbound_nci, local_nci, outbound_mp_interface, outbound_message_service, comms) = setup_base_node_services( - &runtime, + runtime, node_identity.clone(), self.peers.unwrap_or(Vec::new()), blockchain_db.clone(), @@ -192,25 +192,25 @@ impl BaseNodeBuilder { } // Creates a network with two Base Nodes where each node in the network knows the other nodes in the network. -pub fn create_network_with_2_base_nodes(runtime: &Runtime, data_path: &str) -> (NodeInterfaces, NodeInterfaces) { +pub fn create_network_with_2_base_nodes(runtime: &mut Runtime, data_path: &str) -> (NodeInterfaces, NodeInterfaces) { let alice_node_identity = random_node_identity(); let bob_node_identity = random_node_identity(); let alice_node = BaseNodeBuilder::new() .with_node_identity(alice_node_identity.clone()) .with_peers(vec![bob_node_identity.clone()]) - .start(&runtime, data_path); + .start(runtime, data_path); let bob_node = BaseNodeBuilder::new() .with_node_identity(bob_node_identity) .with_peers(vec![alice_node_identity]) - .start(&runtime, data_path); + .start(runtime, data_path); (alice_node, bob_node) } // Creates a network with two Base Nodes where each node in the network knows the other nodes in the network. pub fn create_network_with_2_base_nodes_with_config( - runtime: &Runtime, + runtime: &mut Runtime, base_node_service_config: BaseNodeServiceConfig, mct_config: MerkleChangeTrackerConfig, mempool_service_config: MempoolServiceConfig, @@ -226,21 +226,21 @@ pub fn create_network_with_2_base_nodes_with_config( .with_base_node_service_config(base_node_service_config) .with_merkle_change_tracker_config(mct_config) .with_mempool_service_config(mempool_service_config) - .start(&runtime, data_path); + .start(runtime, data_path); let bob_node = BaseNodeBuilder::new() .with_node_identity(bob_node_identity) .with_peers(vec![alice_node_identity]) .with_base_node_service_config(base_node_service_config) .with_merkle_change_tracker_config(mct_config) .with_mempool_service_config(mempool_service_config) - .start(&runtime, data_path); + .start(runtime, data_path); (alice_node, bob_node) } // Creates a network with three Base Nodes where each node in the network knows the other nodes in the network. pub fn create_network_with_3_base_nodes( - runtime: &Runtime, + runtime: &mut Runtime, data_path: &str, ) -> (NodeInterfaces, NodeInterfaces, NodeInterfaces) { @@ -259,7 +259,7 @@ pub fn create_network_with_3_base_nodes( // Creates a network with three Base Nodes where each node in the network knows the other nodes in the network. pub fn create_network_with_3_base_nodes_with_config( - runtime: &Runtime, + runtime: &mut Runtime, base_node_service_config: BaseNodeServiceConfig, mct_config: MerkleChangeTrackerConfig, mempool_service_config: MempoolServiceConfig, @@ -276,21 +276,21 @@ pub fn create_network_with_3_base_nodes_with_config( .with_base_node_service_config(base_node_service_config) .with_merkle_change_tracker_config(mct_config) .with_mempool_service_config(mempool_service_config) - .start(&runtime, data_path); + .start(runtime, data_path); let bob_node = BaseNodeBuilder::new() .with_node_identity(bob_node_identity.clone()) .with_peers(vec![alice_node_identity.clone(), carol_node_identity.clone()]) .with_base_node_service_config(base_node_service_config) .with_merkle_change_tracker_config(mct_config) .with_mempool_service_config(mempool_service_config) - .start(&runtime, data_path); + .start(runtime, data_path); let carol_node = BaseNodeBuilder::new() .with_node_identity(carol_node_identity.clone()) .with_peers(vec![alice_node_identity, bob_node_identity.clone()]) .with_base_node_service_config(base_node_service_config) .with_merkle_change_tracker_config(mct_config) .with_mempool_service_config(mempool_service_config) - .start(&runtime, data_path); + .start(runtime, data_path); (alice_node, bob_node, carol_node) } @@ -315,7 +315,7 @@ pub fn random_node_identity() -> Arc { // Helper function for starting the comms stack. fn setup_comms_services( - executor: TaskExecutor, + executor: runtime::Handle, node_identity: Arc, peers: Vec>, publisher: InboundDomainConnector, @@ -364,7 +364,7 @@ where // Helper function for starting the services of the Base node. fn setup_base_node_services( - runtime: &Runtime, + runtime: &mut Runtime, node_identity: Arc, peers: Vec>, blockchain_db: BlockchainDatabase>, @@ -381,11 +381,11 @@ fn setup_base_node_services( CommsNode, ) { - let (publisher, subscription_factory) = pubsub_connector(runtime.executor(), 100); + let (publisher, subscription_factory) = pubsub_connector(runtime.handle().clone(), 100); let subscription_factory = Arc::new(subscription_factory); - let (comms, dht) = setup_comms_services(runtime.executor(), node_identity, peers, publisher, data_path); + let (comms, dht) = setup_comms_services(runtime.handle().clone(), node_identity, peers, publisher, data_path); - let fut = StackBuilder::new(runtime.executor(), comms.shutdown_signal()) + let fut = StackBuilder::new(runtime.handle().clone(), comms.shutdown_signal()) .add_initializer(CommsOutboundServiceInitializer::new(dht.outbound_requester())) .add_initializer(BaseNodeServiceInitializer::new( subscription_factory.clone(), diff --git a/base_layer/core/tests/mempool.rs b/base_layer/core/tests/mempool.rs index e83d5c0a61..47d6215fcf 100644 --- a/base_layer/core/tests/mempool.rs +++ b/base_layer/core/tests/mempool.rs @@ -32,11 +32,7 @@ use helpers::{ }, sample_blockchains::create_new_blockchain, }; -use std::{ - ops::Deref, - sync::Arc, - time::{Duration, Instant}, -}; +use std::{ops::Deref, sync::Arc, time::Duration}; use tari_comms_dht::{domain_message::OutboundDomainMessage, outbound::OutboundEncryption}; use tari_core::{ base_node::service::BaseNodeServiceConfig, @@ -391,9 +387,9 @@ fn test_orphaned_mempool_transactions() { #[test] fn request_response_get_stats() { let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); - let (mut alice, bob) = create_network_with_2_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + let (mut alice, bob) = create_network_with_2_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); // Create a Genesis block, and a tx spending the genesis output. Then create 2 orphan txs let (block0, utxo) = create_genesis_block(&bob.blockchain_db, &factories); @@ -438,10 +434,10 @@ fn request_response_get_stats() { #[test] fn request_response_get_tx_state_with_excess_sig() { let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node, carol_node) = - create_network_with_3_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + create_network_with_3_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); let (block0, utxo) = create_genesis_block(&bob_node.blockchain_db, &factories); bob_node.blockchain_db.add_block(block0.clone()).unwrap(); @@ -497,10 +493,10 @@ fn request_response_get_tx_state_with_excess_sig() { #[test] fn receive_and_propagate_transaction() { let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node, carol_node) = - create_network_with_3_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + create_network_with_3_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); let (block0, utxo) = create_genesis_block(&alice_node.blockchain_db, &factories); alice_node.blockchain_db.add_block(block0.clone()).unwrap(); @@ -566,7 +562,7 @@ fn receive_and_propagate_transaction() { #[test] fn service_request_timeout() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let mempool_service_config = MempoolServiceConfig { request_timeout: Duration::from_millis(1), @@ -577,7 +573,7 @@ fn service_request_timeout() { }; let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node) = create_network_with_2_base_nodes_with_config( - &runtime, + &mut runtime, BaseNodeServiceConfig::default(), mct_config, mempool_service_config, diff --git a/base_layer/core/tests/node_service.rs b/base_layer/core/tests/node_service.rs index 722ed5cae2..51543ae780 100644 --- a/base_layer/core/tests/node_service.rs +++ b/base_layer/core/tests/node_service.rs @@ -40,7 +40,7 @@ use helpers::{ BaseNodeBuilder, }, }; -use std::time::{Duration, Instant}; +use std::time::Duration; use tari_core::{ base_node::{ comms_interface::{BlockEvent, CommsInterfaceError}, @@ -67,11 +67,11 @@ use tokio::runtime::Runtime; #[test] fn request_response_get_metadata() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let factories = CryptoFactories::default(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node, carol_node) = - create_network_with_3_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + create_network_with_3_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); let (block0, _) = create_genesis_block(&bob_node.blockchain_db, &factories); bob_node.blockchain_db.add_block(block0).unwrap(); runtime.block_on(async { @@ -94,10 +94,10 @@ fn request_response_get_metadata() { #[test] fn request_and_response_fetch_headers() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node, carol_node) = - create_network_with_3_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + create_network_with_3_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); let mut headerb1 = BlockHeader::new(0); headerb1.height = 1; @@ -138,10 +138,10 @@ fn request_and_response_fetch_headers() { #[test] fn request_and_response_fetch_kernels() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node, carol_node) = - create_network_with_3_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + create_network_with_3_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); let kernel1 = create_test_kernel(5.into(), 0); let kernel2 = create_test_kernel(10.into(), 1); @@ -179,11 +179,11 @@ fn request_and_response_fetch_kernels() { #[test] fn request_and_response_fetch_utxos() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let factories = CryptoFactories::default(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node, carol_node) = - create_network_with_3_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + create_network_with_3_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); let (utxo1, _) = create_utxo(MicroTari(10_000), &factories); let (utxo2, _) = create_utxo(MicroTari(15_000), &factories); @@ -217,10 +217,10 @@ fn request_and_response_fetch_utxos() { #[test] fn request_and_response_fetch_blocks() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, mut bob_node, carol_node) = - create_network_with_3_base_nodes(&runtime, temp_dir.path().to_str().unwrap()); + create_network_with_3_base_nodes(&mut runtime, temp_dir.path().to_str().unwrap()); let factories = CryptoFactories::default(); let db = &mut bob_node.blockchain_db; let (block0, _) = create_genesis_block(db, &factories); @@ -253,7 +253,7 @@ fn request_and_response_fetch_blocks() { #[test] fn request_and_response_fetch_mmr_state() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let factories = CryptoFactories::default(); let mct_config = MerkleChangeTrackerConfig { min_history_len: 1, @@ -261,7 +261,7 @@ fn request_and_response_fetch_mmr_state() { }; let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice, mut bob) = create_network_with_2_base_nodes_with_config( - &runtime, + &mut runtime, BaseNodeServiceConfig::default(), mct_config, MempoolServiceConfig::default(), @@ -341,11 +341,7 @@ fn request_and_response_fetch_mmr_state() { pub async fn event_stream_next(mut stream: TStream, timeout: Duration) -> Option where TStream: Stream + FusedStream + Unpin { - let either = future::select( - stream.select_next_some(), - tokio::timer::delay(Instant::now() + timeout).fuse(), - ) - .await; + let either = future::select(stream.select_next_some(), tokio::time::delay_for(timeout).fuse()).await; match either { Either::Left((v, _)) => Some(v), @@ -355,7 +351,7 @@ where TStream: Stream + FusedStream + Unpin { #[test] fn propagate_and_forward_valid_block() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let factories = CryptoFactories::default(); // Alice will propagate block to bob, bob will receive it, verify it and then propagate it to carol and dan. Dan and @@ -373,7 +369,7 @@ fn propagate_and_forward_valid_block() { let mut alice_node = BaseNodeBuilder::new() .with_node_identity(alice_node_identity.clone()) .with_peers(vec![bob_node_identity.clone()]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let bob_node = BaseNodeBuilder::new() .with_node_identity(bob_node_identity.clone()) .with_peers(vec![ @@ -381,15 +377,15 @@ fn propagate_and_forward_valid_block() { carol_node_identity.clone(), dan_node_identity.clone(), ]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let carol_node = BaseNodeBuilder::new() .with_node_identity(carol_node_identity.clone()) .with_peers(vec![bob_node_identity.clone(), dan_node_identity.clone()]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let dan_node = BaseNodeBuilder::new() .with_node_identity(dan_node_identity) .with_peers(vec![bob_node_identity, carol_node_identity]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let db = &alice_node.blockchain_db; let (block0, _) = create_genesis_block(db, &factories); @@ -444,7 +440,7 @@ fn propagate_and_forward_valid_block() { #[test] fn propagate_and_forward_invalid_block() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let factories = CryptoFactories::default(); // Alice will propagate an invalid block to Carol and Bob, they will check the received block and not propagate the @@ -461,19 +457,19 @@ fn propagate_and_forward_invalid_block() { let mut alice_node = BaseNodeBuilder::new() .with_node_identity(alice_node_identity.clone()) .with_peers(vec![bob_node_identity.clone(), carol_node_identity.clone()]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let bob_node = BaseNodeBuilder::new() .with_node_identity(bob_node_identity.clone()) .with_peers(vec![alice_node_identity.clone(), dan_node_identity.clone()]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let carol_node = BaseNodeBuilder::new() .with_node_identity(carol_node_identity.clone()) .with_peers(vec![alice_node_identity, dan_node_identity.clone()]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let dan_node = BaseNodeBuilder::new() .with_node_identity(dan_node_identity) .with_peers(vec![bob_node_identity, carol_node_identity]) - .start(&runtime, temp_dir.path().to_str().unwrap()); + .start(&mut runtime, temp_dir.path().to_str().unwrap()); let db = &alice_node.blockchain_db; let (block0, _) = create_genesis_block(db, &factories); @@ -522,7 +518,7 @@ fn propagate_and_forward_invalid_block() { #[test] fn service_request_timeout() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let base_node_service_config = BaseNodeServiceConfig { request_timeout: Duration::from_millis(1), desired_response_fraction: BASE_NODE_SERVICE_DESIRED_RESPONSE_FRACTION, @@ -533,7 +529,7 @@ fn service_request_timeout() { }; let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut alice_node, bob_node) = create_network_with_2_base_nodes_with_config( - &runtime, + &mut runtime, base_node_service_config, mct_config, MempoolServiceConfig::default(), @@ -553,10 +549,10 @@ fn service_request_timeout() { #[test] fn local_get_metadata() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let factories = CryptoFactories::default(); - let mut node = BaseNodeBuilder::new().start(&runtime, temp_dir.path().to_str().unwrap()); + let mut node = BaseNodeBuilder::new().start(&mut runtime, temp_dir.path().to_str().unwrap()); let db = &node.blockchain_db; let (block0, _) = create_genesis_block(db, &factories); db.add_block(block0.clone()).unwrap(); @@ -575,9 +571,9 @@ fn local_get_metadata() { #[test] fn local_get_new_block_template_and_get_new_block() { let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); - let mut node = BaseNodeBuilder::new().start(&runtime, temp_dir.path().to_str().unwrap()); + let mut node = BaseNodeBuilder::new().start(&mut runtime, temp_dir.path().to_str().unwrap()); let db = &node.blockchain_db; let (block0, outputs) = create_genesis_block_with_utxos(db, &factories, &[T, T]); @@ -609,10 +605,10 @@ fn local_get_new_block_template_and_get_new_block() { #[test] fn local_get_target_difficulty() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let factories = CryptoFactories::default(); - let mut node = BaseNodeBuilder::new().start(&runtime, temp_dir.path().to_str().unwrap()); + let mut node = BaseNodeBuilder::new().start(&mut runtime, temp_dir.path().to_str().unwrap()); let db = &node.blockchain_db; let (block0, _) = create_genesis_block(db, &factories); @@ -654,10 +650,10 @@ fn local_get_target_difficulty() { #[test] fn local_submit_block() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let factories = CryptoFactories::default(); - let mut node = BaseNodeBuilder::new().start(&runtime, temp_dir.path().to_str().unwrap()); + let mut node = BaseNodeBuilder::new().start(&mut runtime, temp_dir.path().to_str().unwrap()); let db = &node.blockchain_db; let (block0, _) = create_genesis_block(db, &factories); diff --git a/base_layer/core/tests/node_state_machine.rs b/base_layer/core/tests/node_state_machine.rs index 8211e9754b..04ed6d8919 100644 --- a/base_layer/core/tests/node_state_machine.rs +++ b/base_layer/core/tests/node_state_machine.rs @@ -49,7 +49,7 @@ use tokio::runtime::Runtime; #[test] fn test_horizon_state_sync() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let factories = CryptoFactories::default(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let mct_config = MerkleChangeTrackerConfig { @@ -57,7 +57,7 @@ fn test_horizon_state_sync() { max_history_len: 3, }; let (alice_node, mut bob_node) = create_network_with_2_base_nodes_with_config( - &runtime, + &mut runtime, BaseNodeServiceConfig::default(), mct_config, MempoolServiceConfig::default(), @@ -133,7 +133,7 @@ fn test_horizon_state_sync() { #[test] fn test_block_sync() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let factories = CryptoFactories::default(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let mct_config = MerkleChangeTrackerConfig { @@ -141,7 +141,7 @@ fn test_block_sync() { max_history_len: 4, }; let (alice_node, bob_node) = create_network_with_2_base_nodes_with_config( - &runtime, + &mut runtime, BaseNodeServiceConfig::default(), mct_config, MempoolServiceConfig::default(), @@ -215,7 +215,7 @@ fn test_block_sync() { #[test] fn test_lagging_block_sync() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let factories = CryptoFactories::default(); let temp_dir = TempDir::new(string(8).as_str()).unwrap(); let mct_config = MerkleChangeTrackerConfig { @@ -223,7 +223,7 @@ fn test_lagging_block_sync() { max_history_len: 20, }; let (alice_node, bob_node) = create_network_with_2_base_nodes_with_config( - &runtime, + &mut runtime, BaseNodeServiceConfig::default(), mct_config, MempoolServiceConfig::default(), diff --git a/base_layer/p2p/Cargo.toml b/base_layer/p2p/Cargo.toml index 2a27c99bbe..013f69edc1 100644 --- a/base_layer/p2p/Cargo.toml +++ b/base_layer/p2p/Cargo.toml @@ -26,14 +26,14 @@ tari_utilities = { version = "^0.0", path = "../../infrastructure/tari_util"} bytes = "0.4.12" chrono = { version = "0.4.6", features = ["serde"]} derive-error = "0.0.4" -futures = { version = "=0.3.0-alpha.19", package = "futures-preview"} +futures = { version = "^0.3.1"} lmdb-zero = "0.4.4" log = "0.4.6" prost = "0.5.0" rand = "0.6.5" serde = "1.0.90" serde_derive = "1.0.90" -tokio = "0.2.0-alpha.6" +tokio = "0.2.9" tower = "0.3.0-alpha.2" tower-service = { version="0.3.0-alpha.2" } diff --git a/base_layer/p2p/examples/pingpong.rs b/base_layer/p2p/examples/pingpong.rs index e15bb69b8e..62173d3030 100644 --- a/base_layer/p2p/examples/pingpong.rs +++ b/base_layer/p2p/examples/pingpong.rs @@ -199,12 +199,12 @@ fn main() { outbound_buffer_size: 10, dht: Default::default(), }; - let rt = Runtime::new().expect("Failed to create tokio Runtime"); + let mut rt = Runtime::new().expect("Failed to create tokio Runtime"); - let (publisher, subscription_factory) = pubsub_connector(rt.executor(), 100); + let (publisher, subscription_factory) = pubsub_connector(rt.handle().clone(), 100); let subscription_factory = Arc::new(subscription_factory); - let (comms, dht) = initialize_comms(rt.executor(), comms_config, publisher).unwrap(); + let (comms, dht) = initialize_comms(rt.handle().clone(), comms_config, publisher).unwrap(); let peer = Peer::new( peer_identity.public_key().clone(), @@ -215,7 +215,7 @@ fn main() { ); comms.peer_manager().add_peer(peer).unwrap(); - let fut = StackBuilder::new(rt.executor(), comms.shutdown_signal()) + let fut = StackBuilder::new(rt.handle().clone(), comms.shutdown_signal()) .add_initializer(CommsOutboundServiceInitializer::new(dht.outbound_requester())) .add_initializer(LivenessInitializer::new( LivenessConfig { @@ -264,7 +264,6 @@ fn main() { shutdown.trigger().unwrap(); comms.shutdown().unwrap(); - rt.shutdown_on_idle(); } fn setup_ui() -> Cursive { diff --git a/base_layer/p2p/src/comms_connector/inbound_connector.rs b/base_layer/p2p/src/comms_connector/inbound_connector.rs index c42c3b04ad..fd81c66dbb 100644 --- a/base_layer/p2p/src/comms_connector/inbound_connector.rs +++ b/base_layer/p2p/src/comms_connector/inbound_connector.rs @@ -21,9 +21,9 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use super::peer_message::PeerMessage; -use futures::{task::Context, Future, Poll, Sink, SinkExt}; +use futures::{task::Context, Future, Sink, SinkExt}; use log::*; -use std::{error::Error, pin::Pin, sync::Arc}; +use std::{error::Error, pin::Pin, sync::Arc, task::Poll}; use tari_comms_dht::{domain_message::MessageHeader, inbound::DecryptedDhtMessage}; use tari_comms_middleware::MiddlewareError; use tower::Service; diff --git a/base_layer/p2p/src/comms_connector/pubsub.rs b/base_layer/p2p/src/comms_connector/pubsub.rs index 7243b741d0..763289f380 100644 --- a/base_layer/p2p/src/comms_connector/pubsub.rs +++ b/base_layer/p2p/src/comms_connector/pubsub.rs @@ -26,7 +26,7 @@ use futures::{channel::mpsc, FutureExt, SinkExt, StreamExt}; use log::*; use std::sync::Arc; use tari_pubsub::{pubsub_channel, TopicPayload, TopicSubscriptionFactory}; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &'static str = "comms::middleware::pubsub"; @@ -35,7 +35,7 @@ pub type PubsubDomainConnector = InboundDomainConnector ( PubsubDomainConnector, diff --git a/base_layer/p2p/src/initialization.rs b/base_layer/p2p/src/initialization.rs index 8fc3fa9709..52d964ee29 100644 --- a/base_layer/p2p/src/initialization.rs +++ b/base_layer/p2p/src/initialization.rs @@ -38,7 +38,7 @@ use tari_comms_dht as comms_dht; use tari_comms_dht::{Dht, DhtConfig}; use tari_comms_middleware::{pipeline::ServicePipeline, sink::SinkMiddleware}; use tari_storage::{lmdb_store::LMDBBuilder, LMDBWrapper}; -use tokio::runtime::TaskExecutor; +use tokio::runtime; use tower::ServiceBuilder; #[derive(Debug, Error)] @@ -77,7 +77,7 @@ pub struct CommsConfig { /// Initialize Tari Comms configured for tests pub fn initialize_local_test_comms( - executor: TaskExecutor, + executor: runtime::Handle, node_identity: Arc, connector: InboundDomainConnector, data_path: &str, @@ -179,7 +179,7 @@ where /// /// inbound_connector - Service to call pub fn initialize_comms( - executor: TaskExecutor, + executor: runtime::Handle, config: CommsConfig, connector: InboundDomainConnector, ) -> Result<(CommsNode, Dht), CommsInitializationError> diff --git a/base_layer/p2p/src/services/comms_outbound.rs b/base_layer/p2p/src/services/comms_outbound.rs index 4e18d5dcc2..0abcf41a1d 100644 --- a/base_layer/p2p/src/services/comms_outbound.rs +++ b/base_layer/p2p/src/services/comms_outbound.rs @@ -24,7 +24,7 @@ use futures::future::{self, Future}; use tari_comms_dht::outbound::OutboundMessageRequester; use tari_service_framework::{handles::ServiceHandlesFuture, ServiceInitializationError, ServiceInitializer}; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; /// Convenience type alias for external services that want to use this services handle pub type CommsOutboundHandle = OutboundMessageRequester; @@ -43,7 +43,7 @@ impl CommsOutboundServiceInitializer { impl ServiceInitializer for CommsOutboundServiceInitializer { type Future = impl Future>; - fn initialize(&mut self, _: TaskExecutor, handles: ServiceHandlesFuture, _: ShutdownSignal) -> Self::Future { + fn initialize(&mut self, _: runtime::Handle, handles: ServiceHandlesFuture, _: ShutdownSignal) -> Self::Future { handles.register( self.oms .take() diff --git a/base_layer/p2p/src/services/liveness/mod.rs b/base_layer/p2p/src/services/liveness/mod.rs index ef6cb1bfa7..c821bee981 100644 --- a/base_layer/p2p/src/services/liveness/mod.rs +++ b/base_layer/p2p/src/services/liveness/mod.rs @@ -63,7 +63,7 @@ use tari_service_framework::{ ServiceInitializer, }; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; #[cfg(feature = "test-mocks")] pub mod mock; @@ -114,7 +114,7 @@ impl ServiceInitializer for LivenessInitializer { fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/p2p/src/services/liveness/service.rs b/base_layer/p2p/src/services/liveness/service.rs index 9ecb1e7824..9fce91ea99 100644 --- a/base_layer/p2p/src/services/liveness/service.rs +++ b/base_layer/p2p/src/services/liveness/service.rs @@ -34,9 +34,9 @@ use crate::{ services::liveness::{neighbours::Neighbours, LivenessEvent, PongEvent}, tari_message::TariMessageType, }; -use futures::{pin_mut, stream::StreamExt, task::Context, Poll, SinkExt, Stream}; +use futures::{pin_mut, stream::StreamExt, task::Context, SinkExt, Stream}; use log::*; -use std::{pin::Pin, time::Instant}; +use std::{pin::Pin, task::Poll, time::Instant}; use tari_broadcast_channel::Publisher; use tari_comms::{ peer_manager::{NodeId, Peer}, @@ -50,7 +50,7 @@ use tari_comms_dht::{ }; use tari_service_framework::RequestContext; use tari_shutdown::ShutdownSignal; -use tokio::timer::Interval; +use tokio::time; /// Service responsible for testing Liveness for Peers. /// @@ -107,7 +107,7 @@ where pin_mut!(request_stream); let mut ping_tick = match self.config.auto_ping_interval { - Some(interval) => EitherStream::Left(Interval::new(Instant::now() + interval, interval)), + Some(interval) => EitherStream::Left(time::interval_at((Instant::now() + interval).into(), interval)), None => EitherStream::Right(futures::stream::iter(Vec::new())), } .fuse(); @@ -398,7 +398,6 @@ mod test { use tari_service_framework::reply_channel; use tari_shutdown::Shutdown; use tari_test_utils::runtime; - use tokio::future::FutureExt; #[test] fn get_ping_pong_count() { @@ -562,63 +561,64 @@ mod test { }); } - #[tokio::test] - async fn handle_message_pong() { - let mut state = LivenessState::new(); - - let (outbound_tx, _) = mpsc::channel(10); - let oms_handle = OutboundMessageRequester::new(outbound_tx); - - let mut metadata = Metadata::new(); - metadata.insert(MetadataKey::ChainMetadata, b"dummy-data".to_vec()); - let msg = create_dummy_message(PingPongMessage::pong_with_metadata(123, metadata)); - - state.add_inflight_ping(&msg.source_peer.node_id); - // A stream which emits one message and then closes - let pingpong_stream = stream::iter(std::iter::once(msg)); - - let (dht_tx, _) = mpsc::channel(10); - let dht_requester = DhtRequester::new(dht_tx); - // Setup liveness service - let (publisher, subscriber) = broadcast_channel::bounded(100); - let mut shutdown = Shutdown::new(); - let service = LivenessService::new( - Default::default(), - stream::empty(), - pingpong_stream, - state, - dht_requester, - oms_handle, - publisher, - shutdown.to_signal(), - ); + #[test] + fn handle_message_pong() { + runtime::test_async(|rt| { + rt.spawn(async { + let mut state = LivenessState::new(); + + let (outbound_tx, _) = mpsc::channel(10); + let oms_handle = OutboundMessageRequester::new(outbound_tx); + + let mut metadata = Metadata::new(); + metadata.insert(MetadataKey::ChainMetadata, b"dummy-data".to_vec()); + let msg = create_dummy_message(PingPongMessage::pong_with_metadata(123, metadata)); + + state.add_inflight_ping(&msg.source_peer.node_id); + // A stream which emits one message and then closes + let pingpong_stream = stream::iter(std::iter::once(msg)); + + let (dht_tx, _) = mpsc::channel(10); + let dht_requester = DhtRequester::new(dht_tx); + // Setup liveness service + let (publisher, subscriber) = broadcast_channel::bounded(100); + let mut shutdown = Shutdown::new(); + let service = LivenessService::new( + Default::default(), + stream::empty(), + pingpong_stream, + state, + dht_requester, + oms_handle, + publisher, + shutdown.to_signal(), + ); - // Create a flag that gets flipped when the subscribed event is received - let received_event = Arc::new(AtomicBool::new(false)); - let rec_event_clone = received_event.clone(); - - // Listen for the pong event - futures::join!( - async move { - let event = subscriber - .fuse() - .select_next_some() - .timeout(Duration::from_secs(10)) - .await - .unwrap(); - match &*event { - LivenessEvent::ReceivedPong(event) => { - rec_event_clone.store(true, Ordering::SeqCst); - assert_eq!(event.metadata.get(&MetadataKey::ChainMetadata).unwrap(), b"dummy-data"); + // Create a flag that gets flipped when the subscribed event is received + let received_event = Arc::new(AtomicBool::new(false)); + let rec_event_clone = received_event.clone(); + + // Listen for the pong event + futures::join!( + async move { + let event = time::timeout(Duration::from_secs(10), subscriber.fuse().select_next_some()) + .await + .unwrap(); + match &*event { + LivenessEvent::ReceivedPong(event) => { + rec_event_clone.store(true, Ordering::SeqCst); + assert_eq!(event.metadata.get(&MetadataKey::ChainMetadata).unwrap(), b"dummy-data"); + }, + _ => panic!("Unexpected event"), + } + + shutdown.trigger().unwrap(); }, - _ => panic!("Unexpected event"), - } - - shutdown.trigger().unwrap(); - }, - service.run() - ); + service.run() + ); - assert_eq!(received_event.load(Ordering::SeqCst), true); + assert_eq!(received_event.load(Ordering::SeqCst), true); + }); + }); } } diff --git a/base_layer/p2p/tests/services/liveness.rs b/base_layer/p2p/tests/services/liveness.rs index 0ab2d6de17..c51029f8c0 100644 --- a/base_layer/p2p/tests/services/liveness.rs +++ b/base_layer/p2p/tests/services/liveness.rs @@ -40,23 +40,23 @@ use tempdir::TempDir; use tokio::runtime::Runtime; pub fn setup_liveness_service( - runtime: &Runtime, + runtime: &mut Runtime, node_identity: NodeIdentity, peers: Vec, data_path: &str, ) -> (LivenessHandle, CommsNode, Dht) { - let (publisher, subscription_factory) = pubsub_connector(runtime.executor(), 100); + let (publisher, subscription_factory) = pubsub_connector(runtime.handle().clone(), 100); let subscription_factory = Arc::new(subscription_factory); let (comms, dht) = setup_comms_services( - runtime.executor(), + runtime.handle().clone(), Arc::new(node_identity.clone()), peers, publisher, data_path, ); - let fut = StackBuilder::new(runtime.executor(), comms.shutdown_signal()) + let fut = StackBuilder::new(runtime.handle().clone(), comms.shutdown_signal()) .add_initializer(CommsOutboundServiceInitializer::new(dht.outbound_requester())) .add_initializer(LivenessInitializer::new( LivenessConfig { @@ -79,7 +79,7 @@ pub fn setup_liveness_service( #[test] fn end_to_end() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let mut rng = rand::rngs::OsRng::new().unwrap(); @@ -98,14 +98,14 @@ fn end_to_end() { let alice_temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut liveness1, comms_1, _dht_1) = setup_liveness_service( - &runtime, + &mut runtime, node_1_identity.clone(), vec![node_2_identity.clone()], alice_temp_dir.path().to_str().unwrap(), ); let bob_temp_dir = TempDir::new(string(8).as_str()).unwrap(); let (mut liveness2, comms_2, _dht_2) = setup_liveness_service( - &runtime, + &mut runtime, node_2_identity.clone(), vec![node_1_identity.clone()], bob_temp_dir.path().to_str().unwrap(), @@ -201,6 +201,4 @@ fn end_to_end() { comms_1.shutdown().unwrap(); comms_2.shutdown().unwrap(); - - runtime.shutdown_on_idle(); } diff --git a/base_layer/p2p/tests/support/comms_and_services.rs b/base_layer/p2p/tests/support/comms_and_services.rs index 8ed30c2494..2d606ef777 100644 --- a/base_layer/p2p/tests/support/comms_and_services.rs +++ b/base_layer/p2p/tests/support/comms_and_services.rs @@ -31,10 +31,10 @@ use tari_p2p::{ comms_connector::{InboundDomainConnector, PeerMessage}, initialization::initialize_local_test_comms, }; -use tokio::runtime::TaskExecutor; +use tokio::runtime; pub fn setup_comms_services( - executor: TaskExecutor, + executor: runtime::Handle, node_identity: Arc, peers: Vec, publisher: InboundDomainConnector, diff --git a/base_layer/service_framework/Cargo.toml b/base_layer/service_framework/Cargo.toml index 03678d64cc..239e68a798 100644 --- a/base_layer/service_framework/Cargo.toml +++ b/base_layer/service_framework/Cargo.toml @@ -12,9 +12,9 @@ edition = "2018" tari_shutdown = { version = "^0.0", path="../../infrastructure/shutdown" } derive-error = "0.0.4" -futures = { version = "=0.3.0-alpha.19", package = "futures-preview", features=["async-await"]} +futures = { version = "^0.3.1", features=["async-await"]} tower-service = { version="0.3.0-alpha.2" } -tokio = "0.2.0-alpha.6" +tokio = "0.2.9" log = "0.4.8" [dev-dependencies] diff --git a/base_layer/service_framework/src/handles/future.rs b/base_layer/service_framework/src/handles/future.rs index 197c708954..1eaa57bf2b 100644 --- a/base_layer/service_framework/src/handles/future.rs +++ b/base_layer/service_framework/src/handles/future.rs @@ -25,7 +25,6 @@ use crate::handles::LazyService; use futures::{ task::{AtomicWaker, Context}, Future, - Poll, }; use std::{ any::Any, @@ -35,6 +34,7 @@ use std::{ mpsc, Arc, }, + task::Poll, }; /// Create a Notifier, ServiceHandlesFuture pair. diff --git a/base_layer/service_framework/src/handles/lazy_service.rs b/base_layer/service_framework/src/handles/lazy_service.rs index e23fd37114..47ecd68124 100644 --- a/base_layer/service_framework/src/handles/lazy_service.rs +++ b/base_layer/service_framework/src/handles/lazy_service.rs @@ -20,7 +20,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use futures::{ready, task::Context, Future, FutureExt, Poll}; +use futures::{ready, task::Context, Future, FutureExt}; +use std::task::Poll; use tower_service::Service; /// LazyService state @@ -97,9 +98,12 @@ mod test { use crate::tower::service_fn; use futures::future::{self, poll_fn}; use futures_test::task::panic_context; - use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, + use std::{ + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + task::Poll, }; fn mock_fut(flag: Arc) -> impl Future { diff --git a/base_layer/service_framework/src/initializer.rs b/base_layer/service_framework/src/initializer.rs index 812e8918ff..0871bedc83 100644 --- a/base_layer/service_framework/src/initializer.rs +++ b/base_layer/service_framework/src/initializer.rs @@ -25,7 +25,7 @@ use derive_error::Error; use futures::{Future, FutureExt}; use std::pin::Pin; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; #[derive(Debug, Error)] pub enum ServiceInitializationError { @@ -44,7 +44,7 @@ pub trait ServiceInitializer { /// Async initialization code for a service fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future; @@ -64,22 +64,22 @@ pub trait ServiceInitializer { /// /// ```edition2018 /// # use tari_service_framework::handles::ServiceHandlesFuture; -/// # use tokio::runtime::TaskExecutor; -/// let my_initializer = |executor: TaskExecutor, handles_fut: ServiceHandlesFuture| { +/// # use tokio::runtime; +/// let my_initializer = |executor: runtime::Handle, handles_fut: ServiceHandlesFuture| { /// // initialization code /// futures::future::ready(Result::<_, ()>::Ok(())) /// }; /// ``` impl ServiceInitializer for TFunc where - TFunc: FnMut(TaskExecutor, ServiceHandlesFuture, ShutdownSignal) -> TFut, + TFunc: FnMut(runtime::Handle, ServiceHandlesFuture, ShutdownSignal) -> TFut, TFut: Future>, { type Future = TFut; fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future @@ -103,7 +103,7 @@ type ServiceInitializationFuture = Pin ServiceInitializationFuture; @@ -117,7 +117,7 @@ where { fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> ServiceInitializationFuture @@ -151,7 +151,7 @@ impl ServiceInitializer for BoxedServiceInitializer { fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/service_framework/src/reply_channel.rs b/base_layer/service_framework/src/reply_channel.rs index e6ff52ba48..66773748e3 100644 --- a/base_layer/service_framework/src/reply_channel.rs +++ b/base_layer/service_framework/src/reply_channel.rs @@ -31,11 +31,10 @@ use futures::{ task::Context, Future, FutureExt, - Poll, Stream, StreamExt, }; -use std::pin::Pin; +use std::{pin::Pin, task::Poll}; use tower_service::Service; /// Create a new Requester/Responder pair which wraps and calls the given service diff --git a/base_layer/service_framework/src/stack.rs b/base_layer/service_framework/src/stack.rs index 4f50592040..442b8eb542 100644 --- a/base_layer/service_framework/src/stack.rs +++ b/base_layer/service_framework/src/stack.rs @@ -27,19 +27,19 @@ use crate::{ use futures::future::join_all; use std::sync::Arc; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; /// Responsible for building and collecting handles and (usually long-running) service futures. /// `finish` is an async function which resolves once all the services are initialized, or returns /// an error if any one of the services fails to initialize. pub struct StackBuilder { initializers: Vec, - executor: TaskExecutor, + executor: runtime::Handle, shutdown_signal: ShutdownSignal, } impl StackBuilder { - pub fn new(executor: TaskExecutor, shutdown_signal: ShutdownSignal) -> Self { + pub fn new(executor: runtime::Handle, shutdown_signal: ShutdownSignal) -> Self { Self { initializers: Vec::new(), executor, @@ -111,7 +111,7 @@ mod test { fn service_defn_simple() { let rt = Runtime::new().unwrap(); // This is less of a test and more of a demo of using the short-hand implementation of ServiceInitializer - let simple_initializer = |executor: TaskExecutor, _: ServiceHandlesFuture, _: ShutdownSignal| { + let simple_initializer = |executor: runtime::Handle, _: ServiceHandlesFuture, _: ShutdownSignal| { executor.spawn(future::ready(())); future::ok(()) }; @@ -119,7 +119,7 @@ mod test { let shutdown = Shutdown::new(); let handles = block_on( - StackBuilder::new(rt.executor(), shutdown.to_signal()) + StackBuilder::new(rt.handle().clone(), shutdown.to_signal()) .add_initializer(simple_initializer) .finish(), ); @@ -144,12 +144,12 @@ mod test { fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, _shutdown: ShutdownSignal, ) -> Self::Future { - // Spawn some task on the given TaskExecutor + // Spawn some task on the given runtime::Handle executor.spawn(future::ready(())); // Add a handle handles_fut.register(DummyServiceHandle(123)); @@ -184,7 +184,7 @@ mod test { let initializer = DummyInitializer::new(Arc::clone(&shared_state)); let handles = block_on( - StackBuilder::new(rt.executor(), shutdown.to_signal()) + StackBuilder::new(rt.handle().clone(), shutdown.to_signal()) .add_initializer(initializer) .finish(), ) diff --git a/base_layer/service_framework/src/tower/service_ext.rs b/base_layer/service_framework/src/tower/service_ext.rs index 8f9baa45b1..a901558c9d 100644 --- a/base_layer/service_framework/src/tower/service_ext.rs +++ b/base_layer/service_framework/src/tower/service_ext.rs @@ -20,8 +20,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use futures::{ready, task::Context, Future, FutureExt, Poll}; -use std::pin::Pin; +use futures::{ready, task::Context, Future, FutureExt}; +use std::{pin::Pin, task::Poll}; use tower_service::Service; impl ServiceExt for T where T: Service {} diff --git a/base_layer/service_framework/src/tower/service_fn.rs b/base_layer/service_framework/src/tower/service_fn.rs index e651e14588..ce945d7285 100644 --- a/base_layer/service_framework/src/tower/service_fn.rs +++ b/base_layer/service_framework/src/tower/service_fn.rs @@ -21,7 +21,8 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // TODO: Remove this when https://github.com/tower-rs/tower/pull/318 is resolved and published -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; +use std::task::Poll; use tower_service::Service; /// Returns a new `ServiceFn` with the given closure. diff --git a/base_layer/wallet/Cargo.toml b/base_layer/wallet/Cargo.toml index 5213e1cf6c..8ef1937dd6 100644 --- a/base_layer/wallet/Cargo.toml +++ b/base_layer/wallet/Cargo.toml @@ -31,10 +31,9 @@ lmdb-zero = "0.4.4" diesel_migrations = "1.4" diesel = {version="1.4", features = ["sqlite", "serde_json", "chrono", "r2d2"]} rand = "0.5.5" -futures = { version = "=0.3.0-alpha.19", package = "futures-preview", features =["compat", "std"]} -tokio = "0.2.0-alpha.4" +futures = { version = "^0.3.1", features =["compat", "std"]} +tokio = "0.2.9" tower = "0.3.0-alpha.2" -tokio-executor = { version ="^0.2.0-alpha.6", features = ["threadpool"] } tempdir = "0.3.7" [dev-dependencies] diff --git a/base_layer/wallet/src/contacts_service/mod.rs b/base_layer/wallet/src/contacts_service/mod.rs index bdb6e0fe85..0087270d34 100644 --- a/base_layer/wallet/src/contacts_service/mod.rs +++ b/base_layer/wallet/src/contacts_service/mod.rs @@ -34,7 +34,7 @@ use tari_service_framework::{ ServiceInitializer, }; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; pub mod error; pub mod handle; @@ -64,7 +64,7 @@ where T: ContactsBackend + 'static fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/wallet/src/output_manager_service/mod.rs b/base_layer/wallet/src/output_manager_service/mod.rs index 545b02bc8c..7e230a103a 100644 --- a/base_layer/wallet/src/output_manager_service/mod.rs +++ b/base_layer/wallet/src/output_manager_service/mod.rs @@ -33,7 +33,7 @@ use tari_service_framework::{ }; use tari_shutdown::ShutdownSignal; use tari_transactions::types::CryptoFactories; -use tokio::runtime::TaskExecutor; +use tokio::runtime; pub mod error; pub mod handle; @@ -69,7 +69,7 @@ where T: OutputManagerBackend + 'static fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/wallet/src/text_message_service/mod.rs b/base_layer/wallet/src/text_message_service/mod.rs index b4018a0b64..d92907b208 100644 --- a/base_layer/wallet/src/text_message_service/mod.rs +++ b/base_layer/wallet/src/text_message_service/mod.rs @@ -49,7 +49,7 @@ use tari_service_framework::{ ServiceInitializationError, ServiceInitializer, }; -use tokio::runtime::TaskExecutor; +use tokio::runtime::runtime::Handle; const LOG_TARGET: &'static str = "wallet::text_message_service::initializer"; @@ -92,7 +92,7 @@ impl TextMessageServiceInitializer { impl ServiceInitializer for TextMessageServiceInitializer { type Future = impl Future>; - fn initialize(&mut self, executor: TaskExecutor, handles_fut: ServiceHandlesFuture) -> Self::Future { + fn initialize(&mut self, executor: runtime::Handle, handles_fut: ServiceHandlesFuture) -> Self::Future { let pub_key = self .pub_key .take() diff --git a/base_layer/wallet/src/transaction_service/mod.rs b/base_layer/wallet/src/transaction_service/mod.rs index ed0409ae5a..263225ce87 100644 --- a/base_layer/wallet/src/transaction_service/mod.rs +++ b/base_layer/wallet/src/transaction_service/mod.rs @@ -55,7 +55,7 @@ use tari_service_framework::{ }; use tari_shutdown::ShutdownSignal; use tari_transactions::{transaction_protocol::proto, types::CryptoFactories}; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &'static str = "base_layer::wallet::transaction_service"; @@ -116,7 +116,7 @@ where T: TransactionBackend + Clone + 'static fn initialize( &mut self, - executor: TaskExecutor, + executor: runtime::Handle, handles_fut: ServiceHandlesFuture, shutdown: ShutdownSignal, ) -> Self::Future diff --git a/base_layer/wallet/src/wallet.rs b/base_layer/wallet/src/wallet.rs index 20066508df..2c9372afaa 100644 --- a/base_layer/wallet/src/wallet.rs +++ b/base_layer/wallet/src/wallet.rs @@ -108,7 +108,7 @@ where { pub fn new( config: WalletConfig, - runtime: Runtime, + mut runtime: Runtime, wallet_backend: T, transaction_backend: U, output_manager_backend: V, @@ -135,12 +135,12 @@ where let factories = config.factories; let (publisher, subscription_factory) = - pubsub_connector(runtime.executor(), config.comms_config.inbound_buffer_size); + pubsub_connector(runtime.handle().clone(), config.comms_config.inbound_buffer_size); let subscription_factory = Arc::new(subscription_factory); - let (comms, dht) = initialize_comms(runtime.executor(), config.comms_config.clone(), publisher)?; + let (comms, dht) = initialize_comms(runtime.handle().clone(), config.comms_config.clone(), publisher)?; - let fut = StackBuilder::new(runtime.executor(), comms.shutdown_signal()) + let fut = StackBuilder::new(runtime.handle().clone(), comms.shutdown_signal()) .add_initializer(CommsOutboundServiceInitializer::new(dht.outbound_requester())) .add_initializer(LivenessInitializer::new( Default::default(), @@ -222,7 +222,7 @@ where /// exiting. pub fn shutdown(self) -> Result<(), WalletError> { self.comms.shutdown()?; - self.runtime.shutdown_on_idle(); + drop(self.runtime); Ok(()) } diff --git a/base_layer/wallet/tests/contacts_service/mod.rs b/base_layer/wallet/tests/contacts_service/mod.rs index 82ef1d5892..d28f1b1755 100644 --- a/base_layer/wallet/tests/contacts_service/mod.rs +++ b/base_layer/wallet/tests/contacts_service/mod.rs @@ -39,12 +39,12 @@ use tempdir::TempDir; use tokio::runtime::Runtime; pub fn setup_contacts_service( - runtime: &Runtime, + runtime: &mut Runtime, backend: T, ) -> (ContactsServiceHandle, Shutdown) { let shutdown = Shutdown::new(); - let fut = StackBuilder::new(runtime.executor(), shutdown.to_signal()) + let fut = StackBuilder::new(runtime.handle().clone(), shutdown.to_signal()) .add_initializer(ContactsServiceInitializer::new(backend)) .finish(); @@ -108,8 +108,8 @@ pub fn test_memory_database_crud() { pub fn test_contacts_service(backend: T) { let mut rng = rand::OsRng::new().unwrap(); - let runtime = Runtime::new().unwrap(); - let (mut contacts_service, _shutdown) = setup_contacts_service(&runtime, backend); + let mut runtime = Runtime::new().unwrap(); + let (mut contacts_service, _shutdown) = setup_contacts_service(&mut runtime, backend); let mut contacts = Vec::new(); for i in 0..5 { diff --git a/base_layer/wallet/tests/output_manager_service/service.rs b/base_layer/wallet/tests/output_manager_service/service.rs index 85903a1d39..e3d0010710 100644 --- a/base_layer/wallet/tests/output_manager_service/service.rs +++ b/base_layer/wallet/tests/output_manager_service/service.rs @@ -48,13 +48,13 @@ use tempdir::TempDir; use tokio::runtime::Runtime; pub fn setup_output_manager_service( - runtime: &Runtime, + runtime: &mut Runtime, backend: T, ) -> (OutputManagerHandle, Shutdown) { let shutdown = Shutdown::new(); let factories = CryptoFactories::default(); - let fut = StackBuilder::new(runtime.executor(), shutdown.to_signal()) + let fut = StackBuilder::new(runtime.handle().clone(), shutdown.to_signal()) .add_initializer(OutputManagerServiceInitializer::new(backend, factories)) .finish(); @@ -69,9 +69,9 @@ fn sending_transaction_and_confirmation(backend: T) { let mut rng = rand::OsRng::new().unwrap(); let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let num_outputs = 20; for _i in 0..num_outputs { let (_ti, uo) = make_input( @@ -208,9 +208,9 @@ fn send_no_change(backend: T) { let mut rng = rand::OsRng::new().unwrap(); let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let fee_per_gram = MicroTari::from(20); let fee_without_change = Fee::calculate(fee_per_gram, 2, 1); @@ -282,9 +282,9 @@ fn send_no_change_sqlite_db() { fn send_not_enough_for_change(backend: T) { let mut rng = rand::OsRng::new().unwrap(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let fee_per_gram = MicroTari::from(20); let fee_without_change = Fee::calculate(fee_per_gram, 2, 1); @@ -327,9 +327,9 @@ fn send_not_enough_for_change_sqlite_db() { fn receiving_and_confirmation(backend: T) { let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let value = MicroTari::from(5000); let recv_key = runtime.block_on(oms.get_recipient_spending_key(1, value)).unwrap(); @@ -368,9 +368,9 @@ fn cancel_transaction(backend: T) { let mut rng = rand::OsRng::new().unwrap(); let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let num_outputs = 20; for _i in 0..num_outputs { @@ -417,8 +417,8 @@ fn timeout_transaction(backend: T) { let mut rng = rand::OsRng::new().unwrap(); let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let mut runtime = Runtime::new().unwrap(); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let num_outputs = 20; for _i in 0..num_outputs { @@ -470,9 +470,9 @@ fn timeout_transaction_sqlite_db() { fn test_get_balance(backend: T) { let factories = CryptoFactories::default(); let rng = rand::OsRng::new().unwrap(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let balance = runtime.block_on(oms.get_balance()).unwrap(); @@ -522,9 +522,9 @@ fn test_get_balance_sqlite_db() { fn test_confirming_received_output(backend: T) { let factories = CryptoFactories::default(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); - let (mut oms, _shutdown) = setup_output_manager_service(&runtime, backend); + let (mut oms, _shutdown) = setup_output_manager_service(&mut runtime, backend); let value = MicroTari::from(5000); let recv_key = runtime.block_on(oms.get_recipient_spending_key(1, value)).unwrap(); diff --git a/base_layer/wallet/tests/support/comms_and_services.rs b/base_layer/wallet/tests/support/comms_and_services.rs index a755cabd29..dee3f224e6 100644 --- a/base_layer/wallet/tests/support/comms_and_services.rs +++ b/base_layer/wallet/tests/support/comms_and_services.rs @@ -34,10 +34,10 @@ use tari_p2p::{ domain_message::DomainMessage, initialization::initialize_local_test_comms, }; -use tokio::runtime::TaskExecutor; +use tokio::runtime; pub fn setup_comms_services( - executor: TaskExecutor, + executor: runtime::Handle, node_identity: Arc, peers: Vec, publisher: InboundDomainConnector, diff --git a/base_layer/wallet/tests/transaction_service/callback_handler.rs b/base_layer/wallet/tests/transaction_service/callback_handler.rs index 09bf17ac0c..d34b318fe7 100644 --- a/base_layer/wallet/tests/transaction_service/callback_handler.rs +++ b/base_layer/wallet/tests/transaction_service/callback_handler.rs @@ -120,7 +120,7 @@ unsafe extern "C" fn discovery_send_callback(_tx_id: u64, _result: bool) { #[test] fn test_callback_handler() { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -155,7 +155,7 @@ fn test_callback_handler() { let db_folder = db_tempdir.path().to_str().unwrap().to_string(); let alice_db = TransactionMemoryDatabase::new(); let (mut alice_ts, mut alice_oms, _alice_comms) = setup_transaction_service( - &runtime, + &mut runtime, alice_node_identity.clone(), vec![bob_node_identity.clone()], factories.clone(), @@ -179,7 +179,7 @@ fn test_callback_handler() { runtime.spawn(callback_handler.start()); let (mut bob_ts, mut bob_oms, _bob_comms) = setup_transaction_service( - &runtime, + &mut runtime, bob_node_identity.clone(), vec![alice_node_identity.clone(), carol_node_identity.clone()], factories.clone(), @@ -189,7 +189,7 @@ fn test_callback_handler() { ); let (_carol_ts, _carol_oms, _carol_comms) = setup_transaction_service( - &runtime, + &mut runtime, carol_node_identity.clone(), vec![bob_node_identity.clone()], factories.clone(), diff --git a/base_layer/wallet/tests/transaction_service/service.rs b/base_layer/wallet/tests/transaction_service/service.rs index 9d359b8c2e..62cf9e2b01 100644 --- a/base_layer/wallet/tests/transaction_service/service.rs +++ b/base_layer/wallet/tests/transaction_service/service.rs @@ -82,8 +82,17 @@ use tari_wallet::{ use tempdir::TempDir; use tokio::runtime::{Builder, Runtime}; +fn create_runtime() -> Runtime { + Builder::new() + .threaded_scheduler() + .enable_all() + .core_threads(8) + .build() + .unwrap() +} + pub fn setup_transaction_service( - runtime: &Runtime, + runtime: &mut Runtime, node_identity: NodeIdentity, peers: Vec, factories: CryptoFactories, @@ -92,10 +101,10 @@ pub fn setup_transaction_service( discovery_request_timeout: Duration, ) -> (TransactionServiceHandle, OutputManagerHandle, CommsNode) { - let (publisher, subscription_factory) = pubsub_connector(runtime.executor(), 100); + let (publisher, subscription_factory) = pubsub_connector(runtime.handle().clone(), 100); let subscription_factory = Arc::new(subscription_factory); let (comms, dht) = setup_comms_services( - runtime.executor(), + runtime.handle().clone(), Arc::new(node_identity.clone()), peers, publisher, @@ -103,7 +112,7 @@ pub fn setup_transaction_service( discovery_request_timeout, ); - let fut = StackBuilder::new(runtime.executor(), comms.shutdown_signal()) + let fut = StackBuilder::new(runtime.handle().clone(), comms.shutdown_signal()) .add_initializer(CommsOutboundServiceInitializer::new(dht.outbound_requester())) .add_initializer(OutputManagerServiceInitializer::new( OutputManagerMemoryDatabase::new(), @@ -198,7 +207,7 @@ fn manage_single_transaction( database_path: String, ) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -221,7 +230,7 @@ fn manage_single_transaction( .unwrap(); let (mut alice_ts, mut alice_oms, alice_comms) = setup_transaction_service( - &runtime, + &mut runtime, alice_node_identity.clone(), vec![bob_node_identity.clone()], factories.clone(), @@ -259,7 +268,7 @@ fn manage_single_transaction( assert_eq!(alice_completed_tx.len(), 0); let (mut bob_ts, mut bob_oms, bob_comms) = setup_transaction_service( - &runtime, + &mut runtime, bob_node_identity.clone(), vec![alice_node_identity.clone()], factories.clone(), @@ -353,7 +362,7 @@ fn manage_multiple_transactions( database_path: String, ) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); // Alice's parameters @@ -384,7 +393,7 @@ fn manage_multiple_transactions( .unwrap(); let (mut alice_ts, mut alice_oms, alice_comms) = setup_transaction_service( - &runtime, + &mut runtime, alice_node_identity.clone(), vec![bob_node_identity.clone(), carol_node_identity.clone()], factories.clone(), @@ -430,7 +439,7 @@ fn manage_multiple_transactions( // Spin up Bob and Carol let (mut bob_ts, mut bob_oms, bob_comms) = setup_transaction_service( - &runtime, + &mut runtime, bob_node_identity.clone(), vec![alice_node_identity.clone()], factories.clone(), @@ -439,7 +448,7 @@ fn manage_multiple_transactions( Duration::from_secs(1), ); let (mut carol_ts, mut carol_oms, carol_comms) = setup_transaction_service( - &runtime, + &mut runtime, carol_node_identity.clone(), vec![alice_node_identity.clone()], factories.clone(), @@ -543,7 +552,7 @@ fn manage_multiple_transactions_sqlite_db() { } fn test_sending_repeated_tx_ids(alice_backend: T, bob_backend: T) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -632,7 +641,7 @@ fn test_sending_repeated_tx_ids_sqlite_db() { } fn test_accepting_unknown_tx_id_and_malformed_reply(alice_backend: T) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -726,7 +735,7 @@ fn test_accepting_unknown_tx_id_and_malformed_reply_sqlite_db() { } fn finalize_tx_with_nonexistent_txid(alice_backend: T) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -784,7 +793,7 @@ fn finalize_tx_with_nonexistent_txid_sqlite_db() { } fn finalize_tx_with_incorrect_pubkey(alice_backend: T, bob_backend: T) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -892,7 +901,7 @@ fn finalize_tx_with_incorrect_pubkey_sqlite_db() { } fn finalize_tx_with_missing_output(alice_backend: T, bob_backend: T) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -1003,7 +1012,7 @@ fn discovery_async_return_test() { let db_tempdir = TempDir::new(random_string(8).as_str()).unwrap(); let db_folder = db_tempdir.path().to_str().unwrap().to_string(); - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let mut rng = OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -1049,7 +1058,7 @@ fn discovery_async_return_test() { .unwrap(); let (mut alice_ts, mut alice_oms, _alice_comms) = setup_transaction_service( - &runtime, + &mut runtime, alice_node_identity.clone(), vec![bob_node_identity.clone()], factories.clone(), @@ -1060,7 +1069,7 @@ fn discovery_async_return_test() { let alice_event_stream = alice_ts.get_event_stream_fused(); let (_bob_ts, _bob_oms, _bob_comms) = setup_transaction_service( - &runtime, + &mut runtime, bob_node_identity.clone(), vec![ alice_node_identity.clone(), @@ -1117,7 +1126,7 @@ fn discovery_async_return_test() { assert_eq!(initial_balance, runtime.block_on(alice_oms.get_balance()).unwrap()); let (_dave_ts, _dave_oms, _dave_comms) = setup_transaction_service( - &runtime, + &mut runtime, dave_node_identity.clone(), vec![bob_node_identity.clone()], factories.clone(), @@ -1158,7 +1167,7 @@ fn discovery_async_return_test() { } fn test_coinbase(backend: T) { - let runtime = Builder::new().core_threads(8).build().unwrap(); + let mut runtime = create_runtime(); let factories = CryptoFactories::default(); let (mut alice_ts, mut alice_output_manager, _alice_outbound_service, _alice_tx_sender, _alice_tx_ack_sender, _) = diff --git a/base_layer/wallet/tests/wallet/mod.rs b/base_layer/wallet/tests/wallet/mod.rs index 341df5f030..832a811779 100644 --- a/base_layer/wallet/tests/wallet/mod.rs +++ b/base_layer/wallet/tests/wallet/mod.rs @@ -68,7 +68,7 @@ fn create_peer(public_key: CommsPublicKey, net_address: Multiaddr) -> Peer { #[test] fn test_wallet() { with_temp_dir(|dir_path| { - let runtime = Runtime::new().unwrap(); + let mut runtime = Runtime::new().unwrap(); let mut rng = rand::OsRng::new().unwrap(); let factories = CryptoFactories::default(); @@ -217,8 +217,6 @@ fn test_wallet() { let got_contacts = runtime.block_on(alice_wallet.contacts_service.get_contacts()).unwrap(); assert_eq!(contacts, got_contacts); - - runtime.shutdown_on_idle(); }); } diff --git a/base_layer/wallet_ffi/Cargo.toml b/base_layer/wallet_ffi/Cargo.toml index 8723c6d2c6..0cc75ef1d5 100644 --- a/base_layer/wallet_ffi/Cargo.toml +++ b/base_layer/wallet_ffi/Cargo.toml @@ -12,8 +12,8 @@ tari_transactions = { path = "../transactions", version="^0.0"} tari_utilities = { path = "../../infrastructure/tari_util", version = "^0.0"} tari_wallet = { path = "../wallet", version = "^0.0", features = ["test_harness", "c_integration"]} -futures = { version = "=0.3.0-alpha.19", package = "futures-preview", features =["compat", "std"]} -tokio = "0.2.0-alpha.4" +futures = { version = "^0.3.1", features =["compat", "std"]} +tokio = "0.2.9" libc = "0.2.65" rand = "0.5.5" chrono = { version = "0.4.6", features = ["serde"]} diff --git a/comms/Cargo.toml b/comms/Cargo.toml index 88c584979d..eea0615940 100644 --- a/comms/Cargo.toml +++ b/comms/Cargo.toml @@ -17,13 +17,13 @@ tari_storage = { version="^0.0", path = "../infrastructure/storage" } tari_utilities = { version="^0.0", path = "../infrastructure/tari_util" } tari_shutdown = { version="^0.0", path = "../infrastructure/shutdown" } -bitflags ="1.0.4" +bitflags = "1.0.4" bytes = "0.4.12" chrono = { version = "0.4.6", features = ["serde"] } clear_on_drop = "0.2.3" derive-error = "0.0.4" digest = "0.8.0" -futures = { version = "=0.3.0-alpha.19", package = "futures-preview", features = ["async-await"]} +futures = { version = "^0.3", features = ["async-await"]} lazy_static = "1.3.0" lmdb-zero = "0.4.4" log = { version = "0.4.0", features = ["std"] } @@ -35,10 +35,9 @@ serde_derive = "1.0.90" serde_repr = "0.1.5" snow = {git="https://github.com/tari-project/snow.git", branch="sb-make-builder-send", features=["default-resolver"], optional = true} time = "0.1.42" -tokio = "0.2.0-alpha.6" -tokio-executor = { version ="^0.2.0-alpha.6", features = ["threadpool"] } +tokio = {version="^0.2", features=["blocking", "tcp", "stream", "dns"]} ttl_cache = "0.5.1" -yamux = {path="./yamux", optional = true} +yamux = {version="0.4.0", optional = true} zmq = "0.9.2" [dev-dependencies] @@ -51,6 +50,7 @@ rand = "0.5.5" serde_json = "1.0.39" tari_common = { path = "../common", version = "^0.0" } tokio-mock-task = "0.1.1" +tokio-macros = "0.2.3" [build-dependencies] tari_protobuf_build = { version = "^0.0", path="../infrastructure/protobuf_build"} diff --git a/comms/dht/Cargo.toml b/comms/dht/Cargo.toml index 7b04c55225..8d97460fda 100644 --- a/comms/dht/Cargo.toml +++ b/comms/dht/Cargo.toml @@ -24,19 +24,18 @@ bytes = "0.4.12" chrono = "0.4.9" derive-error = "0.0.4" digest = "0.8.1" -futures= {version= "0.3.0-alpha.19", package="futures-preview"} +futures= {version= "^0.3.1"} log = "0.4.8" prost = "0.5.0" +prost-types = "0.5.0" rand = "0.5.5" serde = "1.0.90" serde_derive = "1.0.90" serde_repr = "0.1.5" -tokio = "0.2.0-alpha.6" -tokio-executor = "0.2.0-alpha.6" -tower-filter= {path="../middleware/tower-filter"}#version="=0.3.0-alpha.2", path="../" -tower= "0.3.0-alpha.2" +tokio = "0.2.9" +tower= "0.3.0" +tower-filter = {version="0.3.0-alpha.2", path="../middleware/tower-filter"} ttl_cache = "0.5.1" -prost-types = "0.5.0" [dev-dependencies] tari_test_utils = { version = "^0.0", path = "../../infrastructure/test_utils"} diff --git a/comms/dht/src/actor.rs b/comms/dht/src/actor.rs index 0bbd1e5e0f..882a56f91e 100644 --- a/comms/dht/src/actor.rs +++ b/comms/dht/src/actor.rs @@ -32,6 +32,7 @@ use crate::{ discovery::DhtDiscoveryError, outbound::{OutboundMessageRequester, SendMessageParams}, proto::{dht::JoinMessage, envelope::DhtMessageType, store_forward::StoredMessagesRequest}, + utils::hoist_nested_result, DhtConfig, }; use chrono::{DateTime, Utc}; @@ -62,7 +63,7 @@ use tari_comms::{ }; use tari_shutdown::ShutdownSignal; use tari_utilities::ByteArray; -use tokio_executor::blocking; +use tokio::task; use ttl_cache::TtlCache; const LOG_TARGET: &'static str = "comms::dht::actor"; @@ -79,6 +80,7 @@ pub enum DhtActorError { #[error(msg_embedded, no_from, non_std)] SendFailed(String), DiscoveryError(DhtDiscoveryError), + BlockingJoinError(tokio::task::JoinError), } impl From for DhtActorError { @@ -243,15 +245,18 @@ impl<'a> DhtActor<'a> { let peer_manager = Arc::clone(&self.peer_manager); let node_identity = Arc::clone(&self.node_identity); let config = self.config.clone(); - Box::pin(blocking::run(move || { - match Self::select_peers(config, node_identity, peer_manager, broadcast_strategy) { - Ok(peers) => reply_tx.send(peers).map_err(|_| DhtActorError::ReplyCanceled), - Err(err) => { - error!(target: LOG_TARGET, "Peer selection failed: {}", err); - reply_tx.send(Vec::new()).map_err(|_| DhtActorError::ReplyCanceled) - }, - } - })) + Box::pin( + task::spawn_blocking(move || { + match Self::select_peers(config, node_identity, peer_manager, broadcast_strategy) { + Ok(peers) => reply_tx.send(peers).map_err(|_| DhtActorError::ReplyCanceled), + Err(err) => { + error!(target: LOG_TARGET, "Peer selection failed: {}", err); + reply_tx.send(Vec::new()).map_err(|_| DhtActorError::ReplyCanceled) + }, + } + }) + .map(hoist_nested_result), + ) }, SendRequestStoredMessages(maybe_since) => { let node_identity = Arc::clone(&self.node_identity); diff --git a/comms/dht/src/builder.rs b/comms/dht/src/builder.rs index b64303ff8b..30093cfc44 100644 --- a/comms/dht/src/builder.rs +++ b/comms/dht/src/builder.rs @@ -27,13 +27,13 @@ use tari_comms::{ peer_manager::{NodeIdentity, PeerManager}, }; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; pub struct DhtBuilder { node_identity: Arc, peer_manager: Arc, config: DhtConfig, - executor: TaskExecutor, + executor: runtime::Handle, shutdown_signal: ShutdownSignal, } @@ -50,7 +50,7 @@ impl DhtBuilder { pub fn new( node_identity: Arc, peer_manager: Arc, - executor: TaskExecutor, + executor: runtime::Handle, shutdown_signal: ShutdownSignal, ) -> Self { diff --git a/comms/dht/src/dht.rs b/comms/dht/src/dht.rs index 125a4fb6b4..2f9e28d0eb 100644 --- a/comms/dht/src/dht.rs +++ b/comms/dht/src/dht.rs @@ -42,7 +42,7 @@ use tari_comms::{ }; use tari_comms_middleware::MiddlewareError; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; use tower::{layer::Layer, Service, ServiceBuilder}; use tower_filter::error::Error as FilterError; @@ -68,7 +68,7 @@ pub struct Dht { impl Dht { pub fn new( config: DhtConfig, - executor: TaskExecutor, + executor: runtime::Handle, node_identity: Arc, peer_manager: Arc, shutdown_signal: ShutdownSignal, @@ -285,20 +285,20 @@ mod test { }; use tari_comms_middleware::sink::SinkMiddleware; use tari_shutdown::Shutdown; - use tokio::{future::FutureExt, runtime::Runtime}; + use tokio::{runtime::Runtime, time}; use tower::{layer::Layer, Service}; #[test] fn stack_unencrypted() { let node_identity = make_node_identity(); let peer_manager = make_peer_manager(); - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let shutdown = Shutdown::new(); let dht = DhtBuilder::new( Arc::clone(&node_identity), peer_manager, - rt.executor(), + rt.handle().clone(), shutdown.to_signal(), ) .finish(); @@ -321,7 +321,10 @@ mod test { let msg = rt.block_on(async move { service.call(inbound_message).await.unwrap(); - let msg = out_rx.next().timeout(Duration::from_secs(10)).await.unwrap().unwrap(); + let msg = time::timeout(Duration::from_secs(10), out_rx.next()) + .await + .unwrap() + .unwrap(); msg.success().unwrap().decode_part::>(0).unwrap().unwrap() }); @@ -333,12 +336,12 @@ mod test { let node_identity = make_node_identity(); let peer_manager = make_peer_manager(); - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let shutdown = Shutdown::new(); let dht = DhtBuilder::new( Arc::clone(&node_identity), peer_manager, - rt.executor(), + rt.handle().clone(), shutdown.to_signal(), ) .finish(); @@ -360,7 +363,10 @@ mod test { let msg = rt.block_on(async move { service.call(inbound_message).await.unwrap(); - let msg = out_rx.next().timeout(Duration::from_secs(10)).await.unwrap().unwrap(); + let msg = time::timeout(Duration::from_secs(10), out_rx.next()) + .await + .unwrap() + .unwrap(); msg.success().unwrap().decode_part::>(0).unwrap().unwrap() }); @@ -372,18 +378,16 @@ mod test { let node_identity = make_node_identity(); let peer_manager = make_peer_manager(); - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let shutdown = Shutdown::new(); let mut dht = DhtBuilder::new( Arc::clone(&node_identity), peer_manager, - rt.executor(), + rt.handle().clone(), shutdown.to_signal(), ) .finish(); - let rt = Runtime::new().unwrap(); - let (next_service_tx, mut next_service_rx) = mpsc::channel(10); let (oms_requester, oms_mock) = create_outbound_service_mock(1); // Send all outbound requests to the mock @@ -427,12 +431,12 @@ mod test { let node_identity = make_client_identity(); let peer_manager = make_peer_manager(); - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let shutdown = Shutdown::new(); let dht = DhtBuilder::new( Arc::clone(&node_identity), peer_manager, - rt.executor(), + rt.handle().clone(), shutdown.to_signal(), ) .finish(); diff --git a/comms/dht/src/discovery/requester.rs b/comms/dht/src/discovery/requester.rs index 40bcf6fa62..baffe0816b 100644 --- a/comms/dht/src/discovery/requester.rs +++ b/comms/dht/src/discovery/requester.rs @@ -33,7 +33,7 @@ use tari_comms::{ peer_manager::{NodeId, Peer}, types::CommsPublicKey, }; -use tokio::future::FutureExt; +use tokio::time; #[derive(Debug)] pub struct DiscoverPeerRequest { @@ -118,8 +118,10 @@ impl DhtDiscoveryRequester { .send(DhtDiscoveryRequest::DiscoverPeer(Box::new((request, reply_tx)))) .await?; - reply_rx - .timeout(self.discovery_timeout) + time::timeout( + self.discovery_timeout, + reply_rx + ) .await // Timeout? .map_err(|_| DhtDiscoveryError::DiscoveryTimeout)? diff --git a/comms/dht/src/inbound/decryption.rs b/comms/dht/src/inbound/decryption.rs index 01b26df25f..0a6f1e3747 100644 --- a/comms/dht/src/inbound/decryption.rs +++ b/comms/dht/src/inbound/decryption.rs @@ -24,10 +24,10 @@ use crate::{ envelope::DhtMessageFlags, inbound::message::{DecryptedDhtMessage, DhtInboundMessage}, }; -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; use log::*; use prost::Message; -use std::sync::Arc; +use std::{sync::Arc, task::Poll}; use tari_comms::{message::EnvelopeBody, peer_manager::NodeIdentity, utils::crypt}; use tari_comms_middleware::MiddlewareError; use tower::{layer::Layer, Service, ServiceExt}; diff --git a/comms/dht/src/inbound/dedup.rs b/comms/dht/src/inbound/dedup.rs index cc5740ae5b..bf017d4f18 100644 --- a/comms/dht/src/inbound/dedup.rs +++ b/comms/dht/src/inbound/dedup.rs @@ -21,8 +21,9 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::{actor::DhtRequester, inbound::DhtInboundMessage}; -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; use log::*; +use std::task::Poll; use tari_comms_middleware::MiddlewareError; use tower::{layer::Layer, Service, ServiceExt}; @@ -123,7 +124,7 @@ mod test { #[test] fn process_message() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let spy = service_spy(); let (dht_requester, mut mock) = create_dht_actor_mock(1); @@ -148,6 +149,5 @@ mod test { assert_eq!(spy.call_count(), 1); // Drop dedup so that the DhtMock will stop running drop(dedup); - rt.shutdown_on_idle(); } } diff --git a/comms/dht/src/inbound/deserialize.rs b/comms/dht/src/inbound/deserialize.rs index 0acea8055b..e749ca364f 100644 --- a/comms/dht/src/inbound/deserialize.rs +++ b/comms/dht/src/inbound/deserialize.rs @@ -21,10 +21,10 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::{inbound::DhtInboundMessage, proto::envelope::DhtEnvelope}; -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; use log::*; use prost::Message; -use std::convert::TryInto; +use std::{convert::TryInto, task::Poll}; use tari_comms::message::InboundMessage; use tari_comms_middleware::MiddlewareError; use tower::{layer::Layer, Service, ServiceExt}; diff --git a/comms/dht/src/inbound/dht_handler/middleware.rs b/comms/dht/src/inbound/dht_handler/middleware.rs index 712b1b63d9..2d922074eb 100644 --- a/comms/dht/src/inbound/dht_handler/middleware.rs +++ b/comms/dht/src/inbound/dht_handler/middleware.rs @@ -27,8 +27,8 @@ use crate::{ inbound::DecryptedDhtMessage, outbound::OutboundMessageRequester, }; -use futures::{task::Context, Future, Poll}; -use std::sync::Arc; +use futures::{task::Context, Future}; +use std::{sync::Arc, task::Poll}; use tari_comms::peer_manager::{NodeIdentity, PeerManager}; use tari_comms_middleware::MiddlewareError; use tower::Service; diff --git a/comms/dht/src/lib.rs b/comms/dht/src/lib.rs index b1fdb63c75..527569f9c3 100644 --- a/comms/dht/src/lib.rs +++ b/comms/dht/src/lib.rs @@ -123,6 +123,7 @@ mod consts; mod dht; mod discovery; mod proto; +mod utils; pub mod broadcast_strategy; pub mod domain_message; diff --git a/comms/dht/src/outbound/broadcast.rs b/comms/dht/src/outbound/broadcast.rs index 59a27906b6..f806cf4680 100644 --- a/comms/dht/src/outbound/broadcast.rs +++ b/comms/dht/src/outbound/broadcast.rs @@ -39,10 +39,9 @@ use futures::{ stream::{self, StreamExt}, task::Context, Future, - Poll, }; use log::*; -use std::sync::Arc; +use std::{sync::Arc, task::Poll}; use tari_comms::{ message::MessageFlags, peer_manager::{NodeId, NodeIdentity, Peer}, @@ -419,7 +418,7 @@ mod test { #[test] fn send_message_flood() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let pk = CommsPublicKey::default(); let example_peer = Peer::new( @@ -482,7 +481,7 @@ mod test { #[test] fn send_message_direct_not_found() { // Test for issue https://github.com/tari-project/tari/issues/959 - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let pk = CommsPublicKey::default(); let node_identity = NodeIdentity::random( @@ -531,7 +530,7 @@ mod test { #[test] fn send_message_direct_dht_discovery() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let node_identity = NodeIdentity::random( &mut OsRng::new().unwrap(), diff --git a/comms/dht/src/outbound/encryption.rs b/comms/dht/src/outbound/encryption.rs index 027fe9e8dd..139661ca6c 100644 --- a/comms/dht/src/outbound/encryption.rs +++ b/comms/dht/src/outbound/encryption.rs @@ -21,9 +21,9 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::outbound::message::{DhtOutboundMessage, OutboundEncryption}; -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; use log::*; -use std::sync::Arc; +use std::{sync::Arc, task::Poll}; use tari_comms::{peer_manager::NodeIdentity, utils::crypt}; use tari_comms_middleware::MiddlewareError; use tower::{layer::Layer, Service, ServiceExt}; diff --git a/comms/dht/src/outbound/serialize.rs b/comms/dht/src/outbound/serialize.rs index c1701168ba..14d5a285ec 100644 --- a/comms/dht/src/outbound/serialize.rs +++ b/comms/dht/src/outbound/serialize.rs @@ -21,9 +21,9 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::{consts::DHT_RNG, outbound::message::DhtOutboundMessage, proto::envelope::DhtEnvelope}; -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; use log::*; -use std::sync::Arc; +use std::{sync::Arc, task::Poll}; use tari_comms::{ message::MessageExt, outbound_message_service::OutboundMessage, diff --git a/comms/dht/src/store_forward/error.rs b/comms/dht/src/store_forward/error.rs index f1ca2bff91..5fa70b7306 100644 --- a/comms/dht/src/store_forward/error.rs +++ b/comms/dht/src/store_forward/error.rs @@ -52,4 +52,6 @@ pub enum StoreAndForwardError { DecodeError(DecodeError), /// Dht header was not provided DhtHeaderNotProvided, + /// Failed to spawn blocking task + JoinError(tokio::task::JoinError), } diff --git a/comms/dht/src/store_forward/forward.rs b/comms/dht/src/store_forward/forward.rs index 06cf0a34f2..81c41d3962 100644 --- a/comms/dht/src/store_forward/forward.rs +++ b/comms/dht/src/store_forward/forward.rs @@ -26,9 +26,9 @@ use crate::{ outbound::{OutboundMessageRequester, SendMessageParams}, store_forward::error::StoreAndForwardError, }; -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; use log::*; -use std::sync::Arc; +use std::{sync::Arc, task::Poll}; use tari_comms::{peer_manager::PeerManager, types::CommsPublicKey}; use tari_comms_middleware::MiddlewareError; use tower::{layer::Layer, Service, ServiceExt}; @@ -234,7 +234,7 @@ mod test { #[test] fn decryption_failed() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let spy = service_spy(); let peer_manager = make_peer_manager(); let (oms_requester, oms_mock) = create_outbound_service_mock(1); diff --git a/comms/dht/src/store_forward/saf_handler/middleware.rs b/comms/dht/src/store_forward/saf_handler/middleware.rs index 9ca14f256b..c84c504842 100644 --- a/comms/dht/src/store_forward/saf_handler/middleware.rs +++ b/comms/dht/src/store_forward/saf_handler/middleware.rs @@ -28,8 +28,8 @@ use crate::{ outbound::OutboundMessageRequester, store_forward::SafStorage, }; -use futures::{task::Context, Future, Poll}; -use std::sync::Arc; +use futures::{task::Context, Future}; +use std::{sync::Arc, task::Poll}; use tari_comms::peer_manager::{NodeIdentity, PeerManager}; use tari_comms_middleware::MiddlewareError; use tower::Service; diff --git a/comms/dht/src/store_forward/saf_handler/task.rs b/comms/dht/src/store_forward/saf_handler/task.rs index 1679133c24..f4b70b1545 100644 --- a/comms/dht/src/store_forward/saf_handler/task.rs +++ b/comms/dht/src/store_forward/saf_handler/task.rs @@ -31,8 +31,9 @@ use crate::{ store_forward::{StoredMessage, StoredMessagesRequest, StoredMessagesResponse}, }, store_forward::{error::StoreAndForwardError, SafStorage}, + utils::hoist_nested_result, }; -use futures::{future, stream, Future, StreamExt}; +use futures::{future, stream, Future, FutureExt, StreamExt}; use log::*; use prost::Message; use std::{convert::TryInto, sync::Arc}; @@ -43,8 +44,7 @@ use tari_comms::{ }; use tari_comms_middleware::MiddlewareError; use tari_utilities::ByteArray; -use tokio::runtime::current_thread; -use tokio_executor::blocking; +use tokio::{runtime, task}; use tower::{Service, ServiceExt}; const LOG_TARGET: &'static str = "comms::dht::store_forward"; @@ -300,7 +300,7 @@ where S: Service let peer_manager = Arc::clone(&self.peer_manager); let config = self.config.clone(); let mut dht_requester = self.dht_requester.clone(); - blocking::run(move || { + task::spawn_blocking(move || { if message.dht_header.is_none() { return Err(StoreAndForwardError::DhtHeaderNotProvided); } @@ -318,7 +318,7 @@ where S: Service Self::check_flags(&dht_header)?; // Check that the message has not already been received. // The current thread runtime is used because calls to the DHT actor are async - let mut rt = current_thread::Runtime::new()?; + let mut rt = runtime::Builder::new().basic_scheduler().build()?; rt.block_on(Self::check_duplicate(&mut dht_requester, &dht_header))?; // Attempt to decrypt the message @@ -332,6 +332,7 @@ where S: Service Ok(DecryptedDhtMessage::succeeded(decrypted_body, inbound_msg)) }) + .map(hoist_nested_result) } async fn check_duplicate( diff --git a/comms/dht/src/store_forward/store.rs b/comms/dht/src/store_forward/store.rs index a0b955ac33..50d9f868d4 100644 --- a/comms/dht/src/store_forward/store.rs +++ b/comms/dht/src/store_forward/store.rs @@ -27,9 +27,9 @@ use crate::{ store_forward::{error::StoreAndForwardError, state::SafStorage}, DhtConfig, }; -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; use log::*; -use std::sync::Arc; +use std::{sync::Arc, task::Poll}; use tari_comms::peer_manager::{NodeIdentity, PeerManager}; use tari_comms_middleware::MiddlewareError; use tower::{layer::Layer, Service, ServiceExt}; diff --git a/comms/dht/src/test_utils/service.rs b/comms/dht/src/test_utils/service.rs index 2af2c4cae1..5f34ff9c01 100644 --- a/comms/dht/src/test_utils/service.rs +++ b/comms/dht/src/test_utils/service.rs @@ -20,16 +20,16 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use futures::{future, Poll}; +use futures::future; use std::{ + future::Future, sync::{ atomic::{AtomicUsize, Ordering}, Arc, Mutex, }, - task::Context, + task::{Context, Poll}, }; -use tokio::future::Future; use tower::Service; pub fn service_spy() -> ServiceSpy diff --git a/comms/dht/src/utils.rs b/comms/dht/src/utils.rs new file mode 100644 index 0000000000..7a15329eaf --- /dev/null +++ b/comms/dht/src/utils.rs @@ -0,0 +1,30 @@ +// Copyright 2020, The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// Returns a "denested" result. The outer Result is converted into the inner Result +pub fn hoist_nested_result(result: Result, E1>) -> Result +where E1: Into { + match result { + Ok(v) => v, + Err(err) => Err(err.into()), + } +} diff --git a/comms/dht/tests/dht.rs b/comms/dht/tests/dht.rs index 5753d423d1..19b77e6b74 100644 --- a/comms/dht/tests/dht.rs +++ b/comms/dht/tests/dht.rs @@ -22,10 +22,7 @@ use futures::channel::mpsc; use rand::rngs::OsRng; -use std::{ - sync::Arc, - time::{Duration, Instant}, -}; +use std::{sync::Arc, time::Duration}; use tari_comms::{ builder::CommsNode, connection_manager::PeerConnectionConfig, @@ -39,7 +36,6 @@ use tari_comms_dht::{envelope::NodeDestination, inbound::DecryptedDhtMessage, Dh use tari_comms_middleware::{pipeline::ServicePipeline, sink::SinkMiddleware}; use tari_storage::{lmdb_store::LMDBBuilder, LMDBWrapper}; use tari_test_utils::{async_assert_eventually, paths::create_temporary_data_path, random, runtime}; -use tokio::runtime::TaskExecutor; use tower::ServiceBuilder; fn new_node_identity(control_service_address: Multiaddr) -> NodeIdentity { @@ -72,7 +68,7 @@ fn create_peer_storage(peers: Vec) -> CommsDatabase { } fn setup_comms_dht( - executor: TaskExecutor, + executor: tokio::runtime::Handle, node_identity: NodeIdentity, storage: CommsDatabase, inbound_sink: mpsc::Sender, @@ -146,7 +142,7 @@ fn dht_join_propagation() { // Node A knows about Node B let (tx, ims_rx_A) = mpsc::channel(1); let (node_A_comms, node_A_dht) = setup_comms_dht( - rt.executor(), + rt.handle().clone(), node_A_identity.clone(), create_peer_storage(vec![node_B_identity.clone().into()]), tx, @@ -154,7 +150,7 @@ fn dht_join_propagation() { // Node B knows about Node A and C let (tx, ims_rx_B) = mpsc::channel(1); let (node_B_comms, node_B_dht) = setup_comms_dht( - rt.executor(), + rt.handle().clone(), node_B_identity.clone(), create_peer_storage(vec![node_A_identity.clone().into(), node_C_identity.clone().into()]), tx, @@ -162,7 +158,7 @@ fn dht_join_propagation() { // Node C knows about Node B let (tx, ims_rx_C) = mpsc::channel(1); let (node_C_comms, node_C_dht) = setup_comms_dht( - rt.executor(), + rt.handle().clone(), node_C_identity.clone(), create_peer_storage(vec![node_B_identity.clone().into()]), tx, @@ -226,7 +222,7 @@ fn dht_discover_propagation() { // Node A knows about Node B let (tx, ims_rx_A) = mpsc::channel(1); let (node_A_comms, node_A_dht) = setup_comms_dht( - rt.executor(), + rt.handle().clone(), node_A_identity.clone(), create_peer_storage(vec![node_B_identity.clone().into()]), tx, @@ -234,7 +230,7 @@ fn dht_discover_propagation() { // Node B knows about Node C let (tx, ims_rx_B) = mpsc::channel(1); let (node_B_comms, node_B_dht) = setup_comms_dht( - rt.executor(), + rt.handle().clone(), node_B_identity.clone(), create_peer_storage(vec![node_C_identity.clone().into()]), tx, @@ -242,15 +238,19 @@ fn dht_discover_propagation() { // Node C knows about Node D let (tx, ims_rx_C) = mpsc::channel(1); let (node_C_comms, node_C_dht) = setup_comms_dht( - rt.executor(), + rt.handle().clone(), node_C_identity.clone(), create_peer_storage(vec![node_D_identity.clone().into()]), tx, ); // Node C knows no one let (tx, ims_rx_D) = mpsc::channel(1); - let (node_D_comms, node_D_dht) = - setup_comms_dht(rt.executor(), node_D_identity.clone(), create_peer_storage(vec![]), tx); + let (node_D_comms, node_D_dht) = setup_comms_dht( + rt.handle().clone(), + node_D_identity.clone(), + create_peer_storage(vec![]), + tx, + ); rt.spawn(async move { // Send a discover request from Node A, through B and C, to D. Once Node D diff --git a/comms/middleware/Cargo.toml b/comms/middleware/Cargo.toml index ddead82b5b..2f876bbc62 100644 --- a/comms/middleware/Cargo.toml +++ b/comms/middleware/Cargo.toml @@ -19,18 +19,18 @@ tari_utilities = { version = "^0.0", path = "../../infrastructure/tari_util"} tari_shutdown = { version="^0.0", path = "../../infrastructure/shutdown" } derive-error = "0.0.4" -futures= {version= "0.3.0-alpha.19", package="futures-preview"} +futures= {version= "^0.3.1"} log = "0.4.8" serde = "1.0.90" serde_derive = "1.0.90" -tokio = "0.2.0-alpha.6" -tower= "0.3.0-alpha.2" +tokio = "^0.2" +tower= "0.3.0" rand = "0.5.5" [dev-dependencies] tari_test_utils = {version="^0.0", path="../../infrastructure/test_utils"} tari_storage = {version = "^0.0", path = "../../infrastructure/storage"} -futures-test = { version = "0.3.0-alpha.18", package = "futures-test-preview" } +futures-test = { version = "^0.3.1" } lmdb-zero = "0.4.4" tempdir = "0.3.7" diff --git a/comms/middleware/src/pipeline.rs b/comms/middleware/src/pipeline.rs index 35ba927a91..7fdf1fc54e 100644 --- a/comms/middleware/src/pipeline.rs +++ b/comms/middleware/src/pipeline.rs @@ -24,7 +24,7 @@ use futures::{future, future::Either, stream::FusedStream, FutureExt, Stream, St use log::*; use std::fmt::Debug; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; use tower::{Service, ServiceExt}; const LOG_TARGET: &'static str = "comms::middleware::pipeline"; @@ -60,14 +60,14 @@ where self } - pub fn spawn_with(self, executor: TaskExecutor) { + pub fn spawn_with(self, executor: runtime::Handle) { executor.spawn(self.run(executor.clone()).unwrap_or_else(|err| { error!(target: LOG_TARGET, "ServicePipeline error: {:?}", err); () })); } - pub async fn run(mut self, executor: TaskExecutor) -> Result<(), TSvc::Error> { + pub async fn run(mut self, executor: runtime::Handle) -> Result<(), TSvc::Error> { let mut stream = self.stream.fuse(); let mut shutdown_signal = self .shutdown_signal @@ -83,13 +83,13 @@ where futures::select! { item = stream.select_next_some() => { let mut service = self.service.clone(); - // Call the service on it's own spawned task + // Call the service in it's own spawned task executor.spawn(async move { if let Err(err) = service.oneshot(item).await { // TODO: might want to dispatch this to tracing or provide an on_error callback error!(target: LOG_TARGET, "ServicePipeline error: {:?}", err); } - }) + }); }, should_shutdown = shutdown_signal => { @@ -114,29 +114,36 @@ mod test { use super::*; use crate::test_utils::service_fn; use futures::{future, stream}; - use std::sync::{Arc, Mutex}; + use std::{ + sync::{Arc, Mutex}, + time::Duration, + }; + use tari_test_utils::async_assert_eventually; use tokio::runtime::Runtime; #[test] fn run() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let items = vec![1, 2, 3, 4, 5, 6]; - let st = stream::iter(items.clone()).fuse(); + let stream = stream::iter(items.clone()).fuse(); let collection = Arc::new(Mutex::new(Vec::new())); let cloned = Arc::clone(&collection); let pipeline = ServicePipeline::new( - st, + stream, service_fn(move |req| { cloned.lock().unwrap().push(req); future::ready(Result::<_, ()>::Ok(())) }), ); - rt.block_on(pipeline.run(rt.executor())).unwrap(); - rt.shutdown_on_idle(); - { - let c = collection.lock().unwrap(); - assert_eq!(c.len(), items.len()); - assert!(c.iter().all(|i| items.contains(i))); - } + rt.block_on(pipeline.run(rt.handle().clone())).unwrap(); + rt.block_on(async move { + async_assert_eventually!( + collection.lock().unwrap().len(), + expect = items.len(), + max_attempts = 10, + interval = Duration::from_millis(10) + ); + assert!(collection.lock().unwrap().iter().all(|i| items.contains(i))); + }); } } diff --git a/comms/middleware/src/sink.rs b/comms/middleware/src/sink.rs index ca52d4ce19..b4bf657a97 100644 --- a/comms/middleware/src/sink.rs +++ b/comms/middleware/src/sink.rs @@ -21,9 +21,9 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::MiddlewareError; -use futures::{task::Context, Future, Poll, Sink, SinkExt}; +use futures::{task::Context, Future, Sink, SinkExt}; use log::*; -use std::{error::Error, pin::Pin}; +use std::{error::Error, pin::Pin, task::Poll}; use tower::Service; const LOG_TARGET: &'static str = "comms::middleware::sink"; diff --git a/comms/middleware/src/test_utils.rs b/comms/middleware/src/test_utils.rs index 7e1e7e91ac..f9c0c028c9 100644 --- a/comms/middleware/src/test_utils.rs +++ b/comms/middleware/src/test_utils.rs @@ -23,7 +23,8 @@ //---------------------------------- ServiceFn --------------------------------------------// // TODO: Remove this when https://github.com/tower-rs/tower/pull/318 is published -use futures::{task::Context, Future, Poll}; +use futures::{task::Context, Future}; +use std::task::Poll; use tower::Service; /// Returns a new `ServiceFn` with the given closure. diff --git a/comms/middleware/tower-filter/Cargo.toml b/comms/middleware/tower-filter/Cargo.toml index 0a7204f44a..4069689fcb 100644 --- a/comms/middleware/tower-filter/Cargo.toml +++ b/comms/middleware/tower-filter/Cargo.toml @@ -24,12 +24,13 @@ edition = "2018" publish = false [dependencies] -tower= { version = "=0.3.0-alpha.2"} +tower= { version = "^0.3.0"} pin-project = "0.4" -futures-core-preview = "=0.3.0-alpha.19" +futures-core = "^0.3.1" [dev-dependencies] -tower-test = { version = "=0.3.0-alpha.2" } -tokio-test = "=0.2.0-alpha.6" -tokio = "=0.2.0-alpha.6" -futures-util-preview = "=0.3.0-alpha.19" +tower-test = { version = "^0.3" } +tokio-test = "^0.2" +tokio = "^0.2" +futures-util = "^0.3.1" +tokio-macros = "0.2.3" diff --git a/comms/middleware/tower-filter/tests/filter.rs b/comms/middleware/tower-filter/tests/filter.rs index ff869b894e..e6ada7fd9d 100644 --- a/comms/middleware/tower-filter/tests/filter.rs +++ b/comms/middleware/tower-filter/tests/filter.rs @@ -1,15 +1,16 @@ use futures_util::{future::poll_fn, pin_mut}; -use std::{future::Future, thread}; -use tokio_test::{assert_ready, assert_ready_err, task}; +use std::future::Future; +use tokio::runtime::Handle; +use tokio_test::task; use tower::Service; use tower_filter::{error::Error, Filter}; use tower_test::{assert_request_eq, mock}; -#[tokio::test] +#[tokio_macros::test] async fn passthrough_sync() { let (mut service, handle) = new_service(|_| async { Ok(()) }); - let th = thread::spawn(move || { + let handle = Handle::current().spawn(async move { // Receive the requests and respond pin_mut!(handle); for i in 0..10 { @@ -33,24 +34,21 @@ async fn passthrough_sync() { } futures_util::future::join_all(responses).await; - th.join().unwrap(); + handle.await.unwrap(); } #[test] fn rejected_sync() { - task::mock(|cx| { + task::spawn(async { let (mut service, _handle) = new_service(|_| async { Err(Error::rejected()) }); - - let fut = service.call("hello".into()); - pin_mut!(fut); - assert_ready_err!(fut.poll(cx)); + service.call("hello".into()).await.unwrap_err(); }); } type Mock = mock::Mock; -type Handle = mock::Handle; +type MockHandle = mock::Handle; -fn new_service(f: F) -> (Filter, Handle) +fn new_service(f: F) -> (Filter, MockHandle) where F: Fn(&String) -> U, U: Future>, diff --git a/comms/src/builder/builder.rs b/comms/src/builder/builder.rs index a07ea8c47c..e16dd989b9 100644 --- a/comms/src/builder/builder.rs +++ b/comms/src/builder/builder.rs @@ -44,7 +44,7 @@ use futures::{channel::mpsc, stream, Sink, Stream}; use log::*; use std::{fmt::Debug, sync::Arc}; use tari_shutdown::{Shutdown, ShutdownSignal}; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &str = "comms::builder"; @@ -90,14 +90,14 @@ pub struct CommsBuilder { node_identity: Option>, peer_conn_config: Option, comms_builder_config: Option, - executor: TaskExecutor, + executor: runtime::Handle, oms_backoff: Option, on_shutdown: Option>, } impl CommsBuilder, stream::Empty> { /// Create a new CommsBuilder - pub fn new(executor: TaskExecutor) -> Self { + pub fn new(executor: runtime::Handle) -> Self { let zmq_context = ZmqContext::new(); Self { @@ -380,7 +380,7 @@ pub struct CommsContainer { connection_manager_actor: CommsConnectionManagerActor, control_service: Option, - executor: TaskExecutor, + executor: runtime::Handle, inbound_message_service: InboundMessageService, @@ -437,7 +437,7 @@ pub struct CommsNode { shutdown: Shutdown, node_identity: Arc, peer_manager: Arc, - executor: TaskExecutor, + executor: runtime::Handle, } impl CommsNode { @@ -452,7 +452,7 @@ impl CommsNode { } /// Return a reference to the executor used to run comms tasks - pub fn executor(&self) -> &TaskExecutor { + pub fn executor(&self) -> &runtime::Handle { &self.executor } @@ -514,7 +514,7 @@ mod test { #[test] fn new_no_control_service() { let rt = Runtime::new().unwrap(); - let container = CommsBuilder::new(rt.executor()) + let container = CommsBuilder::new(rt.handle().clone()) .with_node_identity(Arc::new(NodeIdentity::random_for_test(None, PeerFeatures::empty()))) .with_peer_storage(HashmapDatabase::new()) .build() @@ -526,7 +526,7 @@ mod test { #[test] fn new_with_control_service() { let rt = Runtime::new().unwrap(); - let container = CommsBuilder::new(rt.executor()) + let container = CommsBuilder::new(rt.handle().clone()) .with_node_identity(Arc::new(NodeIdentity::random_for_test(None, PeerFeatures::empty()))) .with_peer_storage(HashmapDatabase::new()) .configure_control_service(ControlServiceConfig::default()) diff --git a/comms/src/builder/mod.rs b/comms/src/builder/mod.rs index f86ae6e14c..1922195ef2 100644 --- a/comms/src/builder/mod.rs +++ b/comms/src/builder/mod.rs @@ -33,7 +33,6 @@ //! # use tari_storage::lmdb_store::LMDBBuilder; //! # use lmdb_zero::db; //! # use tari_storage::LMDBWrapper; -//! # use futures::executor::ThreadPool; //! # use tokio::runtime::Runtime; //! # use futures::channel::mpsc; //! // This should be loaded up from storage @@ -53,7 +52,7 @@ //! let (inbound_tx, _inbound_rx) = mpsc::channel(10); //! let (_outbound_tx, outbound_rx) = mpsc::channel(10); //! let runtime = Runtime::new().unwrap(); -//! let services = CommsBuilder::new(runtime.executor()) +//! let services = CommsBuilder::new(runtime.handle().clone()) //! .with_inbound_sink(inbound_tx) //! .with_outbound_stream(outbound_rx) //! // This enables the control service - allowing another peer to connect to this node diff --git a/comms/src/builder/null_sink.rs b/comms/src/builder/null_sink.rs index 80fb4fe234..c463e5a224 100644 --- a/comms/src/builder/null_sink.rs +++ b/comms/src/builder/null_sink.rs @@ -20,8 +20,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use futures::{task::Context, Poll, Sink}; -use std::{marker::PhantomData, pin::Pin}; +use futures::{task::Context, Sink}; +use std::{marker::PhantomData, pin::Pin, task::Poll}; /// Sink to nowhere. This is used as an initial type for the CommsBuilder /// and should be replaced with a working sink (otherwise inbound messages diff --git a/comms/src/connection_manager/deprecated/actor.rs b/comms/src/connection_manager/deprecated/actor.rs index 9ec3c6db68..4500bf4be5 100644 --- a/comms/src/connection_manager/deprecated/actor.rs +++ b/comms/src/connection_manager/deprecated/actor.rs @@ -278,11 +278,11 @@ mod test { use super::*; use crate::test_utils::dialers::CountDialer; use tari_shutdown::Shutdown; - use tokio::runtime::current_thread; + use tokio::runtime::Builder; #[test] fn requester_dial_peer() { - let mut rt = current_thread::Runtime::new().unwrap(); + let mut rt = Builder::new().basic_scheduler().build().unwrap(); let (tx, mut rx) = mpsc::channel(1); let mut requester = ConnectionManagerRequester::new(tx); let node_id = NodeId::new(); @@ -309,7 +309,7 @@ mod test { #[test] fn connection_manager_service_calls_dialer() { - let mut rt = current_thread::Runtime::new().unwrap(); + let mut rt = Builder::new().basic_scheduler().build().unwrap(); let dialer = CountDialer::::new(); let shutdown = Shutdown::new(); @@ -325,7 +325,7 @@ mod test { #[test] fn connection_manager_service_get_active_connection_count() { - let mut rt = current_thread::Runtime::new().unwrap(); + let mut rt = Builder::new().basic_scheduler().build().unwrap(); let dialer = CountDialer::::new(); let shutdown = Shutdown::new(); diff --git a/comms/src/connection_manager/deprecated/error.rs b/comms/src/connection_manager/deprecated/error.rs index c125145b72..d102ec3b80 100644 --- a/comms/src/connection_manager/deprecated/error.rs +++ b/comms/src/connection_manager/deprecated/error.rs @@ -86,4 +86,5 @@ pub enum ConnectionManagerError { /// The listener has not been started ListenerNotStarted, MultiaddrError(multiaddr::Error), + JoinError(tokio::task::JoinError), } diff --git a/comms/src/connection_manager/deprecated/manager.rs b/comms/src/connection_manager/deprecated/manager.rs index 538c4d77a6..66a1a00652 100644 --- a/comms/src/connection_manager/deprecated/manager.rs +++ b/comms/src/connection_manager/deprecated/manager.rs @@ -46,7 +46,7 @@ use crate::{ message::FrameSet, peer_manager::{NodeId, NodeIdentity, Peer, PeerManager}, }; -use futures::{channel::mpsc::Sender, Future}; +use futures::{channel::mpsc::Sender, Future, FutureExt}; use log::*; use std::{ collections::HashMap, @@ -55,7 +55,7 @@ use std::{ time::Duration, }; use tari_utilities::{thread_join::thread_join::ThreadJoinWithTimeout, ByteArray}; -use tokio_executor::blocking; +use tokio::task; const LOG_TARGET: &str = "comms::connection_manager::manager"; @@ -505,10 +505,14 @@ impl Dialer for ConnectionManagerDialer { fn dial(&self, node_id: &NodeId) -> Self::Future { let inner = Arc::clone(&self.inner); let node_id = node_id.clone(); - blocking::run(move || { + task::spawn_blocking(move || { // TODO: This is synchronous until we can make connection manager fully async inner.establish_connection_to_node_id(&node_id) }) + .map(|result| match result { + Ok(x) => x, + Err(err) => Err(err.into()), + }) } } diff --git a/comms/src/connection_manager/dialer.rs b/comms/src/connection_manager/dialer.rs index 1a4e931a93..f339ed8874 100644 --- a/comms/src/connection_manager/dialer.rs +++ b/comms/src/connection_manager/dialer.rs @@ -47,9 +47,9 @@ use futures::{ StreamExt, }; use log::*; -use std::{collections::HashMap, sync::Arc, time::Instant}; +use std::{collections::HashMap, sync::Arc}; use tari_shutdown::{Shutdown, ShutdownSignal}; -use tokio::{runtime::TaskExecutor, timer}; +use tokio::{runtime, time}; const LOG_TARGET: &str = "comms::connection_manager::establisher"; @@ -62,7 +62,7 @@ pub enum DialerRequest { } pub struct Dialer { - executor: TaskExecutor, + executor: runtime::Handle, config: ConnectionManagerConfig, transport: TTransport, backoff: Arc, @@ -80,7 +80,7 @@ where TBackoff: Backoff + Send + Sync + 'static, { pub fn new( - executor: TaskExecutor, + executor: runtime::Handle, config: ConnectionManagerConfig, transport: TTransport, backoff: Arc, @@ -309,7 +309,7 @@ where current_state.peer.node_id.short_str(), backoff_duration.as_secs() ); - let mut delay = timer::delay(Instant::now() + backoff_duration).fuse(); + let mut delay = time::delay_for(backoff_duration).fuse(); let mut cancel_signal = current_state.get_cancel_signal(); futures::select! { _ = delay => { diff --git a/comms/src/connection_manager/listener.rs b/comms/src/connection_manager/listener.rs index 38eaae9c32..55a8111c64 100644 --- a/comms/src/connection_manager/listener.rs +++ b/comms/src/connection_manager/listener.rs @@ -31,13 +31,13 @@ use crate::{ use futures::{channel::mpsc, AsyncRead, AsyncWrite, SinkExt, StreamExt}; use log::*; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &str = "comms::connection_manager::listener"; pub struct PeerListener { listen_address: Multiaddr, - executor: TaskExecutor, + executor: runtime::Handle, conn_man_notifier: mpsc::Sender, shutdown_signal: Option, transport: TTransport, @@ -50,7 +50,7 @@ where TSocket: AsyncRead + AsyncWrite + Send + Unpin + 'static, { pub fn new( - executor: TaskExecutor, + executor: runtime::Handle, listen_address: Multiaddr, transport: TTransport, event_tx: mpsc::Sender, @@ -75,7 +75,7 @@ where match self.listen().await { Ok((inbound, address)) => { - let mut inbound = inbound.fuse(); + let inbound = inbound.fuse(); futures::pin_mut!(inbound); self.transport_address = Some(address); diff --git a/comms/src/connection_manager/manager.rs b/comms/src/connection_manager/manager.rs index 2b356c3b2b..b01b9d058e 100644 --- a/comms/src/connection_manager/manager.rs +++ b/comms/src/connection_manager/manager.rs @@ -45,7 +45,7 @@ use log::*; use multiaddr::Multiaddr; use std::{collections::HashMap, sync::Arc}; use tari_shutdown::ShutdownSignal; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &str = "comms::connection_manager::manager"; @@ -79,7 +79,7 @@ impl Default for ConnectionManagerConfig { pub struct ConnectionManager { config: ConnectionManagerConfig, - executor: TaskExecutor, + executor: runtime::Handle, request_rx: Fuse>, event_rx: Fuse>, establisher_tx: mpsc::Sender, @@ -98,7 +98,7 @@ where { pub fn new( config: ConnectionManagerConfig, - executor: TaskExecutor, + executor: runtime::Handle, transport: TTransport, backoff: Arc, request_rx: mpsc::Receiver, @@ -268,7 +268,7 @@ mod test { #[test] fn connect_to_nonexistent_peer() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let transport = TcpTransport::new(); let transport = NoiseTransport::new( transport, @@ -282,7 +282,7 @@ mod test { let connection_manager = ConnectionManager::new( Default::default(), - rt.executor(), + rt.handle().clone(), transport, Arc::new(ConstantBackoff::new(Duration::from_secs(1))), request_rx, @@ -303,7 +303,5 @@ mod test { } shutdown.trigger().unwrap(); - - rt.shutdown_on_idle(); } } diff --git a/comms/src/connection_manager/peer_connection.rs b/comms/src/connection_manager/peer_connection.rs index 1d1b505fc1..95cf8d4207 100644 --- a/comms/src/connection_manager/peer_connection.rs +++ b/comms/src/connection_manager/peer_connection.rs @@ -38,14 +38,14 @@ use futures::{ }; use log::*; use std::sync::Arc; -use tokio::runtime::TaskExecutor; +use tokio::runtime; const LOG_TARGET: &str = "comms::connection_manager::peer_connection"; const PEER_REQUEST_BUFFER_SIZE: usize = 64; pub async fn create_peer_connection( - executor: TaskExecutor, + executor: runtime::Handle, socket: TSocket, address: Multiaddr, public_key: CommsPublicKey, diff --git a/comms/src/connection_manager/protocol.rs b/comms/src/connection_manager/protocol.rs index e5833dcb1b..98b6344d99 100644 --- a/comms/src/connection_manager/protocol.rs +++ b/comms/src/connection_manager/protocol.rs @@ -163,7 +163,7 @@ mod test { #[test] fn smoke() { // TODO: When we can upgrade to futures 0.3 / async-std we can use an in-memory cursor instead of tcp sockets - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let (mut initiator, mut responder) = rt.block_on(build_connected_tcp_socket_pair()); let mut negotiate_out = ProtocolNegotiation::new(&mut initiator); let mut negotiate_in = ProtocolNegotiation::new(&mut responder); diff --git a/comms/src/macros.rs b/comms/src/macros.rs index 74ba24c353..0fb8164aae 100644 --- a/comms/src/macros.rs +++ b/comms/src/macros.rs @@ -145,7 +145,7 @@ macro_rules! log_if_error_fmt { }}; } -/// Adds #[cfg(feature = "next")] to mod and use +/// Adds #[cfg(feature = "next")] to mod and use statements macro_rules! cfg_next { ($($item:item)+) => { $( diff --git a/comms/src/multiplexing/yamux.rs b/comms/src/multiplexing/yamux.rs index 3e5f130a25..74158c54d0 100644 --- a/comms/src/multiplexing/yamux.rs +++ b/comms/src/multiplexing/yamux.rs @@ -96,7 +96,7 @@ mod test { #[test] fn open_substream() -> io::Result<()> { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let (dialer, listener) = rt.block_on(build_connected_tcp_socket_pair()); let msg = b"The Way of Kings"; @@ -130,7 +130,7 @@ mod test { #[test] fn close() -> io::Result<()> { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let (dialer, listener) = rt.block_on(build_connected_tcp_socket_pair()); let msg = b"Words of Radiance"; @@ -180,7 +180,7 @@ mod test { #[test] fn send_big_message() -> io::Result<()> { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); #[allow(non_upper_case_globals)] static MiB: usize = 1 << 20; static MSG_LEN: usize = 16 * MiB; diff --git a/comms/src/noise/config.rs b/comms/src/noise/config.rs index 11cc115609..d49601280f 100644 --- a/comms/src/noise/config.rs +++ b/comms/src/noise/config.rs @@ -116,7 +116,7 @@ mod test { #[test] fn upgrade_socket() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let node_identity1 = build_node_identity(PeerFeatures::COMMUNICATION_NODE); let config1 = NoiseConfig::new(node_identity1.clone()); diff --git a/comms/src/noise/socket.rs b/comms/src/noise/socket.rs index 04f1780fc6..9d2953255b 100644 --- a/comms/src/noise/socket.rs +++ b/comms/src/noise/socket.rs @@ -666,7 +666,7 @@ mod test { Ok((dialer_result?, listener_result?)) } - #[tokio::test] + #[tokio_macros::test] async fn test_handshake() { let ((dialer_keypair, dialer), (listener_keypair, listener)) = build_test_connection().await.unwrap(); @@ -682,7 +682,7 @@ mod test { ); } - #[tokio::test] + #[tokio_macros::test] async fn simple_test() -> io::Result<()> { let ((_dialer_keypair, dialer), (_listener_keypair, listener)) = build_test_connection().await.unwrap(); @@ -702,7 +702,7 @@ mod test { Ok(()) } - #[tokio::test] + #[tokio_macros::test] async fn interleaved_writes() -> io::Result<()> { let ((_dialer_keypair, dialer), (_listener_keypair, listener)) = build_test_connection().await.unwrap(); @@ -733,7 +733,7 @@ mod test { #[test] fn u16_max_writes() -> io::Result<()> { // Current thread runtime stack overflows, so the full tokio runtime is used here - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); rt.block_on(async move { let ((_dialer_keypair, dialer), (_listener_keypair, listener)) = build_test_connection().await.unwrap(); diff --git a/comms/src/outbound_message_service/service.rs b/comms/src/outbound_message_service/service.rs index 4665a39867..4c526746c6 100644 --- a/comms/src/outbound_message_service/service.rs +++ b/comms/src/outbound_message_service/service.rs @@ -37,11 +37,10 @@ use futures::{ StreamExt, }; use log::*; -use std::{collections::HashMap, sync::Arc, time::Instant}; +use std::{collections::HashMap, sync::Arc}; use tari_shutdown::ShutdownSignal; use tari_utilities::ByteArray; -use tokio::timer; -use tokio_executor::blocking; +use tokio::{task, time}; const LOG_TARGET: &str = "comms::outbound_message_service::worker"; @@ -253,7 +252,9 @@ where async fn test_connection(&self, conn: Arc, node_id: &NodeId) -> bool { let identity = node_id.to_vec(); - blocking::run(move || conn.test_connection(identity).is_ok()).await + task::spawn_blocking(move || conn.test_connection(identity).is_ok()) + .await + .unwrap_or(false) } fn cancel_pending_connection_attempts(&mut self) { @@ -279,7 +280,7 @@ where state.attempts, delay.as_secs() ); - let mut delay = timer::delay(Instant::now() + delay).fuse(); + let mut delay = time::delay_for(delay).fuse(); futures::select! { _ = delay => { debug!(target: LOG_TARGET, "[Attempt {}] Connecting to NodeId '{}'...", state.attempts, state.node_id); @@ -490,7 +491,7 @@ mod test { // Tests sending a number of messages to 2 recipients simultaneously. // This checks that messages from separate requests are batched and a single dial request per // peer is made. - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let (mut new_message_tx, new_message_rx) = mpsc::unbounded(); let (conn_man_tx, mut conn_man_rx) = mpsc::channel(2); @@ -521,7 +522,7 @@ mod test { (node_id1.clone(), b"D".to_vec()), ] .into_iter() - .map(|(node_id, msg)| OutboundMessage::new(node_id, MessageFlags::empty(), msg)), + .map(|(node_id, msg)| Ok(OutboundMessage::new(node_id, MessageFlags::empty(), msg))), ); rt.block_on(new_message_tx.send_all(&mut messages)).unwrap(); @@ -600,6 +601,5 @@ mod test { // Abort pending connections and shutdown the service shutdown.trigger().unwrap(); - rt.shutdown_on_idle(); } } diff --git a/comms/src/peer_manager/async_peer_manager.rs b/comms/src/peer_manager/async_peer_manager.rs index 69f3ace7fc..b3e54bafbb 100644 --- a/comms/src/peer_manager/async_peer_manager.rs +++ b/comms/src/peer_manager/async_peer_manager.rs @@ -22,7 +22,7 @@ use crate::peer_manager::{NodeId, Peer, PeerManager, PeerManagerError}; use std::sync::Arc; -use tokio_executor::blocking; +use tokio::task; #[derive(Clone)] pub struct AsyncPeerManager { @@ -37,7 +37,9 @@ impl AsyncPeerManager { pub async fn find_by_node_id(&self, node_id: &NodeId) -> Result { let node_id = node_id.clone(); let peer_manager = Arc::clone(&self.peer_manager); - blocking::run(move || peer_manager.find_by_node_id(&node_id)).await + task::spawn_blocking(move || peer_manager.find_by_node_id(&node_id)) + .await + .map_err(|_| PeerManagerError::BlockingTaskSpawnError)? } } diff --git a/comms/src/peer_manager/error.rs b/comms/src/peer_manager/error.rs index fb82df9e1a..1ca2b3bd85 100644 --- a/comms/src/peer_manager/error.rs +++ b/comms/src/peer_manager/error.rs @@ -31,6 +31,8 @@ pub enum PeerManagerError { BannedPeer, // An problem has been encountered with the database DatabaseError(KeyValStoreError), + /// Failed to spawn blocking task + BlockingTaskSpawnError, } impl PeerManagerError { diff --git a/comms/src/test_utils/tcp.rs b/comms/src/test_utils/tcp.rs index 1e0e217a8c..98a8956e2d 100644 --- a/comms/src/test_utils/tcp.rs +++ b/comms/src/test_utils/tcp.rs @@ -25,7 +25,7 @@ use futures::StreamExt; use tokio::net::{TcpListener, TcpStream}; pub async fn build_connected_tcp_socket_pair() -> (TcpSocket, TcpSocket) { - let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let mut listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); let local_addr = listener.local_addr().unwrap(); let (in_sock, out_sock) = futures::future::join(listener.incoming().next(), TcpStream::connect(&local_addr)).await; diff --git a/comms/src/test_utils/test_node.rs b/comms/src/test_utils/test_node.rs index 29b65f75f8..45fcd72dbb 100644 --- a/comms/src/test_utils/test_node.rs +++ b/comms/src/test_utils/test_node.rs @@ -80,7 +80,7 @@ pub fn build_connection_manager( let connection_manager = ConnectionManager::new( Default::default(), - runtime.executor(), + runtime.handle().clone(), transport, Arc::new(ConstantBackoff::new(config.dial_backoff_duration)), request_rx, diff --git a/comms/src/transports/tcp.rs b/comms/src/transports/tcp.rs index a1c0f37bba..b1d81a69ce 100644 --- a/comms/src/transports/tcp.rs +++ b/comms/src/transports/tcp.rs @@ -22,9 +22,14 @@ use super::Transport; use crate::utils::multiaddr::{multiaddr_to_socketaddr, socketaddr_to_multiaddr}; -use futures::{future, io::Error, ready, stream::BoxStream, AsyncRead, AsyncWrite, Future, Poll, Stream, StreamExt}; +use futures::{future, io::Error, ready, AsyncRead, AsyncWrite, Future, Stream}; use multiaddr::Multiaddr; -use std::{io, pin::Pin, task::Context, time::Duration}; +use std::{ + io, + pin::Pin, + task::{Context, Poll}, + time::Duration, +}; use tokio::{ io::{AsyncRead as TokioAsyncRead, AsyncWrite as TokioAsyncWrite}, net::{TcpListener, TcpStream}, @@ -90,7 +95,7 @@ impl TcpTransport { impl Transport for TcpTransport { type Error = io::Error; type Inbound = future::Ready>; - type Listener = TcpInbound<'static>; + type Listener = TcpInbound; type Output = (TcpSocket, Multiaddr); type DialFuture = impl Future>; @@ -102,13 +107,7 @@ impl Transport for TcpTransport { let socket_addr = multiaddr_to_socketaddr(&addr)?; let listener = TcpListener::bind(&socket_addr).await?; let local_addr = socketaddr_to_multiaddr(&listener.local_addr()?); - Ok(( - TcpInbound { - incoming: listener.incoming().boxed(), - config, - }, - local_addr, - )) + Ok((TcpInbound::new(config, listener), local_addr)) }) } @@ -126,26 +125,27 @@ impl Transport for TcpTransport { /// Wrapper around an Inbound stream. This ensures that any connecting `TcpStream` is configured according to the /// transport -pub struct TcpInbound<'a> { - incoming: BoxStream<'a, io::Result>, +pub struct TcpInbound { + listener: TcpListener, // BoxStream<'a, io::Result>, config: TcpTransport, } -impl Stream for TcpInbound<'_> { +impl TcpInbound { + pub fn new(config: TcpTransport, listener: TcpListener) -> Self { + Self { listener, config } + } +} + +impl Stream for TcpInbound { type Item = io::Result>>; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match ready!(self.incoming.poll_next_unpin(cx)) { - Some(Ok(stream)) => { - // Configure each socket - self.config.configure(&stream)?; - let peer_addr = socketaddr_to_multiaddr(&stream.peer_addr()?); - let result = future::ready(Ok((TcpSocket::new(stream), peer_addr))); - Poll::Ready(Some(Ok(result))) - }, - Some(Err(err)) => Poll::Ready(Some(Err(err))), - None => Poll::Ready(None), - } + let (socket, _) = ready!(self.listener.poll_accept(cx))?; + // Configure each socket + self.config.configure(&socket)?; + let peer_addr = socketaddr_to_multiaddr(&socket.peer_addr()?); + let result = future::ready(Ok((TcpSocket::new(socket), peer_addr))); + Poll::Ready(Some(Ok(result))) } } diff --git a/comms/tests/connection_manager/actor.rs b/comms/tests/connection_manager/actor.rs index 8249eeba52..563fe2ac77 100644 --- a/comms/tests/connection_manager/actor.rs +++ b/comms/tests/connection_manager/actor.rs @@ -181,7 +181,7 @@ fn with_alice_and_bob(cb: impl FnOnce(CommsTestNode, CommsTestNode)) { #[test] fn establish_connection_simple() { with_alice_and_bob(|alice, bob| { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let shutdown = Shutdown::new(); let (mut requester, service) = create_connection_manager_actor( 1, @@ -204,7 +204,7 @@ fn establish_connection_simple() { #[test] fn establish_connection_simultaneous_connect() { with_alice_and_bob(|alice, bob| { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let shutdown = Shutdown::new(); let (requester_alice, service) = create_connection_manager_actor( 1, diff --git a/comms/tests/inbound_message_service/mod.rs b/comms/tests/inbound_message_service/mod.rs index 61ce371322..2d8bfd9685 100644 --- a/comms/tests/inbound_message_service/mod.rs +++ b/comms/tests/inbound_message_service/mod.rs @@ -35,7 +35,7 @@ use tari_comms::{ use tari_shutdown::Shutdown; use tari_storage::LMDBWrapper; use tari_utilities::ByteArray; -use tokio::{future::FutureExt, runtime::Runtime}; +use tokio::{runtime::Runtime, time::timeout}; /// A utility function that will construct a Comms layer message that would typically arrive from a PeerConnection as a /// FrameSet that deserializes into a MessageEnvelope @@ -58,7 +58,7 @@ fn construct_message(message_body: Vec, node_identity: Arc) -> #[test] fn smoke_test() { - let rt = Runtime::new().unwrap(); + let mut rt = Runtime::new().unwrap(); let node_identity = factories::node_identity::create().build().map(Arc::new).unwrap(); @@ -106,12 +106,14 @@ fn smoke_test() { let num_messages = sent_messages.len(); let messages = rt - .block_on( - inbound_rx - .take(num_messages as u64) - .collect::>() - .timeout(Duration::from_secs(3)), - ) + // timeout() needs to run in the context of a runtime + .block_on(async { + timeout( + Duration::from_secs(3), + inbound_rx.take(num_messages).collect::>(), + ) + .await + }) .unwrap(); assert_eq!(messages.len(), sent_messages.len()); diff --git a/comms/yamux b/comms/yamux deleted file mode 160000 index 9d045557e6..0000000000 --- a/comms/yamux +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9d045557e622db989d12ef2e0d81c1bdc5cd8119 diff --git a/infrastructure/broadcast_channel/Cargo.toml b/infrastructure/broadcast_channel/Cargo.toml index 637e5204f3..10d4bde687 100644 --- a/infrastructure/broadcast_channel/Cargo.toml +++ b/infrastructure/broadcast_channel/Cargo.toml @@ -12,12 +12,12 @@ edition = "2018" [dependencies] arc-swap = "0.4.2" -futures = { version = "=0.3.0-alpha.19", package = "futures-preview" } +futures = { version = "^0.3.1" } crossbeam-channel = "0.3.9" [dev-dependencies] criterion = "0.3.0" -tokio = "0.2.0-alpha.6" +tokio = "0.2.9" [[example]] name = "raw-simple" diff --git a/infrastructure/broadcast_channel/src/async_channel.rs b/infrastructure/broadcast_channel/src/async_channel.rs index 4eb961f126..9be7730303 100644 --- a/infrastructure/broadcast_channel/src/async_channel.rs +++ b/infrastructure/broadcast_channel/src/async_channel.rs @@ -2,11 +2,10 @@ use crate::channel::{bounded as raw_bounded, Receiver, SendError, Sender, TryRec use crossbeam_channel as mpsc; use futures::{ task::{self, AtomicWaker}, - Poll, Sink, Stream, }; -use std::{pin::Pin, sync::Arc}; +use std::{pin::Pin, sync::Arc, task::Poll}; pub fn bounded(size: usize) -> (Publisher, Subscriber) { let (sender, receiver) = raw_bounded(size); diff --git a/infrastructure/pubsub/Cargo.toml b/infrastructure/pubsub/Cargo.toml index 67f5e08473..03bd9d9865 100644 --- a/infrastructure/pubsub/Cargo.toml +++ b/infrastructure/pubsub/Cargo.toml @@ -13,4 +13,4 @@ edition = "2018" [dependencies] tari_broadcast_channel = { version="^0.0", path = "../broadcast_channel" } -futures = { version = "=0.3.0-alpha.19", package = "futures-preview", features=["async-await"] } +futures = { version = "^0.3.1", features=["async-await"] } diff --git a/infrastructure/shutdown/Cargo.toml b/infrastructure/shutdown/Cargo.toml index 9b4d4adcb0..370e827b08 100644 --- a/infrastructure/shutdown/Cargo.toml +++ b/infrastructure/shutdown/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -futures = { version = "=0.3.0-alpha.19", package = "futures-preview"} +futures = "^0.3.1" [dev-dependencies] -tokio = "0.2.0-alpha.6" +tokio = {version="^0.2", features=["rt-core"]} diff --git a/infrastructure/shutdown/src/lib.rs b/infrastructure/shutdown/src/lib.rs index ffab74630d..f2432dd2b8 100644 --- a/infrastructure/shutdown/src/lib.rs +++ b/infrastructure/shutdown/src/lib.rs @@ -115,7 +115,6 @@ mod test { // Shutdown::trigger is idempotent shutdown.trigger().unwrap(); assert_eq!(shutdown.is_triggered(), true); - rt.shutdown_on_idle(); } #[test] @@ -129,7 +128,6 @@ mod test { signal.await.unwrap(); }); shutdown.trigger().unwrap(); - rt.shutdown_on_idle(); } #[test] @@ -143,7 +141,6 @@ mod test { signal.await.unwrap(); }); drop(shutdown); - rt.shutdown_on_idle(); } #[test] @@ -161,6 +158,5 @@ mod test { }); shutdown.trigger().unwrap(); assert_eq!(spy.load(Ordering::SeqCst), true); - rt.shutdown_on_idle(); } } diff --git a/infrastructure/test_utils/Cargo.toml b/infrastructure/test_utils/Cargo.toml index 053520258c..734a7f7224 100644 --- a/infrastructure/test_utils/Cargo.toml +++ b/infrastructure/test_utils/Cargo.toml @@ -7,10 +7,9 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -futures-test = { version = "0.3.0-alpha.18", package = "futures-test-preview" } -futures= {version= "0.3.0-alpha.18", package="futures-preview"} +futures-test = { version = "^0.3.1" } +futures = {version= "^0.3.1"} rand = "0.7.0" -tokio = "0.2.0-alpha.4" -tokio-executor = "0.2.0-alpha.4" +tokio = {version= "0.2.9", features=["rt-threaded", "time", "io-driver"]} lazy_static = "1.3.0" tempdir = "0.3.7" diff --git a/infrastructure/test_utils/src/futures/async_assert_eventually.rs b/infrastructure/test_utils/src/futures/async_assert_eventually.rs index 7d44ffead9..89961e7a3a 100644 --- a/infrastructure/test_utils/src/futures/async_assert_eventually.rs +++ b/infrastructure/test_utils/src/futures/async_assert_eventually.rs @@ -46,7 +46,7 @@ macro_rules! async_assert_eventually { $max_attempts ); } - tokio::timer::delay(Instant::now() + $interval).await; + tokio::time::delay_for($interval).await; value = $check_expr; } }}; diff --git a/infrastructure/test_utils/src/futures/mod.rs b/infrastructure/test_utils/src/futures/mod.rs index a12b9b75f9..e95ce26045 100644 --- a/infrastructure/test_utils/src/futures/mod.rs +++ b/infrastructure/test_utils/src/futures/mod.rs @@ -81,8 +81,8 @@ mod test { use futures::{ future::{self, FutureExt}, task::Context, - Poll, }; + use std::task::Poll; #[test] fn counter_context() { diff --git a/infrastructure/test_utils/src/runtime.rs b/infrastructure/test_utils/src/runtime.rs index 62dcbe91a3..d3b437c19c 100644 --- a/infrastructure/test_utils/src/runtime.rs +++ b/infrastructure/test_utils/src/runtime.rs @@ -20,18 +20,17 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, -}; -use tokio::runtime::Runtime; +use futures::FutureExt; +use std::{future::Future, pin::Pin}; +use tokio::{runtime, runtime::Runtime, task}; -pub fn create_runtime(passed: Arc) -> Runtime { +pub fn create_runtime() -> Runtime { tokio::runtime::Builder::new() - .blocking_threads(4) - // Run the work scheduler on one thread so we can really see the effects of using `blocking` above + .threaded_scheduler() + .enable_io() + .enable_time() + .max_threads(4) .core_threads(1) - .panic_handler(move |_| passed.store(false, Ordering::SeqCst)) .build() .expect("Could not create runtime") } @@ -40,12 +39,61 @@ pub fn create_runtime(passed: Arc) -> Runtime { /// will carry on running forever. /// TODO: Create a test harness which allows test cleanup or at least fail the test after a timeout pub fn test_async(f: F) -where F: FnOnce(&Runtime) { - let passed = Arc::new(AtomicBool::new(true)); - let rt: Runtime = create_runtime(passed.clone()); - f(&rt); - rt.shutdown_on_idle(); - assert!(passed.load(Ordering::SeqCst), "Panic occurred in spawned future"); +where F: FnOnce(&mut TestRuntime) { + let mut rt = TestRuntime::from(create_runtime()); + f(&mut rt); + let handles = rt.handles.drain(..).collect::>(); + for h in handles { + rt.block_on(h); + } +} + +pub struct TestRuntime { + inner: Runtime, + handles: Vec>>>, +} + +impl TestRuntime { + pub fn block_on(&mut self, future: F) -> F::Output { + self.inner.block_on(future) + } + + pub fn spawn(&mut self, future: F) + where + F: Future + Send + 'static, + F::Output: Send + 'static, + { + let handle = self.inner.spawn(future); + self.handles.push( + async move { + if let Err(err) = handle.await { + panic!("{:?}", err); + } + } + .boxed(), + ); + } + + pub fn spawn_unchecked(&mut self, future: F) -> task::JoinHandle + where + F: Future + Send + 'static, + F::Output: Send + 'static, + { + self.inner.spawn(future) + } + + pub fn handle(&self) -> &runtime::Handle { + self.inner.handle() + } +} + +impl From for TestRuntime { + fn from(rt: Runtime) -> Self { + Self { + inner: rt, + handles: Vec::new(), + } + } } // TODO: WIP for a test harness which allows shutdown code to be run in the case of a successful/failed test diff --git a/infrastructure/test_utils/src/streams/mod.rs b/infrastructure/test_utils/src/streams/mod.rs index 5f10374bd2..50f5a88a91 100644 --- a/infrastructure/test_utils/src/streams/mod.rs +++ b/infrastructure/test_utils/src/streams/mod.rs @@ -43,26 +43,26 @@ where /// # use std::time::Duration; /// # use tari_test_utils::collect_stream; /// -/// let rt = Runtime::new().unwrap(); +/// let mut rt = Runtime::new().unwrap(); /// let stream = stream::iter(1..10); /// assert_eq!(collect_stream!(rt, stream, take=3, timeout=Duration::from_secs(1)), vec![1,2,3]); /// ``` #[macro_export] macro_rules! collect_stream { ($runtime:expr, $stream:expr, take=$take:expr, timeout=$timeout:expr $(,)?) => {{ - use futures::StreamExt; - use tokio::future::FutureExt; + use futures::{FutureExt, StreamExt}; + use tokio::time; $runtime - .block_on($stream.take($take).collect::>().timeout($timeout)) + .block_on(async { time::timeout($timeout, $stream.take($take).collect::>()).await }) .expect(format!("Timeout before stream could collect {} item(s)", $take).as_str()) }}; ($runtime:expr, $stream:expr, timeout=$timeout:expr $(,)?) => {{ - use futures::StreamExt; - use tokio::future::FutureExt; + use futures::{FutureExt, StreamExt}; + use tokio::time; $runtime - .block_on($stream.collect::>().timeout($timeout)) + .block_on(async { time::timeout($timeout, $stream.collect::>()).await }) .expect("Stream did not close within timeout") }}; } @@ -75,7 +75,7 @@ macro_rules! collect_stream { /// # use std::time::Duration; /// # use tari_test_utils::collect_stream_count; /// -/// let rt = Runtime::new().unwrap(); +/// let mut rt = Runtime::new().unwrap(); /// let stream = stream::iter(vec![1,2,2,3,2]); /// assert_eq!(collect_stream_count!(rt, stream, timeout=Duration::from_secs(1)).get(&2), Some(&3)); /// ``` diff --git a/rust-toolchain b/rust-toolchain index fb7648c5aa..ee412581d8 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2019-10-04 +nightly-2020-01-08