Skip to content
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

Add epics test for busy signals #650

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft

Add epics test for busy signals #650

wants to merge 4 commits into from

Conversation

coretl
Copy link
Collaborator

@coretl coretl commented Nov 14, 2024

@DominicOram @olliesilvester this is the epics test I mentioned in DiamondLightSource/dodal#897 (comment)

It looks like I need to yield after the q.get rather than before to let the timeout break without an extra yield

@coretl
Copy link
Collaborator Author

coretl commented Nov 14, 2024

Spoke too soon, doesn't work on CI...

@coretl
Copy link
Collaborator Author

coretl commented Nov 15, 2024

Ok, looks like there are actually numerous python bugs in asyncio.wait_for, which is fixed by its reimplementation on top of asyncio.timeout in 3.12: python/cpython#96764

I think this fixes your particular use case, but you can't pass a timeout to observe_value and also wrap it in wait_for with a timeout on python 3.11 and below.

I would also suggest that you move the opencv calls to another thread and consume all the values from the Queue between the two, dropping old updates.

@olliesilvester
Copy link
Contributor

Great, thank you!

@coretl coretl marked this pull request as draft November 15, 2024 17:01
@coretl
Copy link
Collaborator Author

coretl commented Nov 15, 2024

Ok, still some issues will this, will investigate next week

observe_value runs in a lot of tests, so the testing checks for max_yields
needs to be much more than the one for observe_value otherwise they
fight each other
@coretl coretl marked this pull request as ready for review November 18, 2024 11:16
@coretl
Copy link
Collaborator Author

coretl commented Nov 18, 2024

@DominicOram @olliesilvester @rtuck99 I think this is now working, but would be good to talk through the code with one of you to check I understand the problem correctly

@olliesilvester
Copy link
Contributor

@DominicOram @olliesilvester @rtuck99 I think this is now working, but would be good to talk through the code with one of you to check I understand the problem correctly

I'm about today, I'm just reading through the changes now

@olliesilvester
Copy link
Contributor

Discussed with @coretl, I think this change fixes our issue but I will investigate further to see if there are any safer solutions

Copy link
Contributor

@DominicOram DominicOram left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me, especially if @olliesilvester has talked over it too. My only comment would be that if we think it's mostly a problem with asyncio.wait_for in <3.11 then we should add a comment/issue to drop it when we drop 3.11. But if we think there are other, more general, problems this might catch then maybe we shouldn't drop it.

@olliesilvester
Copy link
Contributor

I tried using asyncio.timeout instead, and we seem to get the same issue. I guess this explains why python 3.12 still had this issue.

I'm leaning towards just not using asyncio.wait_for for this scenario. We could just do

async def observe_value(...):
  if time.time() - start_time > overall_timeout:
                  raise TimeoutError
...

instead, and warn against using asyncio.wait_for (or timeout) with observe_value

@coretl
Copy link
Collaborator Author

coretl commented Nov 20, 2024

I'm leaning towards just not using asyncio.wait_for for this scenario

It's messy, but it's probably the most pragmatic solution here, then we relegate wait_for_pending_wakeups to ophyd_async.testing and only use it in tests

@DominicOram thoughts?

@olliesilvester when this is decided would you mind amending this PR or making a new one with the implementation please?

@DominicOram
Copy link
Contributor

I'm not a big fan of this, having to roll you're own timeout code when there's provision for it in asyncio looks on the face of it like a code-smell if you're not familiar with the bug. How would we feel about adding the functionality into observe_value itself e.g. optionally pass in a overall_timeout value? This would then make the path of least resistance be to just use that

@olliesilvester
Copy link
Contributor

Yeah, the timeout will be in observe_value as an optional parameter

@coretl coretl marked this pull request as draft November 22, 2024 10:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants