Currently if poll_ready returns Ready it effectively reserves something (for instance a semaphore token). This means you must be following up with call next. The only other option is to Drop the service which however is not always possible.
It was mentioned in the tokio repo that it would be useful to be able to disarm a service (tokio-rs/tokio#898).
This would be particularly useful when one wants to implement an HTTP health check for a load balancer by checking poll_ready without actually calling.
Example:
pub trait Service<Request> where
<Self::Future as Future>::Output == Result<Self::Response, Self::Error>, {
type Response;
type Error;
type Future: Future;
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
fn call(&mut self, req: Request) -> Self::Future;
fn disarm_ready(&mut self) {}
}
And then be used like this:
pub trait HealthcheckServiceExt<Request>: Service<Request> {
fn is_healthy(&mut self) -> bool {
if self.poll_ready().is_ready() {
self.disarm_ready();
true
} else {
false
}
}
}
The proposed new flow would be the following:
poll_ready must be called. If it's Ready it must be followed up with either call or disarm_ready.
call must not be called without poll_ready being called before
disarm_ready may always be called and should undo what poll_ready did
Clone is supposed to either internally call disarm_ready or do the same it does (a Clone should always be disarmed)
The latter is already the logic that exists in some layers.
Now obviously it's a bit suboptimal that it means not all services will be able to disarmed so it might also be possible to indicate if something can actually be disarmed. For instance already existing services might just not ever be disarmable until they get retrofitted.
Currently if
poll_readyreturnsReadyit effectively reserves something (for instance a semaphore token). This means you must be following up withcallnext. The only other option is toDropthe service which however is not always possible.It was mentioned in the tokio repo that it would be useful to be able to disarm a service (tokio-rs/tokio#898).
This would be particularly useful when one wants to implement an HTTP health check for a load balancer by checking
poll_readywithout actually calling.Example:
And then be used like this:
The proposed new flow would be the following:
poll_readymust be called. If it'sReadyit must be followed up with eithercallordisarm_ready.callmust not be called withoutpoll_readybeing called beforedisarm_readymay always be called and should undo whatpoll_readydidCloneis supposed to either internally calldisarm_readyor do the same it does (a Clone should always be disarmed)The latter is already the logic that exists in some layers.
Now obviously it's a bit suboptimal that it means not all services will be able to disarmed so it might also be possible to indicate if something can actually be disarmed. For instance already existing services might just not ever be disarmable until they get retrofitted.