-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Implement a CachedCall to handle boilerplate of caching results #9353
Conversation
This feels like a relatively common pattern which is hard to get right. I've used `oidc.jwks` as an example for how it could be used.
I'm interested in thoughts on this. I don't think the tests are passing; in any case, if it's a good idea, I want to add unit tests. But if the answer is "why don't you just ....", then I won't pursue it further. |
self._deferred = None # type: Optional[Deferred] | ||
self._result = None # type: Union[None, Failure, TV] | ||
|
||
async def get(self) -> TV: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe slighter nicer ergonomics if we used __call__
instead?
This would let you do something like:
async def handle_request() -> X:
# We can call this multiple times, but it will result in a single call to
# _load_prop().
return await _cached_val()
This feels a bit nicer since you've wrapped a function and then it returns a function-like thing and might let you use it as a decorator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hrm, maybe. I always feel like relying on __call__
is a bit magical, and tend to prefer that the interactions are made explicit, which is why I did it this way. I could be persuaded though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thought is that it makes it more like functools.cached_property
, but perhaps that isn't the goal. 😄
# I *think* this is the easiest way to correctly raise a Failure without having | ||
# to gut-wrench into the implementation of Deferred. | ||
d = Deferred() | ||
d.callback(self._result) | ||
return await d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this will work properly for errors, do we need to call d.errback
if it is an instance of Failure
? (I don't think Deferred
does anything special if you callback a Failure
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does work, because errback(x)
and callback(x)
are both just thin wrappers around _startRunCallbacks(x)
. You could argue that this isn't using Deferred's API as it's intended, which might be fair.
This is now superceded by #9362. |
This feels like a relatively common pattern which is hard to get right.
I've used
oidc.jwks
as an example for how it could be used.