1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-24 03:42:59 +01:00

migrate to tokio 0.2.2

This commit is contained in:
Nikolay Kim 2019-12-05 16:40:24 +06:00
parent d49aca9595
commit 3a858feaec
37 changed files with 281 additions and 461 deletions

View File

@ -1,5 +1,11 @@
# Changes # Changes
## [1.0.0-alpha.3] - 2019-12-xx
### Changed
* Migrate to `tokio=0.2.2`
## [1.0.0-alpha.2] - 2019-12-02 ## [1.0.0-alpha.2] - 2019-12-02
### Changed ### Changed

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-connect" name = "actix-connect"
version = "1.0.0-alpha.2" version = "1.0.0-alpha.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix connect - tcp connector service" description = "Actix connect - tcp connector service"
keywords = ["network", "framework", "async", "futures"] keywords = ["network", "framework", "async", "futures"]
@ -27,33 +27,33 @@ default = ["uri"]
openssl = ["open-ssl", "tokio-openssl"] openssl = ["open-ssl", "tokio-openssl"]
# rustls # rustls
# rustls = ["rust-tls", "tokio-rustls", "webpki"] rustls = ["rust-tls", "tokio-rustls", "webpki"]
# support http::Uri as connect address # support http::Uri as connect address
uri = ["http"] uri = ["http"]
[dependencies] [dependencies]
actix-service = "1.0.0-alpha.3" actix-service = "1.0.0-alpha.3"
actix-codec = "0.2.0-alpha.2" actix-codec = "0.2.0-alpha.3"
actix-utils = "1.0.0-alpha.2" actix-utils = "1.0.0-alpha.3"
actix-rt = "1.0.0-alpha.2" actix-rt = "1.0.0-alpha.3"
derive_more = "0.99.2" derive_more = "0.99.2"
either = "1.5.2" either = "1.5.2"
futures = "0.3.1" futures = "0.3.1"
http = { version = "0.1.17", optional = true } http = { version = "0.2.0", optional = true }
log = "0.4" log = "0.4"
trust-dns-resolver = { version="0.18.0-alpha.1", default-features = false } # trust-dns-resolver = { version="0.18.0", default-features = false }
trust-dns-resolver = { git = "https://github.com/bluejekyll/trust-dns.git", branch = "update-tokio-0.2-alpha.2" }
# openssl # openssl
open-ssl = { version="0.10", package = "openssl", optional = true } open-ssl = { version="0.10", package = "openssl", optional = true }
tokio-openssl = { version = "0.4.0-alpha.6", optional = true } tokio-openssl = { version = "0.4.0", optional = true }
# rustls # rustls
rust-tls = { version = "0.16.0", package = "rustls", optional = true } rust-tls = { version = "0.16.0", package = "rustls", optional = true }
# tokio-rustls = { version = "0.10.0", optional = true } tokio-rustls = { version = "0.12.0", optional = true }
# tokio-rustls = { git = "https://github.com/quininer/tokio-rustls.git", branch = "tokio-0.2", optional = true }
webpki = { version = "0.21", optional = true } webpki = { version = "0.21", optional = true }
[dev-dependencies] [dev-dependencies]
bytes = "0.4" bytes = "0.5.2"
actix-testing = { version="1.0.0-alpha.2" } actix-testing = { version="1.0.0-alpha.2" }

View File

@ -14,7 +14,7 @@ extern crate log;
mod connect; mod connect;
mod connector; mod connector;
mod error; mod error;
mod resolver; mod resolve;
mod service; mod service;
pub mod ssl; pub mod ssl;
@ -23,15 +23,20 @@ mod uri;
use actix_rt::{net::TcpStream, Arbiter}; use actix_rt::{net::TcpStream, Arbiter};
use actix_service::{pipeline, pipeline_factory, Service, ServiceFactory}; use actix_service::{pipeline, pipeline_factory, Service, ServiceFactory};
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
use trust_dns_resolver::system_conf::read_system_conf;
use trust_dns_resolver::AsyncResolver;
pub use trust_dns_resolver::config::{ResolverConfig, ResolverOpts}; pub mod resolver {
pub use trust_dns_resolver::system_conf::read_system_conf; pub use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
pub use trust_dns_resolver::{error::ResolveError, AsyncResolver}; pub use trust_dns_resolver::system_conf::read_system_conf;
pub use trust_dns_resolver::{error::ResolveError, AsyncResolver};
}
pub use self::connect::{Address, Connect, Connection}; pub use self::connect::{Address, Connect, Connection};
pub use self::connector::{TcpConnector, TcpConnectorFactory}; pub use self::connector::{TcpConnector, TcpConnectorFactory};
pub use self::error::ConnectError; pub use self::error::ConnectError;
pub use self::resolver::{Resolver, ResolverFactory}; pub use self::resolve::{Resolver, ResolverFactory};
pub use self::service::{ConnectService, ConnectServiceFactory, TcpConnectService}; pub use self::service::{ConnectService, ConnectServiceFactory, TcpConnectService};
pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> AsyncResolver { pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> AsyncResolver {

View File

@ -11,7 +11,7 @@ use trust_dns_resolver::AsyncResolver;
use crate::connect::{Address, Connect, Connection}; use crate::connect::{Address, Connect, Connection};
use crate::connector::{TcpConnector, TcpConnectorFactory}; use crate::connector::{TcpConnector, TcpConnectorFactory};
use crate::error::ConnectError; use crate::error::ConnectError;
use crate::resolver::{Resolver, ResolverFactory}; use crate::resolve::{Resolver, ResolverFactory};
pub struct ConnectServiceFactory<T> { pub struct ConnectServiceFactory<T> {
tcp: TcpConnectorFactory<T>, tcp: TcpConnectorFactory<T>,

View File

@ -62,7 +62,7 @@ where
type InitError = (); type InitError = ();
type Future = Ready<Result<Self::Service, Self::InitError>>; type Future = Ready<Result<Self::Service, Self::InitError>>;
fn new_service(&self, _: &()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {
ok(RustlsConnectorService { ok(RustlsConnectorService {
connector: self.connector.clone(), connector: self.connector.clone(),
_t: PhantomData, _t: PhantomData,
@ -93,7 +93,7 @@ where
type Error = std::io::Error; type Error = std::io::Error;
type Future = ConnectAsyncExt<T, U>; type Future = ConnectAsyncExt<T, U>;
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> { fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
@ -120,7 +120,7 @@ where
{ {
type Output = Result<Connection<T, TlsStream<U>>, std::io::Error>; type Output = Result<Connection<T, TlsStream<U>>, std::io::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut(); let this = self.get_mut();
Poll::Ready( Poll::Ready(
futures::ready!(Pin::new(&mut this.fut).poll(cx)).map(|stream| { futures::ready!(Pin::new(&mut this.fut).poll(cx)).map(|stream| {

View File

@ -6,8 +6,8 @@ use actix_service::{service_fn, Service, ServiceFactory};
use actix_testing::TestServer; use actix_testing::TestServer;
use bytes::Bytes; use bytes::Bytes;
use futures::SinkExt; use futures::SinkExt;
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
use actix_connect::resolver::{ResolverConfig, ResolverOpts};
use actix_connect::Connect; use actix_connect::Connect;
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
@ -97,7 +97,7 @@ async fn test_new_service() {
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
#[actix_rt::test] #[actix_rt::test]
async fn test_uri() { async fn test_uri() {
use http::HttpTryFrom; use std::convert::TryFrom;
let srv = TestServer::with(|| { let srv = TestServer::with(|| {
service_fn(|io: TcpStream| { service_fn(|io: TcpStream| {
@ -118,7 +118,7 @@ async fn test_uri() {
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
#[actix_rt::test] #[actix_rt::test]
async fn test_rustls_uri() { async fn test_rustls_uri() {
use http::HttpTryFrom; use std::convert::TryFrom;
let srv = TestServer::with(|| { let srv = TestServer::with(|| {
service_fn(|io: TcpStream| { service_fn(|io: TcpStream| {

View File

@ -1,15 +1,17 @@
# Changes # Changes
## [0.3.0-alpha.3] - 2019-12-xx
* Migrate to `tokio=0.2.2`
## [0.3.0-alpha.2] - 2019-12-02 ## [0.3.0-alpha.2] - 2019-12-02
* Migrate to `std::future` * Migrate to `std::future`
## [0.1.1] - 2019-10-14 ## [0.1.1] - 2019-10-14
* Re-register task on every dispatcher poll. * Re-register task on every dispatcher poll.
## [0.1.0] - 2019-09-25 ## [0.1.0] - 2019-09-25
* Initial release * Initial release

View File

@ -22,7 +22,7 @@ actix-service = "1.0.0-alpha.3"
actix-codec = "0.2.0-alpha.2" actix-codec = "0.2.0-alpha.2"
actix-utils = "1.0.0-alpha.2" actix-utils = "1.0.0-alpha.2"
actix-rt = "1.0.0-alpha.2" actix-rt = "1.0.0-alpha.2"
bytes = "0.4" bytes = "0.5"
either = "1.5.2" either = "1.5.2"
futures = "0.3.1" futures = "0.3.1"
pin-project = "0.4.6" pin-project = "0.4.6"

View File

@ -6,6 +6,10 @@
* Fix compilation on non-unix platforms * Fix compilation on non-unix platforms
### Changed
* Migrate to `tokio=0.2.2`
## [1.0.0-alpha.2] - 2019-12-02 ## [1.0.0-alpha.2] - 2019-12-02

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-rt" name = "actix-rt"
version = "1.0.0-alpha.2" version = "1.0.0-alpha.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix runtime" description = "Actix runtime"
keywords = ["network", "framework", "async", "futures"] keywords = ["network", "framework", "async", "futures"]
@ -22,8 +22,4 @@ actix-macros = "0.1.0-alpha.1"
actix-threadpool = "0.3" actix-threadpool = "0.3"
futures = "0.3.1" futures = "0.3.1"
copyless = "0.1.4" copyless = "0.1.4"
tokio = { version = "0.2.2", default-features=false, features=["rt-core", "rt-util", "io-driver", "tcp", "uds", "udp", "time", "signal"] }
tokio = { version = "=0.2.0-alpha.6", features=["rt-current-thread","tcp","uds","udp","timer","signal"] }
tokio-executor = "=0.2.0-alpha.6"
tokio-net = "=0.2.0-alpha.6"
tokio-timer = "=0.3.0-alpha.6"

View File

@ -9,9 +9,8 @@ use std::{fmt, thread};
use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}; use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
use futures::channel::oneshot::{channel, Canceled, Sender}; use futures::channel::oneshot::{channel, Canceled, Sender};
use futures::{future, Future, FutureExt, Stream}; use futures::{future, Future, FutureExt, Stream};
use tokio_executor::current_thread::spawn;
use crate::builder::Builder; use crate::runtime::Runtime;
use crate::system::System; use crate::system::System;
use copyless::BoxHelper; use copyless::BoxHelper;
@ -19,7 +18,7 @@ use copyless::BoxHelper;
thread_local!( thread_local!(
static ADDR: RefCell<Option<Arbiter>> = RefCell::new(None); static ADDR: RefCell<Option<Arbiter>> = RefCell::new(None);
static RUNNING: Cell<bool> = Cell::new(false); static RUNNING: Cell<bool> = Cell::new(false);
static Q: RefCell<Vec<Box<dyn Future<Output = ()>>>> = RefCell::new(Vec::new()); static Q: RefCell<Vec<Pin<Box<dyn Future<Output = ()>>>>> = RefCell::new(Vec::new());
static STORAGE: RefCell<HashMap<TypeId, Box<dyn Any>>> = RefCell::new(HashMap::new()); static STORAGE: RefCell<HashMap<TypeId, Box<dyn Any>>> = RefCell::new(HashMap::new());
); );
@ -101,7 +100,7 @@ impl Arbiter {
let handle = thread::Builder::new() let handle = thread::Builder::new()
.name(name.clone()) .name(name.clone())
.spawn(move || { .spawn(move || {
let mut rt = Builder::new().build_rt().expect("Can not create Runtime"); let mut rt = Runtime::new().expect("Can not create Runtime");
let arb = Arbiter::with_sender(arb_tx); let arb = Arbiter::with_sender(arb_tx);
let (stop, stop_rx) = channel(); let (stop, stop_rx) = channel();
@ -143,14 +142,16 @@ impl Arbiter {
} }
} }
pub(crate) fn run_system() { pub(crate) fn run_system(rt: Option<&Runtime>) {
RUNNING.with(|cell| cell.set(true)); RUNNING.with(|cell| cell.set(true));
Q.with(|cell| { Q.with(|cell| {
let mut v = cell.borrow_mut(); let mut v = cell.borrow_mut();
for fut in v.drain(..) { for fut in v.drain(..) {
// We pin the boxed future, so it can never again be moved. if let Some(rt) = rt {
let fut = unsafe { Pin::new_unchecked(fut) }; rt.spawn(fut);
tokio_executor::current_thread::spawn(fut); } else {
tokio::task::spawn_local(fut);
}
} }
}); });
} }
@ -169,11 +170,14 @@ impl Arbiter {
RUNNING.with(move |cell| { RUNNING.with(move |cell| {
if cell.get() { if cell.get() {
// Spawn the future on running executor // Spawn the future on running executor
spawn(future); tokio::task::spawn_local(future);
} else { } else {
// Box the future and push it to the queue, this results in double boxing // Box the future and push it to the queue, this results in double boxing
// because the executor boxes the future again, but works for now // because the executor boxes the future again, but works for now
Q.with(move |cell| cell.borrow_mut().push(Box::alloc().init(future))); Q.with(move |cell| {
cell.borrow_mut()
.push(unsafe { Pin::new_unchecked(Box::alloc().init(future)) })
});
} }
}); });
} }
@ -325,7 +329,7 @@ impl Future for ArbiterController {
return Poll::Ready(()); return Poll::Ready(());
} }
ArbiterCommand::Execute(fut) => { ArbiterCommand::Execute(fut) => {
spawn(fut); tokio::task::spawn_local(fut);
} }
ArbiterCommand::ExecuteFn(f) => { ArbiterCommand::ExecuteFn(f) => {
f.call_box(); f.call_box();

View File

@ -4,11 +4,7 @@ use std::io;
use futures::channel::mpsc::unbounded; use futures::channel::mpsc::unbounded;
use futures::channel::oneshot::{channel, Receiver}; use futures::channel::oneshot::{channel, Receiver};
use futures::future::{lazy, Future, FutureExt}; use futures::future::{lazy, Future, FutureExt};
use tokio::task::LocalSet;
use tokio::runtime::current_thread::Handle;
use tokio_executor::current_thread::CurrentThread;
use tokio_net::driver::Reactor;
use tokio_timer::{clock::Clock, timer::Timer};
use crate::arbiter::{Arbiter, SystemArbiter}; use crate::arbiter::{Arbiter, SystemArbiter};
use crate::runtime::Runtime; use crate::runtime::Runtime;
@ -23,9 +19,6 @@ pub struct Builder {
/// Name of the System. Defaults to "actix" if unset. /// Name of the System. Defaults to "actix" if unset.
name: Cow<'static, str>, name: Cow<'static, str>,
/// The clock to use
clock: Clock,
/// Whether the Arbiter will stop the whole System on uncaught panic. Defaults to false. /// Whether the Arbiter will stop the whole System on uncaught panic. Defaults to false.
stop_on_panic: bool, stop_on_panic: bool,
} }
@ -34,7 +27,6 @@ impl Builder {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
Builder { Builder {
name: Cow::Borrowed("actix"), name: Cow::Borrowed("actix"),
clock: Clock::new(),
stop_on_panic: false, stop_on_panic: false,
} }
} }
@ -45,14 +37,6 @@ impl Builder {
self self
} }
/// Set the Clock instance that will be used by this System.
///
/// Defaults to the system clock.
pub fn clock(mut self, clock: Clock) -> Self {
self.clock = clock;
self
}
/// Sets the option 'stop_on_panic' which controls whether the System is stopped when an /// Sets the option 'stop_on_panic' which controls whether the System is stopped when an
/// uncaught panic is thrown from a worker thread. /// uncaught panic is thrown from a worker thread.
/// ///
@ -72,8 +56,8 @@ impl Builder {
/// Create new System that can run asynchronously. /// Create new System that can run asynchronously.
/// ///
/// This method panics if it cannot start the system arbiter /// This method panics if it cannot start the system arbiter
pub(crate) fn build_async(self, executor: Handle) -> AsyncSystemRunner { pub(crate) fn build_async(self, local: &LocalSet) -> AsyncSystemRunner {
self.create_async_runtime(executor) self.create_async_runtime(local)
} }
/// This function will start tokio runtime and will finish once the /// This function will start tokio runtime and will finish once the
@ -86,7 +70,7 @@ impl Builder {
self.create_runtime(f).run() self.create_runtime(f).run()
} }
fn create_async_runtime(self, executor: Handle) -> AsyncSystemRunner { fn create_async_runtime(self, local: &LocalSet) -> AsyncSystemRunner {
let (stop_tx, stop) = channel(); let (stop_tx, stop) = channel();
let (sys_sender, sys_receiver) = unbounded(); let (sys_sender, sys_receiver) = unbounded();
@ -96,7 +80,7 @@ impl Builder {
let arb = SystemArbiter::new(stop_tx, sys_receiver); let arb = SystemArbiter::new(stop_tx, sys_receiver);
// start the system arbiter // start the system arbiter
executor.spawn(arb).expect("could not start system arbiter"); let _ = local.spawn_local(arb);
AsyncSystemRunner { stop, system } AsyncSystemRunner { stop, system }
} }
@ -113,40 +97,14 @@ impl Builder {
// system arbiter // system arbiter
let arb = SystemArbiter::new(stop_tx, sys_receiver); let arb = SystemArbiter::new(stop_tx, sys_receiver);
let mut rt = self.build_rt().unwrap(); let mut rt = Runtime::new().unwrap();
rt.spawn(arb); rt.spawn(arb);
// init system arbiter and run configuration method // init system arbiter and run configuration method
let _ = rt.block_on(lazy(move |_| { rt.block_on(lazy(move |_| f()));
f();
Ok::<_, ()>(())
}));
SystemRunner { rt, stop, system } SystemRunner { rt, stop, system }
} }
pub(crate) fn build_rt(&self) -> io::Result<Runtime> {
// We need a reactor to receive events about IO objects from kernel
let reactor = Reactor::new()?;
let reactor_handle = reactor.handle();
// Place a timer wheel on top of the reactor. If there are no timeouts to fire, it'll let the
// reactor pick up some new external events.
let timer = Timer::new_with_now(reactor, self.clock.clone());
let timer_handle = timer.handle();
// And now put a single-threaded executor on top of the timer. When there are no futures ready
// to do something, it'll let the timer or the reactor to generate some new stimuli for the
// futures to continue in their life.
let executor = CurrentThread::new_with_park(timer);
Ok(Runtime::new2(
reactor_handle,
timer_handle,
self.clock.clone(),
executor,
))
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -163,7 +121,7 @@ impl AsyncSystemRunner {
// run loop // run loop
lazy(|_| { lazy(|_| {
Arbiter::run_system(); Arbiter::run_system(None);
async { async {
let res = match stop.await { let res = match stop.await {
Ok(code) => { Ok(code) => {
@ -202,10 +160,7 @@ impl SystemRunner {
let SystemRunner { mut rt, stop, .. } = self; let SystemRunner { mut rt, stop, .. } = self;
// run loop // run loop
let _ = rt.block_on(async { Arbiter::run_system(Some(&rt));
Arbiter::run_system();
Ok::<_, ()>(())
});
let result = match rt.block_on(stop) { let result = match rt.block_on(stop) {
Ok(code) => { Ok(code) => {
if code != 0 { if code != 0 {
@ -226,17 +181,11 @@ impl SystemRunner {
/// Execute a future and wait for result. /// Execute a future and wait for result.
pub fn block_on<F, O>(&mut self, fut: F) -> O pub fn block_on<F, O>(&mut self, fut: F) -> O
where where
F: Future<Output = O>, F: Future<Output = O> + 'static,
{ {
self.rt.block_on(async { Arbiter::run_system(Some(&self.rt));
Arbiter::run_system();
});
let res = self.rt.block_on(fut); let res = self.rt.block_on(fut);
self.rt.block_on(async { Arbiter::stop_system();
Arbiter::stop_system();
});
res res
} }
} }

View File

@ -38,9 +38,9 @@ where
pub mod signal { pub mod signal {
#[cfg(unix)] #[cfg(unix)]
pub mod unix { pub mod unix {
pub use tokio_net::signal::unix::*; pub use tokio::signal::unix::*;
} }
pub use tokio_net::signal::{ctrl_c, CtrlC}; pub use tokio::signal::ctrl_c;
} }
/// TCP/UDP/Unix bindings /// TCP/UDP/Unix bindings
@ -59,21 +59,8 @@ pub mod net {
/// Utilities for tracking time. /// Utilities for tracking time.
pub mod time { pub mod time {
use std::time::{Duration, Instant}; pub use tokio::time::Instant;
pub use tokio::time::{delay_for, delay_until, Delay};
pub use tokio_timer::Interval; pub use tokio::time::{interval, interval_at, Interval};
pub use tokio_timer::{delay, delay_for, Delay}; pub use tokio::time::{timeout, Timeout};
pub use tokio_timer::{timeout, Timeout};
/// Creates new `Interval` that yields with interval of `duration`. The first
/// tick completes immediately.
pub fn interval(duration: Duration) -> Interval {
Interval::new(Instant::now(), duration)
}
/// Creates new `Interval` that yields with interval of `period` with the
/// first tick completing at `at`.
pub fn interval_at(start: Instant, duration: Duration) -> Interval {
Interval::new(start, duration)
}
} }

View File

@ -1,92 +0,0 @@
//! A runtime implementation that runs everything on the current thread.
//!
//! [`current_thread::Runtime`][rt] is similar to the primary
//! [`Runtime`][concurrent-rt] except that it runs all components on the current
//! thread instead of using a thread pool. This means that it is able to spawn
//! futures that do not implement `Send`.
//!
//! Same as the default [`Runtime`][concurrent-rt], the
//! [`current_thread::Runtime`][rt] includes:
//!
//! * A [reactor] to drive I/O resources.
//! * An [executor] to execute tasks that use these I/O resources.
//! * A [timer] for scheduling work to run after a set period of time.
//!
//! Note that [`current_thread::Runtime`][rt] does not implement `Send` itself
//! and cannot be safely moved to other threads.
//!
//! # Spawning from other threads
//!
//! While [`current_thread::Runtime`][rt] does not implement `Send` and cannot
//! safely be moved to other threads, it provides a `Handle` that can be sent
//! to other threads and allows to spawn new tasks from there.
//!
//! For example:
//!
//! ```
//! # extern crate tokio;
//! # extern crate futures;
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//! use std::thread;
//!
//! # fn main() {
//! let mut runtime = Runtime::new().unwrap();
//! let handle = runtime.handle();
//!
//! thread::spawn(move || {
//! handle.spawn(future::ok(()));
//! }).join().unwrap();
//!
//! # /*
//! runtime.run().unwrap();
//! # */
//! # }
//! ```
//!
//! # Examples
//!
//! Creating a new `Runtime` and running a future `f` until its completion and
//! returning its result.
//!
//! ```
//! use tokio::runtime::current_thread::Runtime;
//! use tokio::prelude::*;
//!
//! let mut runtime = Runtime::new().unwrap();
//!
//! // Use the runtime...
//! // runtime.block_on(f); // where f is a future
//! ```
//!
//! [rt]: struct.Runtime.html
//! [concurrent-rt]: ../struct.Runtime.html
//! [chan]: https://docs.rs/futures/0.1/futures/sync/mpsc/fn.channel.html
//! [reactor]: ../../reactor/struct.Reactor.html
//! [executor]: https://tokio.rs/docs/getting-started/runtime-model/#executors
//! [timer]: ../../timer/index.html
mod builder;
mod runtime;
pub use self::builder::Builder;
pub use self::runtime::{Runtime, Handle};
pub use tokio_current_thread::spawn;
pub use tokio_current_thread::TaskExecutor;
use futures::Future;
/// Run the provided future to completion using a runtime running on the current thread.
///
/// This first creates a new [`Runtime`], and calls [`Runtime::block_on`] with the provided future,
/// which blocks the current thread until the provided future completes. It then calls
/// [`Runtime::run`] to wait for any other spawned futures to resolve.
pub fn block_on_all<F>(future: F) -> Result<F::Item, F::Error>
where
F: Future,
{
let mut r = Runtime::new().expect("failed to start runtime on current thread");
let v = r.block_on(future)?;
r.run().expect("failed to resolve remaining futures");
Ok(v)
}

View File

@ -1,73 +1,36 @@
use std::error::Error; use std::future::Future;
use std::{fmt, io}; use std::io;
use tokio::{runtime, task::LocalSet};
use futures::Future;
use tokio_executor::current_thread::{self, CurrentThread};
use tokio_net::driver::{Handle as ReactorHandle, Reactor};
use tokio_timer::{
clock::Clock,
timer::{self, Timer},
};
use crate::builder::Builder;
/// Single-threaded runtime provides a way to start reactor /// Single-threaded runtime provides a way to start reactor
/// and executor on the current thread. /// and runtime on the current thread.
/// ///
/// See [module level][mod] documentation for more details. /// See [module level][mod] documentation for more details.
/// ///
/// [mod]: index.html /// [mod]: index.html
#[derive(Debug)] #[derive(Debug)]
pub struct Runtime { pub struct Runtime {
reactor_handle: ReactorHandle, local: LocalSet,
timer_handle: timer::Handle, rt: runtime::Runtime,
clock: Clock,
executor: CurrentThread<Timer<Reactor>>,
}
/// Error returned by the `run` function.
#[derive(Debug)]
pub struct RunError {
inner: current_thread::RunError,
}
impl fmt::Display for RunError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "{}", self.inner)
}
}
impl Error for RunError {
fn description(&self) -> &str {
self.inner.description()
}
fn cause(&self) -> Option<&dyn Error> {
self.inner.source()
}
} }
impl Runtime { impl Runtime {
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
/// Returns a new runtime initialized with default configuration values. /// Returns a new runtime initialized with default configuration values.
pub fn new() -> io::Result<Runtime> { pub fn new() -> io::Result<Runtime> {
Builder::new().build_rt() let rt = runtime::Builder::new()
.enable_io()
.enable_time()
.basic_scheduler()
.build()?;
Ok(Runtime {
rt,
local: LocalSet::new(),
})
} }
pub(super) fn new2( /// Spawn a future onto the single-threaded runtime.
reactor_handle: ReactorHandle,
timer_handle: timer::Handle,
clock: Clock,
executor: CurrentThread<Timer<Reactor>>,
) -> Runtime {
Runtime {
reactor_handle,
timer_handle,
clock,
executor,
}
}
/// Spawn a future onto the single-threaded Tokio runtime.
/// ///
/// See [module level][mod] documentation for more details. /// See [module level][mod] documentation for more details.
/// ///
@ -75,7 +38,7 @@ impl Runtime {
/// ///
/// # Examples /// # Examples
/// ///
/// ```rust /// ```rust,ignore
/// # use futures::{future, Future, Stream}; /// # use futures::{future, Future, Stream};
/// use actix_rt::Runtime; /// use actix_rt::Runtime;
/// ///
@ -95,11 +58,11 @@ impl Runtime {
/// ///
/// This function panics if the spawn fails. Failure occurs if the executor /// This function panics if the spawn fails. Failure occurs if the executor
/// is currently at capacity and is unable to spawn a new future. /// is currently at capacity and is unable to spawn a new future.
pub fn spawn<F>(&mut self, future: F) -> &mut Self pub fn spawn<F>(&self, future: F) -> &Self
where where
F: Future<Output = ()> + 'static, F: Future<Output = ()> + 'static,
{ {
self.executor.spawn(future); self.local.spawn_local(future);
self self
} }
@ -121,41 +84,9 @@ impl Runtime {
/// complete execution by calling `block_on` or `run`. /// complete execution by calling `block_on` or `run`.
pub fn block_on<F>(&mut self, f: F) -> F::Output pub fn block_on<F>(&mut self, f: F) -> F::Output
where where
F: Future, F: Future + 'static,
{ {
self.enter(|executor| { let res = self.local.block_on(&mut self.rt, f);
// Run the provided future res
executor.block_on(f)
})
}
/// Run the executor to completion, blocking the thread until **all**
/// spawned futures have completed.
pub fn run(&mut self) -> Result<(), RunError> {
self.enter(|executor| executor.run())
.map_err(|e| RunError { inner: e })
}
fn enter<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut CurrentThread<Timer<Reactor>>) -> R,
{
let Runtime {
ref reactor_handle,
ref timer_handle,
ref clock,
ref mut executor,
..
} = *self;
// WARN: We do not enter the executor here, since in tokio 0.2 the executor is entered
// automatically inside its `block_on` and `run` methods
tokio_executor::with_default(&mut current_thread::TaskExecutor::current(), || {
tokio_timer::clock::with_default(clock, || {
let _reactor_guard = tokio_net::driver::set_default(reactor_handle);
let _timer_guard = tokio_timer::set_default(timer_handle);
f(executor)
})
})
} }
} }

View File

@ -4,7 +4,7 @@ use std::io;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use futures::channel::mpsc::UnboundedSender; use futures::channel::mpsc::UnboundedSender;
use tokio::runtime::current_thread::Handle; use tokio::task::LocalSet;
use crate::arbiter::{Arbiter, SystemCommand}; use crate::arbiter::{Arbiter, SystemCommand};
use crate::builder::{Builder, SystemRunner}; use crate::builder::{Builder, SystemRunner};
@ -58,16 +58,16 @@ impl System {
} }
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
/// Create new system using provided CurrentThread Handle. /// Create new system using provided tokio Handle.
/// ///
/// This method panics if it can not spawn system arbiter /// This method panics if it can not spawn system arbiter
pub fn run_in_executor<T: Into<String>>( pub fn run_in_tokio<T: Into<String>>(
name: T, name: T,
executor: Handle, local: &LocalSet,
) -> impl Future<Output = Result<(), io::Error>> + Send { ) -> impl Future<Output = io::Result<()>> {
Self::builder() Self::builder()
.name(name) .name(name)
.build_async(executor) .build_async(local)
.run_nonblocking() .run_nonblocking()
} }

View File

@ -2,6 +2,10 @@
## [1.0.0-alpha.3] - 2019-12-xx ## [1.0.0-alpha.3] - 2019-12-xx
### Changed
* Migrate to `tokio=0.2.2`
### Fixed ### Fixed
* Fix compilation on non-unix platforms * Fix compilation on non-unix platforms

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-server" name = "actix-server"
version = "1.0.0-alpha.2" version = "1.0.0-alpha.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix server - General purpose tcp server" description = "Actix server - General purpose tcp server"
keywords = ["network", "framework", "async", "futures"] keywords = ["network", "framework", "async", "futures"]
@ -22,9 +22,9 @@ default = []
[dependencies] [dependencies]
actix-service = "1.0.0-alpha.3" actix-service = "1.0.0-alpha.3"
actix-rt = "1.0.0-alpha.2" actix-rt = "1.0.0-alpha.3"
actix-codec = "0.2.0-alpha.2" actix-codec = "0.2.0-alpha.3"
actix-utils = "1.0.0-alpha.2" actix-utils = "1.0.0-alpha.3"
log = "0.4" log = "0.4"
num_cpus = "1.0" num_cpus = "1.0"
@ -33,13 +33,10 @@ net2 = "0.2"
futures = "0.3.1" futures = "0.3.1"
slab = "0.4" slab = "0.4"
tokio-net = { version = "0.2.0-alpha.6", features = ["signal", "tcp", "uds"] }
futures-core-preview = "0.3.0-alpha.19"
# unix domain sockets # unix domain sockets
mio-uds = { version = "0.6.7" } mio-uds = { version = "0.6.7" }
[dev-dependencies] [dev-dependencies]
bytes = "0.4" bytes = "0.5"
env_logger = "0.6" env_logger = "0.6"
actix-testing = "1.0.0-alpha.2" actix-testing = "1.0.0-alpha.3"

View File

@ -1,10 +1,9 @@
use std::sync::mpsc as sync_mpsc; use std::sync::mpsc as sync_mpsc;
use std::time::{Duration, Instant}; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use actix_rt::time::delay; use actix_rt::time::{delay_until, Instant};
use actix_rt::System; use actix_rt::System;
use futures::FutureExt;
use log::{error, info}; use log::{error, info};
use slab::Slab; use slab::Slab;
@ -440,13 +439,10 @@ impl Accept {
info.timeout = Some(Instant::now() + Duration::from_millis(500)); info.timeout = Some(Instant::now() + Duration::from_millis(500));
let r = self.timer.1.clone(); let r = self.timer.1.clone();
System::current().arbiter().send( System::current().arbiter().send(Box::pin(async move {
async move { delay_until(Instant::now() + Duration::from_millis(510)).await;
delay(Instant::now() + Duration::from_millis(510)).await; let _ = r.set_readiness(mio::Ready::readable());
let _ = r.set_readiness(mio::Ready::readable()); }));
}
.boxed(),
);
return; return;
} }
} }

View File

@ -1,10 +1,11 @@
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::{Duration, Instant}; use std::time::Duration;
use std::{io, mem, net}; use std::{io, mem, net};
use actix_rt::net::TcpStream; use actix_rt::net::TcpStream;
use actix_rt::{spawn, time::delay, Arbiter, System}; use actix_rt::time::{delay_until, Instant};
use actix_rt::{spawn, System};
use futures::channel::mpsc::{unbounded, UnboundedReceiver}; use futures::channel::mpsc::{unbounded, UnboundedReceiver};
use futures::channel::oneshot; use futures::channel::oneshot;
use futures::future::ready; use futures::future::ready;
@ -305,22 +306,11 @@ impl ServerBuilder {
} }
fn start_worker(&self, idx: usize, notify: AcceptNotify) -> WorkerClient { fn start_worker(&self, idx: usize, notify: AcceptNotify) -> WorkerClient {
let (tx1, rx1) = unbounded();
let (tx2, rx2) = unbounded();
let timeout = self.shutdown_timeout;
let avail = WorkerAvailability::new(notify); let avail = WorkerAvailability::new(notify);
let worker = WorkerClient::new(idx, tx1, tx2, avail.clone());
let services: Vec<Box<dyn InternalServiceFactory>> = let services: Vec<Box<dyn InternalServiceFactory>> =
self.services.iter().map(|v| v.clone_factory()).collect(); self.services.iter().map(|v| v.clone_factory()).collect();
Arbiter::new().send( Worker::start(idx, services, avail, self.shutdown_timeout)
async move {
Worker::start(rx1, rx2, services, avail, timeout);
}
.boxed(),
);
worker
} }
fn handle_cmd(&mut self, item: ServerCommand) { fn handle_cmd(&mut self, item: ServerCommand) {
@ -395,8 +385,10 @@ impl ServerBuilder {
if exit { if exit {
spawn( spawn(
async { async {
delay(Instant::now() + Duration::from_millis(300)) delay_until(
.await; Instant::now() + Duration::from_millis(300),
)
.await;
System::current().stop(); System::current().stop();
} }
.boxed(), .boxed(),
@ -409,10 +401,12 @@ impl ServerBuilder {
// we need to stop system if server was spawned // we need to stop system if server was spawned
if self.exit { if self.exit {
spawn( spawn(
delay(Instant::now() + Duration::from_millis(300)).then(|_| { delay_until(Instant::now() + Duration::from_millis(300)).then(
System::current().stop(); |_| {
ready(()) System::current().stop();
}), ready(())
},
),
); );
} }
if let Some(tx) = completion { if let Some(tx) = completion {

View File

@ -3,7 +3,7 @@ use std::io;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use futures_core::stream::Stream; use futures::future::lazy;
use crate::server::Server; use crate::server::Server;
@ -33,11 +33,13 @@ pub(crate) struct Signals {
impl Signals { impl Signals {
pub(crate) fn start(srv: Server) -> io::Result<()> { pub(crate) fn start(srv: Server) -> io::Result<()> {
actix_rt::spawn({ actix_rt::spawn(lazy(|_| {
#[cfg(not(unix))] #[cfg(not(unix))]
{ {
let stream = actix_rt::signal::ctrl_c()?; match actix_rt::signal::ctrl_c() {
Signals { srv, stream } Ok(stream) => actix_rt::spawn(Signals { srv, stream }),
Err(e) => log::error!("Can not initialize ctrl-c handler err: {}", e),
}
} }
#[cfg(unix)] #[cfg(unix)]
@ -54,12 +56,19 @@ impl Signals {
]; ];
for (kind, sig) in sig_map.iter() { for (kind, sig) in sig_map.iter() {
streams.push((*sig, unix::signal(*kind)?)); match unix::signal(*kind) {
Ok(stream) => streams.push((*sig, stream)),
Err(e) => log::error!(
"Can not initialize stream handler for {:?} err: {}",
sig,
e
),
}
} }
Signals { srv, streams } actix_rt::spawn(Signals { srv, streams })
} }
}); }));
Ok(()) Ok(())
} }
@ -81,7 +90,7 @@ impl Future for Signals {
{ {
for idx in 0..self.streams.len() { for idx in 0..self.streams.len() {
loop { loop {
match Pin::new(&mut self.streams[idx].1).poll_next(cx) { match self.streams[idx].1.poll_recv(cx) {
Poll::Ready(None) => return Poll::Ready(()), Poll::Ready(None) => return Poll::Ready(()),
Poll::Pending => break, Poll::Pending => break,
Poll::Ready(Some(_)) => { Poll::Ready(Some(_)) => {

View File

@ -3,8 +3,6 @@ use std::{fmt, io, net};
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_rt::net::TcpStream; use actix_rt::net::TcpStream;
use tokio_net::driver::Handle;
pub(crate) enum StdListener { pub(crate) enum StdListener {
Tcp(net::TcpListener), Tcp(net::TcpListener),
#[cfg(all(unix))] #[cfg(all(unix))]
@ -152,7 +150,7 @@ pub trait FromStream: AsyncRead + AsyncWrite + Sized {
impl FromStream for TcpStream { impl FromStream for TcpStream {
fn from_stdstream(sock: StdStream) -> io::Result<Self> { fn from_stdstream(sock: StdStream) -> io::Result<Self> {
match sock { match sock {
StdStream::Tcp(stream) => TcpStream::from_std(stream, &Handle::default()), StdStream::Tcp(stream) => TcpStream::from_std(stream),
#[cfg(all(unix))] #[cfg(all(unix))]
StdStream::Uds(_) => { StdStream::Uds(_) => {
panic!("Should not happen, bug in server impl"); panic!("Should not happen, bug in server impl");
@ -166,9 +164,7 @@ impl FromStream for actix_rt::net::UnixStream {
fn from_stdstream(sock: StdStream) -> io::Result<Self> { fn from_stdstream(sock: StdStream) -> io::Result<Self> {
match sock { match sock {
StdStream::Tcp(_) => panic!("Should not happen, bug in server impl"), StdStream::Tcp(_) => panic!("Should not happen, bug in server impl"),
StdStream::Uds(stream) => { StdStream::Uds(stream) => actix_rt::net::UnixStream::from_std(stream),
actix_rt::net::UnixStream::from_std(stream, &Handle::default())
}
} }
} }
} }

View File

@ -4,10 +4,10 @@ use std::sync::Arc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time; use std::time;
use actix_rt::time::{delay, Delay}; use actix_rt::time::{delay_until, Delay, Instant};
use actix_rt::{spawn, Arbiter}; use actix_rt::{spawn, Arbiter};
use actix_utils::counter::Counter; use actix_utils::counter::Counter;
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
use futures::channel::oneshot; use futures::channel::oneshot;
use futures::future::{join_all, LocalBoxFuture, MapOk}; use futures::future::{join_all, LocalBoxFuture, MapOk};
use futures::{Future, FutureExt, Stream, TryFutureExt}; use futures::{Future, FutureExt, Stream, TryFutureExt};
@ -161,56 +161,66 @@ enum WorkerServiceStatus {
impl Worker { impl Worker {
pub(crate) fn start( pub(crate) fn start(
rx: UnboundedReceiver<WorkerCommand>, idx: usize,
rx2: UnboundedReceiver<StopCommand>,
factories: Vec<Box<dyn InternalServiceFactory>>, factories: Vec<Box<dyn InternalServiceFactory>>,
availability: WorkerAvailability, availability: WorkerAvailability,
shutdown_timeout: time::Duration, shutdown_timeout: time::Duration,
) { ) -> WorkerClient {
availability.set(false); let (tx1, rx) = unbounded();
let mut wrk = MAX_CONNS_COUNTER.with(|conns| Worker { let (tx2, rx2) = unbounded();
rx, let avail = availability.clone();
rx2,
availability,
factories,
shutdown_timeout,
services: Vec::new(),
conns: conns.clone(),
state: WorkerState::Unavailable(Vec::new()),
});
let mut fut: Vec<MapOk<LocalBoxFuture<'static, _>, _>> = Vec::new(); Arbiter::new().send(
for (idx, factory) in wrk.factories.iter().enumerate() { async move {
fut.push(factory.create().map_ok(move |r| { availability.set(false);
r.into_iter() let mut wrk = MAX_CONNS_COUNTER.with(move |conns| Worker {
.map(|(t, s): (Token, _)| (idx, t, s)) rx,
.collect::<Vec<_>>() rx2,
})); availability,
} factories,
shutdown_timeout,
services: Vec::new(),
conns: conns.clone(),
state: WorkerState::Unavailable(Vec::new()),
});
spawn(async move { let mut fut: Vec<MapOk<LocalBoxFuture<'static, _>, _>> = Vec::new();
let res = join_all(fut).await; for (idx, factory) in wrk.factories.iter().enumerate() {
let res: Result<Vec<_>, _> = res.into_iter().collect(); fut.push(factory.create().map_ok(move |r| {
match res { r.into_iter()
Ok(services) => { .map(|(t, s): (Token, _)| (idx, t, s))
for item in services { .collect::<Vec<_>>()
for (factory, token, service) in item { }));
assert_eq!(token.0, wrk.services.len()); }
wrk.services.push(WorkerService {
factory, spawn(async move {
service, let res = join_all(fut).await;
status: WorkerServiceStatus::Unavailable, let res: Result<Vec<_>, _> = res.into_iter().collect();
}); match res {
Ok(services) => {
for item in services {
for (factory, token, service) in item {
assert_eq!(token.0, wrk.services.len());
wrk.services.push(WorkerService {
factory,
service,
status: WorkerServiceStatus::Unavailable,
});
}
}
}
Err(e) => {
error!("Can not start worker: {:?}", e);
Arbiter::current().stop();
} }
} }
} wrk.await
Err(e) => { });
error!("Can not start worker: {:?}", e);
Arbiter::current().stop();
}
} }
wrk.await .boxed(),
}); );
WorkerClient::new(idx, tx1, tx2, avail)
} }
fn shutdown(&mut self, force: bool) { fn shutdown(&mut self, force: bool) {
@ -322,8 +332,8 @@ impl Future for Worker {
if num != 0 { if num != 0 {
info!("Graceful worker shutdown, {} connections", num); info!("Graceful worker shutdown, {} connections", num);
self.state = WorkerState::Shutdown( self.state = WorkerState::Shutdown(
Box::pin(delay(time::Instant::now() + time::Duration::from_secs(1))), Box::pin(delay_until(Instant::now() + time::Duration::from_secs(1))),
Box::pin(delay(time::Instant::now() + self.shutdown_timeout)), Box::pin(delay_until(Instant::now() + self.shutdown_timeout)),
Some(result), Some(result),
); );
} else { } else {
@ -399,7 +409,6 @@ impl Future for Worker {
); );
} }
Poll::Pending => { Poll::Pending => {
// self.state = WorkerState::Restarting(idx, token, fut);
return Poll::Pending; return Poll::Pending;
} }
} }
@ -428,19 +437,18 @@ impl Future for Worker {
match t1.as_mut().poll(cx) { match t1.as_mut().poll(cx) {
Poll::Pending => (), Poll::Pending => (),
Poll::Ready(_) => { Poll::Ready(_) => {
*t1 = Box::pin(delay( *t1 = Box::pin(delay_until(
time::Instant::now() + time::Duration::from_secs(1), Instant::now() + time::Duration::from_secs(1),
)); ));
let _ = t1.as_mut().poll(cx); let _ = t1.as_mut().poll(cx);
} }
} }
// self.state = WorkerState::Shutdown(t1, t2, tx);
Poll::Pending Poll::Pending
} }
WorkerState::Available => { WorkerState::Available => {
loop { loop {
match Pin::new(&mut self.rx).poll_next(cx) { match Pin::new(&mut self.rx).poll_next(cx) {
// handle incoming tcp stream // handle incoming io stream
Poll::Ready(Some(WorkerCommand(msg))) => { Poll::Ready(Some(WorkerCommand(msg))) => {
match self.check_readiness(cx) { match self.check_readiness(cx) {
Ok(true) => { Ok(true) => {

View File

@ -29,6 +29,8 @@ fn test_bind() {
let h = thread::spawn(move || { let h = thread::spawn(move || {
let sys = actix_rt::System::new("test"); let sys = actix_rt::System::new("test");
let srv = Server::build() let srv = Server::build()
.workers(1)
.disable_signals()
.bind("test", addr, move || service_fn(|_| ok::<_, ()>(()))) .bind("test", addr, move || service_fn(|_| ok::<_, ()>(())))
.unwrap() .unwrap()
.start(); .start();
@ -51,14 +53,16 @@ fn test_listen() {
let h = thread::spawn(move || { let h = thread::spawn(move || {
let sys = actix_rt::System::new("test"); let sys = actix_rt::System::new("test");
let lst = net::TcpListener::bind(addr).unwrap(); let lst = net::TcpListener::bind(addr).unwrap();
let srv = Server::build() Server::build()
.disable_signals()
.workers(1)
.listen("test", lst, move || service_fn(|_| ok::<_, ()>(()))) .listen("test", lst, move || service_fn(|_| ok::<_, ()>(())))
.unwrap() .unwrap()
.start(); .start();
let _ = tx.send((srv, actix_rt::System::current())); let _ = tx.send(actix_rt::System::current());
let _ = sys.run(); let _ = sys.run();
}); });
let (_, sys) = rx.recv().unwrap(); let sys = rx.recv().unwrap();
thread::sleep(time::Duration::from_millis(500)); thread::sleep(time::Duration::from_millis(500));
assert!(net::TcpStream::connect(addr).is_ok()); assert!(net::TcpStream::connect(addr).is_ok());
@ -72,10 +76,12 @@ fn test_start() {
let addr = unused_addr(); let addr = unused_addr();
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let h = thread::spawn(move || { let _ = thread::spawn(move || {
let sys = actix_rt::System::new("test"); let sys = actix_rt::System::new("test");
let srv: Server = Server::build() let srv: Server = Server::build()
.backlog(100) .backlog(100)
.workers(1)
.disable_signals()
.bind("test", addr, move || { .bind("test", addr, move || {
service_fn(|io: TcpStream| { service_fn(|io: TcpStream| {
async move { async move {
@ -126,7 +132,7 @@ fn test_start() {
thread::sleep(time::Duration::from_millis(100)); thread::sleep(time::Duration::from_millis(100));
let _ = sys.stop(); let _ = sys.stop();
let _ = h.join(); // let _ = h.join();
} }
#[test] #[test]
@ -142,6 +148,7 @@ fn test_configure() {
let num = num2.clone(); let num = num2.clone();
let sys = actix_rt::System::new("test"); let sys = actix_rt::System::new("test");
let srv = Server::build() let srv = Server::build()
.disable_signals()
.configure(move |cfg| { .configure(move |cfg| {
let num = num.clone(); let num = num.clone();
let lst = net::TcpListener::bind(addr3).unwrap(); let lst = net::TcpListener::bind(addr3).unwrap();

View File

@ -1,5 +1,9 @@
# Changes # Changes
## [1.0.0-alpha.3] - 2019-12-xx
* Migrate to `tokio=0.2.2`
## [1.0.0-alpha.2] - 2019-12-02 ## [1.0.0-alpha.2] - 2019-12-02
* Re-export `test` attribute macros * Re-export `test` attribute macros

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-testing" name = "actix-testing"
version = "1.0.0-alpha.2" version = "1.0.0-alpha.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix testing utils" description = "Actix testing utils"
keywords = ["network", "framework", "async", "futures"] keywords = ["network", "framework", "async", "futures"]
@ -17,13 +17,11 @@ name = "actix_testing"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
actix-rt = "1.0.0-alpha.2" actix-rt = "1.0.0-alpha.3"
actix-macros = "0.1.0-alpha.1" actix-macros = "0.1.0-alpha.1"
actix-server = "1.0.0-alpha.2" actix-server = "1.0.0-alpha.3"
actix-service = "1.0.0-alpha.3" actix-service = "1.0.0-alpha.3"
log = "0.4" log = "0.4"
net2 = "0.2" net2 = "0.2"
futures = "0.3.1" futures = "0.3.1"
tokio-net = { version = "=0.2.0-alpha.6" }

View File

@ -7,9 +7,7 @@ use std::{net, thread};
use actix_rt::{net::TcpStream, System}; use actix_rt::{net::TcpStream, System};
use actix_server::{Server, ServerBuilder, ServiceFactory}; use actix_server::{Server, ServerBuilder, ServiceFactory};
use net2::TcpBuilder; use net2::TcpBuilder;
use tokio_net::driver::Handle;
#[cfg(not(test))] // Work around for rust-lang/rust#62127 #[cfg(not(test))] // Work around for rust-lang/rust#62127
pub use actix_macros::test; pub use actix_macros::test;
@ -25,7 +23,8 @@ pub use actix_macros::test;
/// use actix_service::{service_fn}; /// use actix_service::{service_fn};
/// use actix_testing::TestServer; /// use actix_testing::TestServer;
/// ///
/// fn main() { /// #[actix_rt::main]
/// async fn main() {
/// let srv = TestServer::with(|| service_fn( /// let srv = TestServer::with(|| service_fn(
/// |sock| async move { /// |sock| async move {
/// println!("New connection: {:?}", sock); /// println!("New connection: {:?}", sock);
@ -142,7 +141,7 @@ impl TestServerRuntime {
/// Connect to server, return tokio TcpStream /// Connect to server, return tokio TcpStream
pub fn connect(&self) -> std::io::Result<TcpStream> { pub fn connect(&self) -> std::io::Result<TcpStream> {
TcpStream::from_std(net::TcpStream::connect(self.addr)?, &Handle::default()) TcpStream::from_std(net::TcpStream::connect(self.addr)?)
} }
} }

View File

@ -1,5 +1,13 @@
# Changes # Changes
[1.0.0-alpha.3] - 2019-12-xx
### Changed
* Migrate to `tokio=0.2.2`
* Enable rustls acceptor service
## [1.0.0-alpha.1] - 2019-12-02 ## [1.0.0-alpha.1] - 2019-12-02
* Split openssl accetor from actix-server package * Split openssl accetor from actix-server package

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-tls" name = "actix-tls"
version = "1.0.0-alpha.1" version = "1.0.0-alpha.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix tls services" description = "Actix tls services"
keywords = ["network", "framework", "async", "futures"] keywords = ["network", "framework", "async", "futures"]
@ -30,9 +30,9 @@ rustls = ["rust-tls", "webpki"]
[dependencies] [dependencies]
actix-service = "1.0.0-alpha.3" actix-service = "1.0.0-alpha.3"
actix-codec = "0.2.0-alpha.2" actix-codec = "0.2.0-alpha.3"
actix-utils = "1.0.0-alpha.2" actix-utils = "1.0.0-alpha.3"
actix-rt = "1.0.0-alpha.2" actix-rt = "1.0.0-alpha.3"
derive_more = "0.99.2" derive_more = "0.99.2"
either = "1.5.2" either = "1.5.2"
futures = "0.3.1" futures = "0.3.1"
@ -40,15 +40,14 @@ log = "0.4"
# openssl # openssl
open-ssl = { version="0.10", package = "openssl", optional = true } open-ssl = { version="0.10", package = "openssl", optional = true }
tokio-openssl = { version = "=0.4.0-alpha.6", optional = true } tokio-openssl = { version = "0.4.0", optional = true }
# rustls # rustls
rust-tls = { version = "0.16.0", package = "rustls", optional = true } rust-tls = { version = "0.16.0", package = "rustls", optional = true }
webpki = { version = "0.21", optional = true } webpki = { version = "0.21", optional = true }
webpki-roots = { version = "0.17", optional = true } webpki-roots = { version = "0.17", optional = true }
# tokio-rustls = { version = "0.12.0-alpha.2", optional = true } tokio-rustls = { version = "0.12.0", optional = true }
# tokio-rustls = { git = "https://github.com/quininer/tokio-rustls.git", branch = "tokio-0.2", optional = true }
[dev-dependencies] [dev-dependencies]
bytes = "0.4" bytes = "0.5"
actix-testing = { version="1.0.0-alpha.2" } actix-testing = { version="1.0.0-alpha.3" }

View File

@ -2,6 +2,8 @@
## [1.0.0-alpha.3] - 2019-12-xx ## [1.0.0-alpha.3] - 2019-12-xx
* Migrate to `tokio=0.2.2`
* Fix oneshot * Fix oneshot
## [1.0.0-alpha.2] - 2019-12-02 ## [1.0.0-alpha.2] - 2019-12-02

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-utils" name = "actix-utils"
version = "1.0.0-alpha.2" version = "1.0.0-alpha.3"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix utils - various actix net related services" description = "Actix utils - various actix net related services"
keywords = ["network", "framework", "async", "futures"] keywords = ["network", "framework", "async", "futures"]
@ -19,9 +19,9 @@ path = "src/lib.rs"
[dependencies] [dependencies]
actix-service = "1.0.0-alpha.3" actix-service = "1.0.0-alpha.3"
actix-rt = "1.0.0-alpha.2" actix-rt = "1.0.0-alpha.3"
actix-codec = "0.2.0-alpha.2" actix-codec = "0.2.0-alpha.3"
bytes = "0.4" bytes = "0.5.2"
either = "1.5.2" either = "1.5.2"
futures = "0.3.1" futures = "0.3.1"
pin-project = "0.4.6" pin-project = "0.4.6"

View File

@ -3,9 +3,9 @@ use std::future::Future;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::{Duration, Instant}; use std::time::Duration;
use actix_rt::time::{delay, Delay}; use actix_rt::time::{delay_until, Delay, Instant};
use actix_service::{Service, ServiceFactory}; use actix_service::{Service, ServiceFactory};
use futures::future::{ok, Ready}; use futures::future::{ok, Ready};
@ -81,13 +81,13 @@ where
F: Fn() -> E, F: Fn() -> E,
{ {
pub fn new(ka: Duration, time: LowResTimeService, f: F) -> Self { pub fn new(ka: Duration, time: LowResTimeService, f: F) -> Self {
let expire = time.now() + ka; let expire = Instant::from_std(time.now() + ka);
KeepAliveService { KeepAliveService {
f, f,
ka, ka,
time, time,
expire, expire,
delay: delay(expire), delay: delay_until(expire),
_t: PhantomData, _t: PhantomData,
} }
} }
@ -105,7 +105,7 @@ where
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
match Pin::new(&mut self.delay).poll(cx) { match Pin::new(&mut self.delay).poll(cx) {
Poll::Ready(_) => { Poll::Ready(_) => {
let now = self.time.now(); let now = Instant::from_std(self.time.now());
if self.expire <= now { if self.expire <= now {
Poll::Ready(Err((self.f)())) Poll::Ready(Err((self.f)()))
} else { } else {
@ -119,7 +119,7 @@ where
} }
fn call(&mut self, req: R) -> Self::Future { fn call(&mut self, req: R) -> Self::Future {
self.expire = self.time.now() + self.ka; self.expire = Instant::from_std(self.time.now() + self.ka);
ok(req) ok(req)
} }
} }

View File

@ -1,5 +1,11 @@
# Changes # Changes
## [0.2.0] - 2019-12-05
* Update http to 0.2
* Update regex to 1.3
## [0.1.5] - 2019-05-15 ## [0.1.5] - 2019-05-15
* Remove debug prints * Remove debug prints

View File

@ -1,6 +1,6 @@
[package] [package]
name = "actix-router" name = "actix-router"
version = "0.1.5" version = "0.2.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Path router" description = "Path router"
keywords = ["actix"] keywords = ["actix"]
@ -20,13 +20,12 @@ path = "src/lib.rs"
default = ["http"] default = ["http"]
[dependencies] [dependencies]
bytes = "0.4" regex = "1.3.1"
regex = "1.0"
serde = "1.0.80" serde = "1.0.80"
string = "0.2.0" string = "0.2.1"
log = "0.4" log = "0.4.8"
http = { version="0.1.14", optional=true } http = { version="0.2.0", optional=true }
[dev-dependencies] [dev-dependencies]
http = "0.1.14" http = "0.2.0"
serde_derive = "1.0" serde_derive = "1.0"

View File

@ -491,7 +491,8 @@ pub(crate) fn insert_slash(path: &str) -> String {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use http::{HttpTryFrom, Uri}; use http::Uri;
use std::convert::TryFrom;
#[test] #[test]
fn test_parse_static() { fn test_parse_static() {

View File

@ -200,7 +200,8 @@ fn restore_ch(d1: u8, d2: u8) -> Option<u8> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use http::{HttpTryFrom, Uri}; use http::Uri;
use std::convert::TryFrom;
use super::*; use super::*;
use crate::{Path, ResourceDef}; use crate::{Path, ResourceDef};