The Service trait requires users to call poll_ready before invoking the call function in order to check if the service is ready or not. However, users are not obligated to do this and may forget to call poll_ready.
Therefore, it is worth considering whether it would be beneficial to use the type system to prevent users from invoking call if the service is not ready.
One suggestion is to introduce a ready token with type Service::Ready as follows:
pub trait Service<Request> {
type Response;
type Error;
type Future: Future<Output = Result<Self::Response, Self::Error>>;
type Ready;
fn poll_ready(
&mut self,
cx: &mut Context<'_>
) -> Poll<Result<Self::Ready, Self::Error>>;
fn call(&mut self, token: Self::Ready, req: Request) -> Self::Future;
}
With this approach, users must obtain a token: Self::Ready before invoking call, which can only be extracted from Poll::Ready(Ok(Self::Ready)). This follows the "Parse, not validate" paradigm.
Incorporating the ready token in the implementation of Service would help eliminate the need for checking the invalid state that may occur while invoking call:
The Service trait requires users to call
poll_ready
before invoking thecall
function in order to check if the service is ready or not. However, users are not obligated to do this and may forget to callpoll_ready
.Therefore, it is worth considering whether it would be beneficial to use the type system to prevent users from invoking
call
if the service is not ready.One suggestion is to introduce a ready token with type
Service::Ready
as follows:With this approach, users must obtain a
token: Self::Ready
before invokingcall
, which can only be extracted fromPoll::Ready(Ok(Self::Ready))
. This follows the "Parse, not validate" paradigm.Incorporating the ready token in the implementation of
Service
would help eliminate the need for checking the invalid state that may occur while invokingcall
:https://github.com/tower-rs/tower/blob/664cb35abb8da07b6c46212375c481153d8abfb9/tower/src/limit/rate/service.rs#L116