-
-
Notifications
You must be signed in to change notification settings - Fork 733
Avoid deadlock when two tasks are concurrently waiting for an unresolved ActorFuture
#5709
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
Conversation
Can one of the admins verify this patch? |
43bb3d2
to
95f11e9
Compare
f2a84c5
to
cb8e7de
Compare
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.
Thanks @graingert, this is a nice piece of work, and the implementation seems sound to me. A few design questions, but nothing major.
1a09c7e
to
f2fbc8a
Compare
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.
Not too important, but I could see some type annotations here being helpful, mostly just for future readers. Particularly for things like:
-
ActorFuture.result
return type (makingActorFuture
generic would be necessary) -
ActorFuture.__await__
return type -
_ActorFuture._out
6549929
to
6e54fd1
Compare
6e54fd1
to
35b0c65
Compare
Hmm, tried your PR with Python 3.10.1 and the results were not completely conclusive:
Complete build log with all packages used and step taken to run the test suite. |
await self._event.wait() | ||
out = self._out | ||
assert out is not None | ||
return out.unwrap() |
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.
Can you elucidate a bit more the purpose of these wrapper classes, as opposed to the more direct inspection of the result that there was previously? It seems like they are related to trying to get a chain of custody for the generic _T
, but I'm not sure it really buys much since the setting of the result here isn't checked, so we ultimately have an _OK(Unknown)
.
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.
Yeah ideally this would have been done with TypedDict but they're not supported python/mypy#3863
class _OK(TypedDict, Generic[_T]):
status: Literal["OK"]
result: _T
class _Error(TypedDict):
status: Literal["error"]
exception: Exception
...
def _set_result(self, out: _Error | _OK[_T]): ...
It seems like they are related to trying to get a chain of custody for the generic _T, but I'm not sure it really buys much since the setting of the result here isn't checked, so we ultimately have an _OK(Unknown).
I needed to draw the line somewhere of what's typed and what's not in this PR, and chose to type all the methods and classes of BaseActorFuture. _Error | _OK[_T] | None
is also needed for the internal state ActorFuture
so I think it's worth it for now
I love the new generic machinery @graingert, and I like that it brings it a bit closer to how |
749bce9
to
0364c50
Compare
7fde98b
to
a4012e5
Compare
this keeps the somewhat odd late asyncio.Event() construction in one location that can be removed by pyupgrade
each test uses a different method so it's confusing me to edit both ends of the test file
…rActorFuture->EagerActorFuture
a4012e5
to
2a7b3e4
Compare
Waiting for builds to pass and then will merge. |
ActorFuture
All green 🥲 |
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.
Looks great
Was this supposed to be python310-fix? Because it doesn’t work for me: test_client.py::test_client_gather_semaphore_loop, |
Thank you @graingert ! This looks great. Sorry for us taking so long with reviewing it. |
pre-commit run --all-files