-
Notifications
You must be signed in to change notification settings - Fork 178
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(api): New protocols print a JSON "run log" from opentrons_execute…
… and opentrons.execute.execute() (#13629)
- Loading branch information
1 parent
b538156
commit 24eb3c1
Showing
14 changed files
with
473 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
"""Monitor the execution of commands in a `ProtocolEngine`.""" | ||
|
||
|
||
from dataclasses import dataclass | ||
import typing | ||
import contextlib | ||
|
||
|
||
from opentrons.protocol_engine import Command, ProtocolEngine | ||
|
||
|
||
@dataclass | ||
class RunningEvent: | ||
"""Emitted when a command starts running.""" | ||
|
||
command: Command | ||
|
||
|
||
@dataclass | ||
class NoLongerRunningEvent: | ||
"""Emitted when a command stops running--either because it succeeded, or failed.""" | ||
|
||
command: Command | ||
|
||
|
||
Event = typing.Union[RunningEvent, NoLongerRunningEvent] | ||
Callback = typing.Callable[[Event], None] | ||
|
||
|
||
@contextlib.contextmanager | ||
def monitor_commands( | ||
protocol_engine: ProtocolEngine, | ||
callback: Callback, | ||
) -> typing.Generator[None, None, None]: | ||
"""Monitor the execution of commands in `protocol_engine`. | ||
While this context manager is open, `callback` will be called any time `protocol_engine` | ||
starts or stops a command. | ||
""" | ||
# Subscribe to all state updates in protocol_engine. | ||
# On every update, diff the new state against the last state and see if the currently | ||
# running command has changed. If it has, emit the appropriate events. | ||
|
||
last_running_id: typing.Optional[str] = None | ||
|
||
def handle_state_update(_message_from_broker: None) -> None: | ||
nonlocal last_running_id | ||
|
||
running_id = protocol_engine.state_view.commands.get_running() | ||
if running_id != last_running_id: | ||
if last_running_id is not None: | ||
callback( | ||
NoLongerRunningEvent( | ||
protocol_engine.state_view.commands.get(last_running_id) | ||
) | ||
) | ||
|
||
if running_id is not None: | ||
callback( | ||
RunningEvent(protocol_engine.state_view.commands.get(running_id)) | ||
) | ||
last_running_id = running_id | ||
|
||
with protocol_engine.state_update_broker.subscribed(handle_state_update): | ||
yield |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
api/src/opentrons/protocol_engine/state/change_notifier.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,31 @@ | ||
"""Simple state change notification interface.""" | ||
import asyncio | ||
|
||
from opentrons.util.broker import Broker, ReadOnlyBroker | ||
|
||
|
||
class ChangeNotifier: | ||
"""An interface tto emit or subscribe to state change notifications.""" | ||
|
||
def __init__(self) -> None: | ||
"""Initialize the ChangeNotifier with an internal Event.""" | ||
self._event = asyncio.Event() | ||
self._broker = Broker[None]() | ||
|
||
def notify(self) -> None: | ||
"""Notify all `wait`'ers that the state has changed.""" | ||
self._event.set() | ||
self._broker.publish(None) | ||
|
||
async def wait(self) -> None: | ||
"""Wait until the next state change notification.""" | ||
self._event.clear() | ||
await self._event.wait() | ||
|
||
@property | ||
def broker(self) -> ReadOnlyBroker[None]: | ||
"""Return a broker that you can use to get notified of all changes. | ||
This is an alternative interface to `wait()`. | ||
""" | ||
return self._broker |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.