pub trait Service<St, Req> {
type Res;
type Error;
// Required method
async fn call(
&self,
req: Req,
ctx: Ctx<'_, Self, St>,
) -> Result<Self::Res, Self::Error>;
// Provided methods
async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Self::Error> { ... }
async fn shutdown(&self, ctx: Ctx<'_, Self, St>) { ... }
fn map<F, Res>(self, f: F) -> ServiceChain<Map<F, Self, Res>, St, Req>
where Self: Sized,
F: Fn(Self::Res) -> Res { ... }
fn map_err<F, E>(self, f: F) -> ServiceChain<MapErr<F, Self, E>, St, Req>
where Self: Sized,
F: Fn(Self::Error) -> E { ... }
fn and_then<Next, F>(
self,
f: F,
) -> ServiceChain<AndThen<Self, Next>, St, Req>
where Self: Sized,
Next: Service<St, Self::Res, Error = Self::Error>,
F: IntoService<Next, St, Self::Res> { ... }
fn pipeline(self, st: St) -> Pipeline<Req, Self::Res, Self::Error>
where Self: Sized + 'static,
St: 'static,
Req: 'static { ... }
}Expand description
An asynchronous operation from a request to a response.
A service receives requests and asynchronously produces responses. Conceptually, it is similar to:
async fn(Request) -> Result<Response, Error>The request and pipeline-state types are generic parameters. The response
and error types are associated types, allowing one service type to implement
Service for multiple request types.
Methods take &self, so implementations that mutate internal state must use
interior mutability such as Cell, RefCell, or a synchronization
primitive when appropriate.
The same abstraction can represent client- and server-side operations. Services focus on transformation, making them straightforward to test and compose.
A service call requires a Ctx and therefore runs through a Pipeline
or from another service. The pipeline coordinates readiness across a
composed service chain before dispatching a request.
struct MyService;
impl Service<(), u8> for MyService {
type Res = u64;
type Error = Infallible;
async fn call(&self, req: u8, ctx: Ctx<'_, Self>) -> Result<Self::Res, Self::Error> {
Ok(req as u64)
}
}Simple services do not need a manual trait implementation. The example
above can be expressed with fn_service:
let service = fn_service(|req: u8| async move {
Ok::<_, Infallible>(u64::from(req))
});
let pipeline = Pipeline::new((), service);
assert_eq!(pipeline.call(10).await?, 10);Required Associated Types§
Required Methods§
Sourceasync fn call(
&self,
req: Req,
ctx: Ctx<'_, Self, St>,
) -> Result<Self::Res, Self::Error>
async fn call( &self, req: Req, ctx: Ctx<'_, Self, St>, ) -> Result<Self::Res, Self::Error>
Processes a request and asynchronously returns the response.
The enclosing pipeline checks readiness before invoking this method.
Implementations should not call their own ready method. A composed
service can use ctx to call an inner service.
Provided Methods§
Sourceasync fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Self::Error>
async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Self::Error>
Waits until the service is ready to process a request.
If the service is at capacity, the returned future remains pending until capacity becomes available.
Pipeline readiness is coordinated across all services in a composed chain. A request is dispatched only when the chain is ready.
Sourceasync fn shutdown(&self, ctx: Ctx<'_, Self, St>)
async fn shutdown(&self, ctx: Ctx<'_, Self, St>)
Shuts down the service.
Returns when the service has been properly shut down.
Sourcefn map<F, Res>(self, f: F) -> ServiceChain<Map<F, Self, Res>, St, Req>
fn map<F, Res>(self, f: F) -> ServiceChain<Map<F, Self, Res>, St, Req>
Maps this service’s output to a different type, returning a new service.
This is similar to Option::map or Iterator::map, changing the
output type of the underlying service.
This function consumes the original service and returns a wrapped version,
following the pattern of standard library map methods.
Sourcefn map_err<F, E>(self, f: F) -> ServiceChain<MapErr<F, Self, E>, St, Req>
fn map_err<F, E>(self, f: F) -> ServiceChain<MapErr<F, Self, E>, St, Req>
Maps this service’s error to a different type, returning a new service.
This is similar to Result::map_err, changing the error type of the
underlying service. It is useful, for example, to ensure multiple
services have the same error type.
This function consumes the original service and returns a wrapped version.
Sourcefn and_then<Next, F>(self, f: F) -> ServiceChain<AndThen<Self, Next>, St, Req>
fn and_then<Next, F>(self, f: F) -> ServiceChain<AndThen<Self, Next>, St, Req>
Calls another service after this service completes successfully.
The first service’s response becomes the second service’s request. If the first service returns an error, the second service is not called.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".