diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index a8615de8..7c76e171 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v2 - name: Install Rust uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 610c549a..3e77e990 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: version: - - 1.39.0 + - 1.42.0 - stable - nightly @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v2 - name: Install ${{ matrix.version }} uses: actions-rs/toolchain@v1 @@ -65,7 +65,7 @@ jobs: - name: Generate coverage file if: matrix.version == 'stable' && (github.ref == 'refs/heads/master' || github.event_name == 'pull_request') run: | - which cargo-tarpaulin || cargo install cargo-tarpaulin + cargo install cargo-tarpaulin cargo tarpaulin --out Xml --workspace --all-features - name: Upload to Codecov @@ -76,5 +76,7 @@ jobs: - name: Clear the cargo caches run: | - which cargo-cache || cargo install cargo-cache --no-default-features --features ci-autoclean + rustup update stable + rustup override set stable + cargo install cargo-cache --no-default-features --features ci-autoclean cargo-cache diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 87c87b88..98788274 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -21,7 +21,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v2 - name: Install ${{ matrix.version }} uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/windows-mingw.yml b/.github/workflows/windows-mingw.yml index b41d32cc..b83d251b 100644 --- a/.github/workflows/windows-mingw.yml +++ b/.github/workflows/windows-mingw.yml @@ -21,7 +21,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v2 - name: Install ${{ matrix.version }} uses: actions-rs/toolchain@v1 @@ -31,12 +31,12 @@ jobs: override: true - name: Install MSYS2 - uses: numworks/setup-msys2@v1 + uses: msys2/setup-msys2@v2 - name: Install packages run: | - msys2do pacman -Sy --noconfirm pacman - msys2do pacman --noconfirm -S base-devel pkg-config + msys2 -c 'pacman -Sy --noconfirm pacman' + msys2 -c 'pacman --noconfirm -S base-devel pkg-config' - name: check build uses: actions-rs/cargo@v1 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e0de16cc..a319fd65 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -27,7 +27,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v2 - name: Install ${{ matrix.version }} uses: actions-rs/toolchain@v1 diff --git a/README.md b/README.md index b291fd13..827f937f 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ Actix net - framework for composable network services ## Documentation & community resources -* [Chat on gitter](https://gitter.im/actix/actix) -* Minimum supported Rust version: 1.39 or later +* [Chat on Gitter](https://gitter.im/actix/actix) +* Minimum supported Rust version: 1.42 or later ## Example diff --git a/actix-codec/CHANGES.md b/actix-codec/CHANGES.md index aa873992..c8b7fbe3 100644 --- a/actix-codec/CHANGES.md +++ b/actix-codec/CHANGES.md @@ -1,10 +1,21 @@ # Changes ## Unreleased - 2020-xx-xx + +## 0.3.0 - 2020-08-23 +* No changes from beta 2. + +## 0.3.0-beta.2 - 2020-08-19 +* Remove unused type parameter from `Framed::replace_codec`. + +## 0.3.0-beta.1 - 2020-08-19 * Use `.advance()` instead of `.split_to()`. * Upgrade `tokio-util` to `0.3`. * Improve `BytesCodec` `.encode()` performance * Simplify `BytesCodec` `.decode()` +* Rename methods on `Framed` to better describe their use. +* Add method on `Framed` to get a pinned reference to the underlying I/O. +* Add method on `Framed` check emptiness of read buffer. ## [0.2.0] - 2019-12-10 diff --git a/actix-codec/Cargo.toml b/actix-codec/Cargo.toml index 8b14dd70..f834fdaf 100644 --- a/actix-codec/Cargo.toml +++ b/actix-codec/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "actix-codec" -version = "0.2.0" +version = "0.3.0" authors = ["Nikolay Kim "] -description = "Utilities for encoding and decoding frames" +description = "Codec utilities for working with framed protocols." keywords = ["network", "framework", "async", "futures"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-net.git" @@ -10,7 +10,6 @@ documentation = "https://docs.rs/actix-codec/" categories = ["network-programming", "asynchronous"] license = "MIT OR Apache-2.0" edition = "2018" -workspace = ".." [lib] name = "actix_codec" @@ -21,7 +20,7 @@ bitflags = "1.2.1" bytes = "0.5.2" futures-core = { version = "0.3.4", default-features = false } futures-sink = { version = "0.3.4", default-features = false } -tokio = { version = "0.2.5", default-features = false } -tokio-util = { version = "0.3.1", default-features = false, features = ["codec"] } log = "0.4" pin-project = "0.4.17" +tokio = { version = "0.2.5", default-features = false } +tokio-util = { version = "0.3.1", default-features = false, features = ["codec"] } diff --git a/actix-codec/src/framed.rs b/actix-codec/src/framed.rs index bfa5c7b6..844f20d8 100644 --- a/actix-codec/src/framed.rs +++ b/actix-codec/src/framed.rs @@ -23,6 +23,12 @@ bitflags::bitflags! { /// A unified `Stream` and `Sink` interface to an underlying I/O object, using /// the `Encoder` and `Decoder` traits to encode and decode frames. +/// +/// Raw I/O objects work with byte sequences, but higher-level code usually +/// wants to batch these into meaningful chunks, called "frames". This +/// method layers framing on top of an I/O object, by using the `Encoder`/`Decoder` +/// traits to handle encoding and decoding of message frames. Note that +/// the incoming and outgoing frame types may be distinct. #[pin_project] pub struct Framed { #[pin] @@ -38,15 +44,6 @@ where T: AsyncRead + AsyncWrite, U: Decoder, { - /// Provides a `Stream` and `Sink` interface for reading and writing to this - /// `Io` object, using `Decode` and `Encode` to read and write the raw data. - /// - /// Raw I/O objects work with byte sequences, but higher-level code usually - /// wants to batch these into meaningful chunks, called "frames". This - /// method layers framing on top of an I/O object, by using the `Codec` - /// traits to handle encoding and decoding of messages frames. Note that - /// the incoming and outgoing frame types may be distinct. - /// /// This function returns a *single* object that is both `Stream` and /// `Sink`; grouping this into a single object is often useful for layering /// things like gzip or TLS, which require both read and write access to the @@ -63,40 +60,13 @@ where } impl Framed { - /// Provides a `Stream` and `Sink` interface for reading and writing to this - /// `Io` object, using `Decode` and `Encode` to read and write the raw data. - /// - /// Raw I/O objects work with byte sequences, but higher-level code usually - /// wants to batch these into meaningful chunks, called "frames". This - /// method layers framing on top of an I/O object, by using the `Codec` - /// traits to handle encoding and decoding of messages frames. Note that - /// the incoming and outgoing frame types may be distinct. - /// - /// This function returns a *single* object that is both `Stream` and - /// `Sink`; grouping this into a single object is often useful for layering - /// things like gzip or TLS, which require both read and write access to the - /// underlying object. - /// - /// This objects takes a stream and a readbuffer and a writebuffer. These - /// field can be obtained from an existing `Framed` with the - /// `into_parts` method. - pub fn from_parts(parts: FramedParts) -> Framed { - Framed { - io: parts.io, - codec: parts.codec, - flags: parts.flags, - write_buf: parts.write_buf, - read_buf: parts.read_buf, - } - } - /// Returns a reference to the underlying codec. - pub fn get_codec(&self) -> &U { + pub fn codec_ref(&self) -> &U { &self.codec } /// Returns a mutable reference to the underlying codec. - pub fn get_codec_mut(&mut self) -> &mut U { + pub fn codec_mut(&mut self) -> &mut U { &mut self.codec } @@ -106,20 +76,29 @@ impl Framed { /// Note that care should be taken to not tamper with the underlying stream /// of data coming in as it may corrupt the stream of frames otherwise /// being worked with. - pub fn get_ref(&self) -> &T { + pub fn io_ref(&self) -> &T { &self.io } - /// Returns a mutable reference to the underlying I/O stream wrapped by - /// `Frame`. + /// Returns a mutable reference to the underlying I/O stream. /// /// Note that care should be taken to not tamper with the underlying stream /// of data coming in as it may corrupt the stream of frames otherwise /// being worked with. - pub fn get_mut(&mut self) -> &mut T { + pub fn io_mut(&mut self) -> &mut T { &mut self.io } + /// Returns a `Pin` of a mutable reference to the underlying I/O stream. + pub fn io_pin(self: Pin<&mut Self>) -> Pin<&mut T> { + self.project().io + } + + /// Check if read buffer is empty. + pub fn is_read_buf_empty(&self) -> bool { + self.read_buf.is_empty() + } + /// Check if write buffer is empty. pub fn is_write_buf_empty(&self) -> bool { self.write_buf.is_empty() @@ -130,8 +109,15 @@ impl Framed { self.write_buf.len() >= HW } + /// Check if framed is able to write more data. + /// + /// `Framed` object considers ready if there is free space in write buffer. + pub fn is_write_ready(&self) -> bool { + self.write_buf.len() < HW + } + /// Consume the `Frame`, returning `Frame` with different codec. - pub fn into_framed(self, codec: U2) -> Framed { + pub fn replace_codec(self, codec: U2) -> Framed { Framed { codec, io: self.io, @@ -142,7 +128,7 @@ impl Framed { } /// Consume the `Frame`, returning `Frame` with different io. - pub fn map_io(self, f: F) -> Framed + pub fn into_map_io(self, f: F) -> Framed where F: Fn(T) -> T2, { @@ -156,7 +142,7 @@ impl Framed { } /// Consume the `Frame`, returning `Frame` with different codec. - pub fn map_codec(self, f: F) -> Framed + pub fn into_map_codec(self, f: F) -> Framed where F: Fn(U) -> U2, { @@ -168,22 +154,6 @@ impl Framed { write_buf: self.write_buf, } } - - /// Consumes the `Frame`, returning its underlying I/O stream, the buffer - /// with unprocessed data, and the codec. - /// - /// Note that care should be taken to not tamper with the underlying stream - /// of data coming in as it may corrupt the stream of frames otherwise - /// being worked with. - pub fn into_parts(self) -> FramedParts { - FramedParts { - io: self.io, - codec: self.codec, - flags: self.flags, - read_buf: self.read_buf, - write_buf: self.write_buf, - } - } } impl Framed { @@ -203,13 +173,6 @@ impl Framed { Ok(()) } - /// Check if framed is able to write more data. - /// - /// `Framed` object considers ready if there is free space in write buffer. - pub fn is_write_ready(&self) -> bool { - self.write_buf.len() < HW - } - /// Try to read underlying I/O stream and decode item. pub fn next_item( mut self: Pin<&mut Self>, @@ -376,6 +339,41 @@ where } } +impl Framed { + /// This function returns a *single* object that is both `Stream` and + /// `Sink`; grouping this into a single object is often useful for layering + /// things like gzip or TLS, which require both read and write access to the + /// underlying object. + /// + /// These objects take a stream, a read buffer and a write buffer. These + /// fields can be obtained from an existing `Framed` with the `into_parts` method. + pub fn from_parts(parts: FramedParts) -> Framed { + Framed { + io: parts.io, + codec: parts.codec, + flags: parts.flags, + write_buf: parts.write_buf, + read_buf: parts.read_buf, + } + } + + /// Consumes the `Frame`, returning its underlying I/O stream, the buffer + /// with unprocessed data, and the codec. + /// + /// Note that care should be taken to not tamper with the underlying stream + /// of data coming in as it may corrupt the stream of frames otherwise + /// being worked with. + pub fn into_parts(self) -> FramedParts { + FramedParts { + io: self.io, + codec: self.codec, + flags: self.flags, + read_buf: self.read_buf, + write_buf: self.write_buf, + } + } +} + /// `FramedParts` contains an export of the data of a Framed transport. /// It can be used to construct a new `Framed` with a different codec. /// It contains all current buffers and the inner transport. diff --git a/actix-codec/src/lib.rs b/actix-codec/src/lib.rs index 3035be13..d972763e 100644 --- a/actix-codec/src/lib.rs +++ b/actix-codec/src/lib.rs @@ -8,7 +8,9 @@ //! [`AsyncWrite`]: AsyncWrite //! [`Sink`]: futures_sink::Sink //! [`Stream`]: futures_core::Stream + #![deny(rust_2018_idioms)] +#![warn(missing_docs)] mod bcodec; mod framed; diff --git a/actix-connect/CHANGES.md b/actix-connect/CHANGES.md index d921acac..dd829518 100644 --- a/actix-connect/CHANGES.md +++ b/actix-connect/CHANGES.md @@ -1,12 +1,16 @@ # Changes -## [unreleased] +## Unreleased + + +## 2.0.0-alpha.4 - 2020-08-17 ### Changed * Update `rustls` dependency to 0.18 * Update `tokio-rustls` dependency to 0.14 + ## [2.0.0-alpha.3] - 2020-05-08 ### Fixed diff --git a/actix-connect/Cargo.toml b/actix-connect/Cargo.toml index 617421b4..233195c5 100644 --- a/actix-connect/Cargo.toml +++ b/actix-connect/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "actix-connect" -version = "2.0.0-alpha.3" +version = "2.0.0" authors = ["Nikolay Kim "] -description = "Actix connect - tcp connector service" +description = "TCP connector service for Actix ecosystem." keywords = ["network", "framework", "async", "futures"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-net.git" @@ -31,10 +31,11 @@ rustls = ["rust-tls", "tokio-rustls", "webpki"] uri = ["http"] [dependencies] -actix-service = "1.0.3" -actix-codec = "0.2.0" -actix-utils = "1.0.6" -actix-rt = "1.0.0" +actix-service = "1.0.6" +actix-codec = "0.3.0" +actix-utils = "2.0.0" +actix-rt = "1.1.1" + derive_more = "0.99.2" either = "1.5.3" futures-util = { version = "0.3.4", default-features = false } @@ -44,14 +45,14 @@ trust-dns-proto = { version = "0.19", default-features = false, features = ["tok trust-dns-resolver = { version = "0.19", default-features = false, features = ["tokio-runtime", "system-config"] } # openssl -open-ssl = { version="0.10", package = "openssl", optional = true } +open-ssl = { package = "openssl", version = "0.10", optional = true } tokio-openssl = { version = "0.4.0", optional = true } # rustls -rust-tls = { version = "0.18.0", package = "rustls", optional = true } +rust-tls = { package = "rustls", version = "0.18.0", optional = true } tokio-rustls = { version = "0.14.0", optional = true } webpki = { version = "0.21", optional = true } [dev-dependencies] bytes = "0.5.3" -actix-testing = { version="1.0.0" } +actix-testing = "1.0.0" diff --git a/actix-connect/src/connect.rs b/actix-connect/src/connect.rs index f4f7f6b7..7d5531e5 100644 --- a/actix-connect/src/connect.rs +++ b/actix-connect/src/connect.rs @@ -43,7 +43,7 @@ pub struct Connect { } impl Connect { - /// Create `Connect` instance by spliting the string by ':' and convert the second part to u16 + /// Create `Connect` instance by splitting the string by ':' and convert the second part to u16 pub fn new(req: T) -> Connect { let (_, port) = parse(req.host()); Connect { @@ -53,7 +53,8 @@ impl Connect { } } - /// Create new `Connect` instance from host and address. Connector skips name resolution stage for such connect messages. + /// Create new `Connect` instance from host and address. Connector skips name resolution stage + /// for such connect messages. pub fn with(req: T, addr: SocketAddr) -> Connect { Connect { req, @@ -102,7 +103,7 @@ impl Connect { self.req.port().unwrap_or(self.port) } - /// Preresolved addresses of the request. + /// Pre-resolved addresses of the request. pub fn addrs(&self) -> ConnectAddrsIter<'_> { let inner = match self.addr { None => Either::Left(None), @@ -113,7 +114,7 @@ impl Connect { ConnectAddrsIter { inner } } - /// Takes preresolved addresses of the request. + /// Takes pre-resolved addresses of the request. pub fn take_addrs(&mut self) -> ConnectTakeAddrsIter { let inner = match self.addr.take() { None => Either::Left(None), diff --git a/actix-connect/src/connector.rs b/actix-connect/src/connector.rs index e9fb1525..9dc9a2ad 100644 --- a/actix-connect/src/connector.rs +++ b/actix-connect/src/connector.rs @@ -13,7 +13,7 @@ use futures_util::future::{err, ok, BoxFuture, Either, FutureExt, Ready}; use super::connect::{Address, Connect, Connection}; use super::error::ConnectError; -/// Tcp connector service factory +/// TCP connector service factory #[derive(Debug)] pub struct TcpConnectorFactory(PhantomData); @@ -22,7 +22,7 @@ impl TcpConnectorFactory { TcpConnectorFactory(PhantomData) } - /// Create tcp connector service + /// Create TCP connector service pub fn service(&self) -> TcpConnector { TcpConnector(PhantomData) } @@ -54,7 +54,7 @@ impl ServiceFactory for TcpConnectorFactory { } } -/// Tcp connector service +/// TCP connector service #[derive(Default, Debug)] pub struct TcpConnector(PhantomData); @@ -74,6 +74,7 @@ impl Service for TcpConnector { type Request = Connect; type Response = Connection; type Error = ConnectError; + #[allow(clippy::type_complexity)] type Future = Either, Ready>>; fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { @@ -94,7 +95,7 @@ impl Service for TcpConnector { } #[doc(hidden)] -/// Tcp stream connector response future +/// TCP stream connector response future pub struct TcpConnectorResponse { req: Option, port: u16, diff --git a/actix-connect/src/error.rs b/actix-connect/src/error.rs index 3c56f072..84b363dc 100644 --- a/actix-connect/src/error.rs +++ b/actix-connect/src/error.rs @@ -20,7 +20,7 @@ pub enum ConnectError { #[display(fmt = "Connector received `Connect` method with unresolved host")] Unresolved, - /// Connection io error + /// Connection IO error #[display(fmt = "{}", _0)] Io(io::Error), } diff --git a/actix-connect/src/lib.rs b/actix-connect/src/lib.rs index 85dcf99e..56e6a110 100644 --- a/actix-connect/src/lib.rs +++ b/actix-connect/src/lib.rs @@ -1,11 +1,11 @@ -//! Actix connect - tcp connector service +//! TCP connector service for Actix ecosystem. //! //! ## Package feature //! //! * `openssl` - enables ssl support via `openssl` crate //! * `rustls` - enables ssl support via `rustls` crate -#![deny(rust_2018_idioms, warnings)] -#![allow(clippy::type_complexity)] + +#![deny(rust_2018_idioms)] #![recursion_limit = "128"] #[macro_use] @@ -71,7 +71,7 @@ pub async fn start_default_resolver() -> Result { get_default_resolver().await } -/// Create tcp connector service +/// Create TCP connector service. pub fn new_connector( resolver: AsyncResolver, ) -> impl Service, Response = Connection, Error = ConnectError> @@ -79,7 +79,7 @@ pub fn new_connector( pipeline(Resolver::new(resolver)).and_then(TcpConnector::new()) } -/// Create tcp connector service +/// Create TCP connector service factory. pub fn new_connector_factory( resolver: AsyncResolver, ) -> impl ServiceFactory< @@ -92,14 +92,14 @@ pub fn new_connector_factory( pipeline_factory(ResolverFactory::new(resolver)).and_then(TcpConnectorFactory::new()) } -/// Create connector service with default parameters +/// Create connector service with default parameters. pub fn default_connector( ) -> impl Service, Response = Connection, Error = ConnectError> + Clone { pipeline(Resolver::default()).and_then(TcpConnector::new()) } -/// Create connector service factory with default parameters +/// Create connector service factory with default parameters. pub fn default_connector_factory() -> impl ServiceFactory< Config = (), Request = Connect, diff --git a/actix-connect/src/resolve.rs b/actix-connect/src/resolve.rs index faf68a19..bfb1482f 100644 --- a/actix-connect/src/resolve.rs +++ b/actix-connect/src/resolve.rs @@ -106,6 +106,7 @@ impl Service for Resolver { type Request = Connect; type Response = Connect; type Error = ConnectError; + #[allow(clippy::type_complexity)] type Future = Either< Pin>>>, Ready, Self::Error>>, diff --git a/actix-connect/src/service.rs b/actix-connect/src/service.rs index f337382b..1047e3df 100644 --- a/actix-connect/src/service.rs +++ b/actix-connect/src/service.rs @@ -114,6 +114,7 @@ enum ConnectState { } impl ConnectState { + #[allow(clippy::type_complexity)] fn poll( &mut self, cx: &mut Context<'_>, diff --git a/actix-connect/src/ssl/openssl.rs b/actix-connect/src/ssl/openssl.rs index 6858adbe..e1c6b6fb 100644 --- a/actix-connect/src/ssl/openssl.rs +++ b/actix-connect/src/ssl/openssl.rs @@ -17,7 +17,7 @@ use crate::{ Address, Connect, ConnectError, ConnectService, ConnectServiceFactory, Connection, }; -/// Openssl connector factory +/// OpenSSL connector factory pub struct OpensslConnector { connector: SslConnector, _t: PhantomData<(T, U)>, @@ -97,6 +97,7 @@ where type Request = Connection; type Response = Connection>; type Error = io::Error; + #[allow(clippy::type_complexity)] type Future = Either, Ready>>; fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { @@ -164,7 +165,7 @@ impl OpensslConnectServiceFactory { } } - /// Construct new connect service with custom dns resolver + /// Construct new connect service with custom DNS resolver pub fn with_resolver(connector: SslConnector, resolver: AsyncResolver) -> Self { OpensslConnectServiceFactory { tcp: ConnectServiceFactory::with_resolver(resolver), @@ -172,7 +173,7 @@ impl OpensslConnectServiceFactory { } } - /// Construct openssl connect service + /// Construct OpenSSL connect service pub fn service(&self) -> OpensslConnectService { OpensslConnectService { tcp: self.tcp.service(), diff --git a/actix-connect/tests/test_connect.rs b/actix-connect/tests/test_connect.rs index 549d559f..21d78d2c 100644 --- a/actix-connect/tests/test_connect.rs +++ b/actix-connect/tests/test_connect.rs @@ -88,9 +88,9 @@ async fn test_new_service() { assert_eq!(con.peer_addr().unwrap(), srv.addr()); } -#[cfg(feature = "openssl")] +#[cfg(all(feature = "openssl", feature = "uri"))] #[actix_rt::test] -async fn test_uri() { +async fn test_openssl_uri() { use std::convert::TryFrom; let srv = TestServer::with(|| { @@ -107,7 +107,7 @@ async fn test_uri() { assert_eq!(con.peer_addr().unwrap(), srv.addr()); } -#[cfg(feature = "rustls")] +#[cfg(all(feature = "rustls", feature = "uri"))] #[actix_rt::test] async fn test_rustls_uri() { use std::convert::TryFrom; diff --git a/actix-server/CHANGES.md b/actix-server/CHANGES.md index 067adcd6..7111fb0b 100644 --- a/actix-server/CHANGES.md +++ b/actix-server/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## Unreleased + +### Changed + +* workers must be greater than 0 + ## [1.0.3] - 2020-05-19 ### Changed diff --git a/actix-server/Cargo.toml b/actix-server/Cargo.toml index 1d9dca0b..868b36cc 100644 --- a/actix-server/Cargo.toml +++ b/actix-server/Cargo.toml @@ -23,8 +23,8 @@ default = [] [dependencies] actix-service = "1.0.1" actix-rt = "1.0.0" -actix-codec = "0.2.0" -actix-utils = "1.0.4" +actix-codec = "0.3.0" +actix-utils = "2.0.0" log = "0.4" num_cpus = "1.11" diff --git a/actix-server/src/builder.rs b/actix-server/src/builder.rs index 2e8ae30e..8a90d598 100644 --- a/actix-server/src/builder.rs +++ b/actix-server/src/builder.rs @@ -72,8 +72,9 @@ impl ServerBuilder { /// Set number of workers to start. /// /// By default server uses number of available logical cpu as workers - /// count. + /// count. Workers must be greater than 0. pub fn workers(mut self, num: usize) -> Self { + assert_ne!(num, 0, "workers must be greater than 0"); self.threads = num; self } @@ -276,7 +277,7 @@ impl ServerBuilder { info!("Starting \"{}\" service on {}", sock.1, sock.2); } self.accept.start( - mem::replace(&mut self.sockets, Vec::new()) + mem::take(&mut self.sockets) .into_iter() .map(|t| (t.0, t.2)) .collect(), @@ -355,7 +356,7 @@ impl ServerBuilder { // stop accept thread self.accept.send(Command::Stop); - let notify = std::mem::replace(&mut self.notify, Vec::new()); + let notify = std::mem::take(&mut self.notify); // stop workers if !self.workers.is_empty() && graceful { diff --git a/actix-service/CHANGES.md b/actix-service/CHANGES.md index e7c1fefa..011ac65e 100644 --- a/actix-service/CHANGES.md +++ b/actix-service/CHANGES.md @@ -1,6 +1,9 @@ # Changes -## Unreleased +## Unreleased - 2020-xx-xx + + +## 1.0.6 - 2020-08-09 ### Fixed diff --git a/actix-service/Cargo.toml b/actix-service/Cargo.toml index 8ab0a05b..7c73e9bf 100644 --- a/actix-service/Cargo.toml +++ b/actix-service/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "actix-service" -version = "1.0.5" +version = "1.0.6" authors = ["Nikolay Kim "] -description = "Actix service" -keywords = ["network", "framework", "async", "futures"] +description = "Service trait and combinators for representing asynchronous request/response operations." +keywords = ["network", "framework", "async", "futures", "service"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-net.git" -documentation = "https://docs.rs/actix-service/" +documentation = "https://docs.rs/actix-service" +readme = "README.md" categories = ["network-programming", "asynchronous"] license = "MIT OR Apache-2.0" edition = "2018" diff --git a/actix-service/README.md b/actix-service/README.md new file mode 100644 index 00000000..29ca42ea --- /dev/null +++ b/actix-service/README.md @@ -0,0 +1,7 @@ +# actix-service + +> Service trait and combinators for representing asynchronous request/response operations. + +See documentation for detailed explanations these components: [https://docs.rs/actix-service](docs). + +[docs]: https://docs.rs/actix-service diff --git a/actix-service/benches/and_then.rs b/actix-service/benches/and_then.rs index 98de007d..f4174dd7 100644 --- a/actix-service/benches/and_then.rs +++ b/actix-service/benches/and_then.rs @@ -293,9 +293,8 @@ where let start = std::time::Instant::now(); // benchmark body rt.block_on(async move { join_all(srvs.iter_mut().map(|srv| srv.call(()))).await }); - let elapsed = start.elapsed(); // check that at least first request succeeded - elapsed + start.elapsed() }) }); } diff --git a/actix-service/benches/unsafecell_vs_refcell.rs b/actix-service/benches/unsafecell_vs_refcell.rs index 9746cf9e..a599795f 100644 --- a/actix-service/benches/unsafecell_vs_refcell.rs +++ b/actix-service/benches/unsafecell_vs_refcell.rs @@ -95,9 +95,8 @@ where let start = std::time::Instant::now(); // benchmark body rt.block_on(async move { join_all(srvs.iter_mut().map(|srv| srv.call(()))).await }); - let elapsed = start.elapsed(); // check that at least first request succeeded - elapsed + start.elapsed() }) }); } diff --git a/actix-service/src/fn_service.rs b/actix-service/src/fn_service.rs index 225e56b9..08690a5d 100644 --- a/actix-service/src/fn_service.rs +++ b/actix-service/src/fn_service.rs @@ -29,7 +29,7 @@ where /// /// Service that divides two usize values. /// async fn div((x, y): (usize, usize)) -> Result { /// if y == 0 { -/// Err(io::Error::new(io::ErrorKind::Other, "divide by zdro")) +/// Err(io::Error::new(io::ErrorKind::Other, "divide by zero")) /// } else { /// Ok(x / y) /// } diff --git a/actix-service/src/lib.rs b/actix-service/src/lib.rs index 68a5dbc6..fd09184c 100644 --- a/actix-service/src/lib.rs +++ b/actix-service/src/lib.rs @@ -1,3 +1,5 @@ +//! See [`Service`](trait.Service.html) docs for information on this crate's foundational trait. + #![deny(rust_2018_idioms, warnings)] #![allow(clippy::type_complexity)] @@ -29,21 +31,23 @@ pub use self::map_config::{map_config, unit_config}; pub use self::pipeline::{pipeline, pipeline_factory, Pipeline, PipelineFactory}; pub use self::transform::{apply, Transform}; -/// An asynchronous function from `Request` to a `Response`. +/// An asynchronous operation from `Request` to a `Response`. /// -/// `Service` represents a service that represanting interation, taking requests and giving back -/// replies. You can think about service as a function with one argument and result as a return -/// type. In general form it looks like `async fn(Req) -> Result`. `Service` -/// trait just generalizing form of this function. Each parameter described as an assotiated type. +/// The `Service` trait models a request/response interaction, receiving requests and returning +/// replies. You can think about a service as a function with one argument that returns some result +/// asynchronously. Conceptually, the operation looks like this: /// -/// Services provides a symmetric and uniform API, same abstractions represents -/// clients and servers. Services describe only `transforamtion` operation -/// which encorouge to simplify api surface and phrases `value transformation`. -/// That leads to simplier design of each service. That also allows better testability -/// and better composition. +/// ```rust,ignore +/// async fn(Request) -> Result +/// ``` /// -/// Services could be represented in several different forms. In general, -/// Service is a type that implements `Service` trait. +/// The `Service` trait just generalizes this form where each parameter is described as an +/// associated type on the trait. Services can also have mutable state that influence computation. +/// +/// `Service` provides a symmetric and uniform API; the same abstractions can be used to represent +/// both clients and servers. Services describe only _transformation_ operations which encourage +/// simple API surfaces. This leads to simpler design of each service, improves test-ability and +/// makes composition easier. /// /// ```rust,ignore /// struct MyService; @@ -52,7 +56,7 @@ pub use self::transform::{apply, Transform}; /// type Request = u8; /// type Response = u64; /// type Error = MyError; -/// type Future = Pin>>; +/// type Future = Pin>>>; /// /// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { ... } /// @@ -60,8 +64,8 @@ pub use self::transform::{apply, Transform}; /// } /// ``` /// -/// Service can have mutable state that influence computation. -/// This service could be rewritten as a simple function: +/// Sometimes it is not necessary to implement the Service trait. For example, the above service +/// could be rewritten as a simple function and passed to [fn_service](fn.fn_service.html). /// /// ```rust,ignore /// async fn my_service(req: u8) -> Result; @@ -89,11 +93,9 @@ pub trait Service { /// It is permitted for the service to return `Ready` from a `poll_ready` /// call and the next invocation of `call` results in an error. /// - /// There are several notes to consider: - /// + /// # Notes /// 1. `.poll_ready()` might be called on different task from actual service call. - /// - /// 2. In case of chained services, `.poll_ready()` get called for all services at once. + /// 1. In case of chained services, `.poll_ready()` get called for all services at once. fn poll_ready(&mut self, ctx: &mut task::Context<'_>) -> Poll>; /// Process the request and return the response asynchronously. @@ -127,7 +129,7 @@ pub trait Service { /// Map this service's error to a different error, returning a new service. /// /// This function is similar to the `Result::map_err` where it will change - /// the error type of the underlying service. This is useful for example to + /// the error type of the underlying service. For example, this can be useful to /// ensure that services have the same error type. /// /// Note that this function consumes the receiving service and returns a @@ -141,42 +143,42 @@ pub trait Service { } } -/// Creates new `Service` values. +/// Factory for creating `Service`s. /// -/// Acts as a service factory. This is useful for cases where new `Service` -/// values must be produced. One case is a TCP server listener. The listener -/// accepts new TCP streams, obtains a new `Service` value using the -/// `ServiceFactory` trait, and uses that new `Service` value to process inbound +/// Acts as a service factory. This is useful for cases where new `Service`s +/// must be produced. One case is a TCP server listener. The listener +/// accepts new TCP streams, obtains a new `Service` using the +/// `ServiceFactory` trait, and uses the new `Service` to process inbound /// requests on that new TCP stream. /// /// `Config` is a service factory configuration type. pub trait ServiceFactory { - /// Requests handled by the service. + /// Requests handled by the created services. type Request; - /// Responses given by the service + /// Responses given by the created services. type Response; - /// Errors produced by the service + /// Errors produced by the created services. type Error; - /// Service factory configuration + /// Service factory configuration. type Config; - /// The `Service` value created by this factory + /// The kind of `Service` created by this factory. type Service: Service< Request = Self::Request, Response = Self::Response, Error = Self::Error, >; - /// Errors produced while building a service. + /// Errors potentially raised while building a service. type InitError; /// The future of the `Service` instance. type Future: Future>; - /// Create and return a new service value asynchronously. + /// Create and return a new service asynchronously. fn new_service(&self, cfg: Self::Config) -> Self::Future; /// Map this service's output to a different type, returning a new service diff --git a/actix-tls/CHANGES.md b/actix-tls/CHANGES.md index b0d9ad28..d8badb42 100644 --- a/actix-tls/CHANGES.md +++ b/actix-tls/CHANGES.md @@ -1,6 +1,9 @@ # Changes -## [unreleased] +## Unreleased + + +## 2.0.0-alpha.2 - 2020-08-17 ### Changed @@ -8,6 +11,7 @@ * Update `tokio-rustls` dependency to 0.14 * Update `webpki-roots` dependency to 0.20 + ## [2.0.0-alpha.1] - 2020-03-03 ### Changed diff --git a/actix-tls/Cargo.toml b/actix-tls/Cargo.toml index 99be200d..f6c886e0 100644 --- a/actix-tls/Cargo.toml +++ b/actix-tls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-tls" -version = "2.0.0-alpha.1" +version = "2.0.0-alpha.2" authors = ["Nikolay Kim "] description = "Actix tls services" keywords = ["network", "framework", "async", "futures"] @@ -33,8 +33,8 @@ nativetls = ["native-tls", "tokio-tls"] [dependencies] actix-service = "1.0.0" -actix-codec = "0.2.0" -actix-utils = "1.0.0" +actix-codec = "0.3.0" +actix-utils = "2.0.0" actix-rt = "1.0.0" derive_more = "0.99.2" either = "1.5.2" diff --git a/actix-utils/CHANGES.md b/actix-utils/CHANGES.md index b75c03d3..fe7aca31 100644 --- a/actix-utils/CHANGES.md +++ b/actix-utils/CHANGES.md @@ -2,8 +2,13 @@ ## Unreleased - 2020-xx-xx +## 2.0.0 - 2020-08-23 +* No changes from beta 1. + +## 2.0.0-beta.1 - 2020-08-19 * Upgrade `tokio-util` to `0.3`. * Remove unsound custom Cell and use `std::cell::RefCell` instead, as well as `actix-service`. +* Rename method to correctly spelled `LocalWaker::is_registered`. ## [1.0.6] - 2020-01-08 diff --git a/actix-utils/Cargo.toml b/actix-utils/Cargo.toml index f0a89165..e253545a 100644 --- a/actix-utils/Cargo.toml +++ b/actix-utils/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "actix-utils" -version = "1.0.6" +version = "2.0.0" authors = ["Nikolay Kim "] -description = "Actix utils - various actix net related services" +description = "Various network related services and utilities for the Actix ecosystem." keywords = ["network", "framework", "async", "futures"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-net.git" @@ -16,15 +16,15 @@ name = "actix_utils" path = "src/lib.rs" [dependencies] -actix-service = "1.0.1" -actix-rt = "1.0.0" -actix-codec = "0.2.0" -bitflags = "1.2" +actix-codec = "0.3.0" +actix-rt = "1.1.1" +actix-service = "1.0.6" +bitflags = "1.2.1" bytes = "0.5.3" either = "1.5.3" futures-channel = { version = "0.3.4", default-features = false } futures-sink = { version = "0.3.4", default-features = false } futures-util = { version = "0.3.4", default-features = false } -pin-project = "0.4.17" log = "0.4" +pin-project = "0.4.17" slab = "0.4" diff --git a/actix-utils/src/counter.rs b/actix-utils/src/counter.rs index ceaa727c..4fe9dd0a 100644 --- a/actix-utils/src/counter.rs +++ b/actix-utils/src/counter.rs @@ -7,7 +7,7 @@ use crate::task::LocalWaker; #[derive(Clone)] /// Simple counter with ability to notify task on reaching specific number /// -/// Counter could be cloned, total ncount is shared across all clones. +/// Counter could be cloned, total n-count is shared across all clones. pub struct Counter(Rc); struct CounterInner { diff --git a/actix-utils/src/framed.rs b/actix-utils/src/dispatcher.rs similarity index 99% rename from actix-utils/src/framed.rs rename to actix-utils/src/dispatcher.rs index fef70ff0..15d3ccf7 100644 --- a/actix-utils/src/framed.rs +++ b/actix-utils/src/dispatcher.rs @@ -1,5 +1,7 @@ //! Framed dispatcher service and related utilities + #![allow(type_alias_bounds)] + use std::pin::Pin; use std::task::{Context, Poll}; use std::{fmt, mem}; diff --git a/actix-utils/src/inflight.rs b/actix-utils/src/inflight.rs index f07e4592..5ed987c7 100644 --- a/actix-utils/src/inflight.rs +++ b/actix-utils/src/inflight.rs @@ -152,7 +152,7 @@ mod tests { } #[actix_rt::test] - async fn test_newtransform() { + async fn test_new_transform() { let wait_time = Duration::from_millis(50); let srv = apply(InFlight::new(1), fn_factory(|| ok(SleepService(wait_time)))); diff --git a/actix-utils/src/lib.rs b/actix-utils/src/lib.rs index be013729..7fde1f59 100644 --- a/actix-utils/src/lib.rs +++ b/actix-utils/src/lib.rs @@ -1,11 +1,12 @@ //! Actix utils - various helper services + #![deny(rust_2018_idioms)] #![allow(clippy::type_complexity)] pub mod condition; pub mod counter; +pub mod dispatcher; pub mod either; -pub mod framed; pub mod inflight; pub mod keepalive; pub mod mpsc; diff --git a/actix-utils/src/oneshot.rs b/actix-utils/src/oneshot.rs index 16f2c4b4..e75fad60 100644 --- a/actix-utils/src/oneshot.rs +++ b/actix-utils/src/oneshot.rs @@ -170,7 +170,7 @@ pub struct PReceiver { inner: Rc>>>, } -// The oneshots do not ever project Pin to the inner T +// The one-shots do not ever project Pin to the inner T impl Unpin for PReceiver {} impl Unpin for PSender {} diff --git a/actix-utils/src/order.rs b/actix-utils/src/order.rs index ba589f30..c418f1d3 100644 --- a/actix-utils/src/order.rs +++ b/actix-utils/src/order.rs @@ -231,7 +231,7 @@ mod tests { } #[actix_rt::test] - async fn test_inorder() { + async fn test_in_order() { let (tx1, rx1) = oneshot::channel(); let (tx2, rx2) = oneshot::channel(); let (tx3, rx3) = oneshot::channel(); diff --git a/actix-utils/src/task.rs b/actix-utils/src/task.rs index 349e3501..dca386b8 100644 --- a/actix-utils/src/task.rs +++ b/actix-utils/src/task.rs @@ -36,7 +36,7 @@ impl LocalWaker { #[inline] /// Check if waker has been registered. - pub fn is_registed(&self) -> bool { + pub fn is_registered(&self) -> bool { unsafe { (*self.waker.get()).is_some() } } diff --git a/actix-utils/src/time.rs b/actix-utils/src/time.rs index 02a56607..2ce65bc3 100644 --- a/actix-utils/src/time.rs +++ b/actix-utils/src/time.rs @@ -173,7 +173,7 @@ mod tests { /// /// Expected Behavior: Two back-to-back calls of `LowResTimeService::now()` return the same value. #[actix_rt::test] - async fn lowres_time_service_time_does_not_immediately_change() { + async fn low_res_time_service_time_does_not_immediately_change() { let resolution = Duration::from_millis(50); let time_service = LowResTimeService::with(resolution); assert_eq!(time_service.now(), time_service.now()); @@ -210,7 +210,7 @@ mod tests { /// Expected Behavior: Two calls of `LowResTimeService::now()` made in subsequent resolution interval return different values /// and second value is greater than the first one at least by a resolution interval. #[actix_rt::test] - async fn lowres_time_service_time_updates_after_resolution_interval() { + async fn low_res_time_service_time_updates_after_resolution_interval() { let resolution = Duration::from_millis(100); let wait_time = Duration::from_millis(300); let time_service = LowResTimeService::with(resolution); diff --git a/actix-utils/src/timeout.rs b/actix-utils/src/timeout.rs index 83fbb84f..f1d30f19 100644 --- a/actix-utils/src/timeout.rs +++ b/actix-utils/src/timeout.rs @@ -58,10 +58,7 @@ impl PartialEq for TimeoutError { TimeoutError::Service(e2) => e1 == e2, TimeoutError::Timeout => false, }, - TimeoutError::Timeout => match other { - TimeoutError::Service(_) => false, - TimeoutError::Timeout => true, - }, + TimeoutError::Timeout => matches!(other, TimeoutError::Timeout), } } } @@ -223,7 +220,7 @@ mod tests { } #[actix_rt::test] - async fn test_timeout_newservice() { + async fn test_timeout_new_service() { let resolution = Duration::from_millis(100); let wait_time = Duration::from_millis(500); diff --git a/router/src/lib.rs b/router/src/lib.rs index 75485b5a..f97b34e8 100644 --- a/router/src/lib.rs +++ b/router/src/lib.rs @@ -37,7 +37,6 @@ impl ResourcePath for bytestring::ByteString { /// Helper trait for type that could be converted to path pattern pub trait IntoPattern { - /// Signle patter fn is_single(&self) -> bool; fn patterns(&self) -> Vec;