You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This doesn't take timeout, so to add timeout on top we wrap with asyncio.wait or similar (like other primitives in the asyncio library). Unfortunately this makes logging the error difficult as connect calls recursively connect child devices. The way we report reasonable errors at the moment is to catch the CancelledError that is injected when the task times out, and raise NotConnectedError with the name of the signal in question, accumulating them in the parent until we produce a single top level NotConnectedError with all the failing signals:
"""Call many underlying signals, accumulating `NotConnected` exceptions
Raises
------
`NotConnected` if cancelled
"""
ts= {k: asyncio.create_task(c) for (k, c) incoros.items()} # type: ignore
try:
done, pending=awaitasyncio.wait(ts.values())
exceptasyncio.CancelledError:
fortints.values():
t.cancel()
lines: List[str] = []
fork, tints.items():
try:
awaitt
exceptNotConnectedase:
iflen(e.lines) ==1:
lines.append(f"{k}: {e.lines[0]}")
else:
lines.append(f"{k}:")
lines+= [f" {line}"forlineine.lines]
raiseNotConnected(*lines)
else:
# Wait for everything to foreground the exceptions
forfinlist(done) +list(pending):
awaitf
This is horrible. It also bites people who await device.connect() rather than using asyncio.wait like in DiamondLightSource/dodal#223.
@callumforrester suggested a better way, pass the timeout down, then let each child produce a class ConnectTimeoutError(TimeoutError) when it times out, then assemble it at the top level with an asyncio.gather(*coros, return_exceptions=True), squashing ConnectTimeoutErrors into a single one.
An ophyd_async device timed out on Hyperion yesterday, very difficult to diagnose without knowing what device / signal timed out, so this change will be very useful
At the moment we have:
ophyd-async/src/ophyd_async/core/device.py
Lines 53 to 65 in f1b4aba
This doesn't take timeout, so to add timeout on top we wrap with
asyncio.wait
or similar (like other primitives in the asyncio library). Unfortunately this makes logging the error difficult asconnect
calls recursively connect child devices. The way we report reasonable errors at the moment is to catch theCancelledError
that is injected when the task times out, and raiseNotConnectedError
with the name of the signal in question, accumulating them in the parent until we produce a single top levelNotConnectedError
with all the failing signals:ophyd-async/src/ophyd_async/core/utils.py
Lines 26 to 53 in f1b4aba
This is horrible. It also bites people who
await device.connect()
rather than usingasyncio.wait
like in DiamondLightSource/dodal#223.@callumforrester suggested a better way, pass the timeout down, then let each child produce a
class ConnectTimeoutError(TimeoutError)
when it times out, then assemble it at the top level with anasyncio.gather(*coros, return_exceptions=True)
, squashingConnectTimeoutError
s into a single one.This would change the signature to:
with each concrete class raising
ConnectTimeoutError
if it times out, thenwait_for_connection
doing the squashing ofConnectTimeoutErrors
.The text was updated successfully, but these errors were encountered: