-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
experiment with permit based service framework #757
Comments
I wasn't aware at the time, making a note of it now - if we did split this trait in two it would become close to the suggestion by @olix0r #626 (comment). |
How does this interact with drop and cancelation? Is it better or worse than the current model? This reminds me a lot of completion based io for some reason (https://www.ncameron.org/blog/async-io-with-completion-model-io-systems/). |
I don't think the design here addresses the lower-level problems relating to async drop if that's what you mean, but it does address the disarm problem. I like to think about Under current contract, the
And citing OP of the disarm thread:
The implementation here solves this problem because you can deallocate shared resource prior to |
I've now implemented a decent percentage of the existing Problems common to all
The following are specific to
|
Overview
burger
is an experimental permit based service API.I published a few example implementations in this repository. This API is possible (migration here) without
async fn
in traits and just GATs. It requires a lot of pin projection madness and extra GATs.The purpose of the issue is to collect critiques to inform the design of
tower
.Motivating Questions
Why use permits?
Permits allow you to disarm a service after it's ready and can be used to enforce a tighter service contract.
Why doesn't
call
accept&self
?The readiness of one service does not ensure the readiness of a different service of the same type - we want to disallow sharing of permits. There are three options here:
call
from&self
to the permit.Choosing 1 is safe and less obscure than 2.
Why does
call
take ownership of the permit?A permit should allow only one
call
.Why is
Service::Permit<'a>
a GAT?We want to be able to pass the innards of
&self
into theSelf::Permit<'_>
by reference. CloningArc
s from the&self
toSelf::Permit
will result in poor performance and developer experience.Why does
fn acquire
accept&self
rather than&mut self
?If it accepted
&mut self
we would only ever be able to obtain one permit at a time.Why
async fn acquire
rather thanfn acquire
liketower::Service::poll_ready
?Both approaches boil down to the same kind of state machines eventually. Using
Future
allows for easy composition with the largeFuture
s ecosystem and with otherService::acquire
calls.Why do
async fn acquire
andasync fn call
not return aResult
?Most of the
Service
style combinators work withoutResult
.If the user wants to write a
Service
with a fallibleasync fn acquire
then they can model the permit as aResult
and havecall
return theErr
. If the user wants to write an infallibleacquire
and a falliblecall
the signatures are no longer coupled by convention alone.Perhaps the value of
acquire
returning aResult
outweighs the flexibility though.Split this into two traits?
We could split the
Service
trait intoAcquire
andCall
whereCall
is implemented on the permit and hasasync fn call(self, request: Request)
. I have no strong opinions on this. Maybe this helps with object safety?The text was updated successfully, but these errors were encountered: