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

improve boxed service docs

This commit is contained in:
Rob Ede 2021-04-15 20:43:02 +01:00
parent ef206f40fb
commit 4e6d88d143
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
4 changed files with 43 additions and 38 deletions

View File

@ -22,8 +22,10 @@ path = "src/lib.rs"
[dependencies] [dependencies]
futures-core = { version = "0.3.7", default-features = false } futures-core = { version = "0.3.7", default-features = false }
paste = "1"
pin-project-lite = "0.2" pin-project-lite = "0.2"
[dev-dependencies] [dev-dependencies]
actix-rt = "2.0.0" actix-rt = "2.0.0"
actix-utils = "3.0.0-beta.4"
futures-util = { version = "0.3.7", default-features = false } futures-util = { version = "0.3.7", default-features = false }

View File

@ -3,26 +3,30 @@
use alloc::{boxed::Box, rc::Rc}; use alloc::{boxed::Box, rc::Rc};
use core::{future::Future, pin::Pin}; use core::{future::Future, pin::Pin};
use paste::paste;
use crate::{Service, ServiceFactory}; use crate::{Service, ServiceFactory};
/// A boxed future without a Send bound or lifetime parameters. /// A boxed future with no send bound or lifetime parameters.
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>; pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
macro_rules! service_object { macro_rules! service_object {
($name: ident, $type: tt, $fn_name: ident) => { ($name: ident, $type: tt, $fn_name: ident) => {
/// Type alias for service trait object. paste! {
pub type $name<Req, Res, Err> = $type< #[doc = "Type alias for service trait object using `" $type "`."]
dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>, pub type $name<Req, Res, Err> = $type<
>; dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>,
>;
/// Create service trait object. #[doc = "Wraps service as a trait object using [`" $name "`]."]
pub fn $fn_name<S, Req>(service: S) -> $name<Req, S::Response, S::Error> pub fn $fn_name<S, Req>(service: S) -> $name<Req, S::Response, S::Error>
where where
S: Service<Req> + 'static, S: Service<Req> + 'static,
Req: 'static, Req: 'static,
S::Future: 'static, S::Future: 'static,
{ {
$type::new(ServiceWrapper::new(service)) $type::new(ServiceWrapper::new(service))
}
} }
}; };
} }
@ -56,10 +60,10 @@ where
} }
} }
/// Wrapper for a service factory trait object that will produce a boxed trait object service. /// Wrapper for a service factory that will map it's services to boxed trait object services.
pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>); pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>);
/// Create service factory trait object. /// Wraps a service factory that returns service trait objects.
pub fn factory<SF, Req>( pub fn factory<SF, Req>(
factory: SF, factory: SF,
) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error, SF::InitError> ) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error, SF::InitError>

View File

@ -73,7 +73,7 @@ use self::ready::{err, ok, ready, Ready};
/// impl Service<u8> for MyService { /// impl Service<u8> for MyService {
/// type Response = u64; /// type Response = u64;
/// type Error = MyError; /// type Error = MyError;
/// type Future = Pin<Box<Future<Output=Result<Self::Response, Self::Error>>>>; /// type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
/// ///
/// fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { ... } /// fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { ... }
/// ///
@ -82,7 +82,7 @@ use self::ready::{err, ok, ready, Ready};
/// ``` /// ```
/// ///
/// Sometimes it is not necessary to implement the Service trait. For example, the above service /// 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_service()). /// could be rewritten as a simple function and passed to [`fn_service`](fn_service()).
/// ///
/// ```ignore /// ```ignore
/// async fn my_service(req: u8) -> Result<u64, MyError>; /// async fn my_service(req: u8) -> Result<u64, MyError>;
@ -102,13 +102,12 @@ pub trait Service<Req> {
/// Returns `Ready` when the service is able to process requests. /// Returns `Ready` when the service is able to process requests.
/// ///
/// If the service is at capacity, then `Pending` is returned and the task /// If the service is at capacity, then `Pending` is returned and the task is notified when the
/// is notified when the service becomes ready again. This function is /// service becomes ready again. This function is expected to be called while on a task.
/// expected to be called while on a task.
/// ///
/// This is a **best effort** implementation. False positives are permitted. /// This is a best effort implementation. False positives are permitted. It is permitted for
/// It is permitted for the service to return `Ready` from a `poll_ready` /// the service to return `Ready` from a `poll_ready` call and the next invocation of `call`
/// call and the next invocation of `call` results in an error. /// results in an error.
/// ///
/// # Notes /// # Notes
/// 1. `poll_ready` might be called on a different task to `call`. /// 1. `poll_ready` might be called on a different task to `call`.
@ -117,25 +116,26 @@ pub trait Service<Req> {
/// Process the request and return the response asynchronously. /// Process the request and return the response asynchronously.
/// ///
/// This function is expected to be callable off task. As such, /// This function is expected to be callable off-task. As such, implementations of `call` should
/// implementations should take care to not call `poll_ready`. If the /// take care to not call `poll_ready`. If the service is at capacity and the request is unable
/// service is at capacity and the request is unable to be handled, the /// to be handled, the returned `Future` should resolve to an error.
/// returned `Future` should resolve to an error.
/// ///
/// Calling `call` without calling `poll_ready` is permitted. The /// Invoking `call` without first invoking `poll_ready` is permitted. Implementations must be
/// implementation must be resilient to this fact. /// resilient to this fact.
fn call(&self, req: Req) -> Self::Future; fn call(&self, req: Req) -> Self::Future;
} }
/// Factory for creating `Service`s. /// Factory for creating `Service`s.
/// ///
/// Acts as a service factory. This is useful for cases where new `Service`s /// This is useful for cases where new `Service`s must be produced. One case is a TCP
/// must be produced. One case is a TCP server listener. The listener /// server listener: a listener accepts new connections, constructs a new `Service` for each using
/// accepts new TCP streams, obtains a new `Service` using the /// the `ServiceFactory` trait, and uses the new `Service` to process inbound requests on that new
/// `ServiceFactory` trait, and uses the new `Service` to process inbound /// connection.
/// requests on that new TCP stream.
/// ///
/// `Config` is a service factory configuration type. /// `Config` is a service factory configuration type.
///
/// Simple factories may be able to use [`fn_factory`] or [`fn_factory_with_config`] to
/// reduce boilerplate.
pub trait ServiceFactory<Req> { pub trait ServiceFactory<Req> {
/// Responses given by the created services. /// Responses given by the created services.
type Response; type Response;

View File

@ -222,10 +222,9 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::{ use core::time::Duration;
future::{ready, Ready},
time::Duration, use actix_utils::future::{ready, Ready};
};
use super::*; use super::*;
use crate::Service; use crate::Service;