-
Notifications
You must be signed in to change notification settings - Fork 9
Fix NopReceiver.ready() to properly terminate when receiver is closed. #427
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
Fix NopReceiver.ready() to properly terminate when receiver is closed. #427
Conversation
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.
Pull Request Overview
This PR ensures that NopReceiver.ready() unblocks and returns False when close() is called, preventing it from hanging indefinitely.
- Replace the
_closedflag with a future (_ready_future) to signal closure toready(). - Update
ready(),consume(), andclose()to use the new future-based mechanism. - Add a test that verifies
ready()returns False immediately afterclose(). - Note the bugfix in
RELEASE_NOTES.md.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| tests/experimental/test_nop_receiver.py | Added test_close_method_effect_on_ready to check that ready() terminates when closed. |
| src/frequenz/channels/experimental/_nop_receiver.py | Swapped the _closed boolean for _ready_future and updated ready(), consume(), and close(). |
| RELEASE_NOTES.md | Documented the fix for NopReceiver.ready() closure behavior. |
| # Create a task that waits for the receiver to be ready. | ||
| task = asyncio.create_task(receiver.ready()) | ||
|
|
||
| # Wait for the task to start. | ||
| await asyncio.sleep(0.1) |
Copilot
AI
Jun 16, 2025
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.
[nitpick] Relying on sleep can lead to flaky tests; consider using an asyncio.Event or polling task.done() to deterministically wait until the task is awaiting ready().
| # Create a task that waits for the receiver to be ready. | |
| task = asyncio.create_task(receiver.ready()) | |
| # Wait for the task to start. | |
| await asyncio.sleep(0.1) | |
| # Create an event to signal when the task starts. | |
| task_started = asyncio.Event() | |
| async def wait_for_ready(): | |
| task_started.set() # Signal that the task has started. | |
| return await receiver.ready() | |
| # Create a task that waits for the receiver to be ready. | |
| task = asyncio.create_task(wait_for_ready()) | |
| # Wait for the task to start. | |
| await task_started.wait() |
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.
But I need to make sure ready is called before cancel.
This won't do that.
The ready() method was not terminating when close() was called, causing it to hang indefinitely. This fix ensures ready() returns False when the receiver is closed. Signed-off-by: Elzbieta Kotulska <[email protected]>
ebe52e7 to
0559463
Compare
Because it is recommended in the python documentation. This way alternative event loop implementations can inject their own optimized implementations of a Future object. Signed-off-by: Elzbieta Kotulska <[email protected]>
0559463 to
7130676
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.
oops
NopReceiver.ready() to properly terminate when receiver is closed.
NopReceiver.ready() to properly terminate when receiver is closed.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 guess it doesn't matter as long as it works, but maybe using a Event would be less low-level-ish.
The ready() method was not terminating when close() was called, causing it to hang indefinitely. This fix ensures ready() returns False when the receiver is closed.