-
Notifications
You must be signed in to change notification settings - Fork 175
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
refactor(api, robot-server): Refactor ProtocolRunner per protocol type #12343
Conversation
protocol_source: Optional[ProtocolSource] = None, | ||
) -> ProtocolRunResult: | ||
"""Run a given protocol to completion.""" | ||
# TODO(mc, 2022-01-11): move load to runner creation, remove from `run` |
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 totally do this for this pr
@@ -37,3 +51,13 @@ stages: | |||
- id: 'RunActionNotAllowed' | |||
title: 'Run Action Not Allowed' | |||
detail: 'Cannot pause a run that is not running.' | |||
|
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.
investigate why this is hanging without the stop
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.
this is hanging on edge too
Codecov Report
@@ Coverage Diff @@
## edge #12343 +/- ##
==========================================
- Coverage 73.81% 73.70% -0.11%
==========================================
Files 2228 2220 -8
Lines 61587 61316 -271
Branches 6382 6374 -8
==========================================
- Hits 45461 45194 -267
+ Misses 14637 14635 -2
+ Partials 1489 1487 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
|
False, True | ||
) | ||
|
||
assert legacy_subject.was_started() is False |
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.
this is wrong. need to fix this test to test real cases
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.
Looking great so far!
Co-authored-by: Max Marrone <[email protected]>
Tested on an OT-2 with json, python, legacy protocols. tested with live protocol commands. works as expected. |
"""Create a ProtocolRunner wired to a simulating HardwareControlAPI. | ||
async def create_simulating_runner( | ||
robot_type: RobotType, protocol_config: ProtocolConfig | ||
) -> AbstractRunner: |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
@@ -27,43 +31,75 @@ | |||
) | |||
|
|||
|
|||
class ProtocolRunResult(NamedTuple): | |||
class RunnerRunResult(NamedTuple): |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
"""An interface to manage and control a protocol run. | ||
|
||
The ProtocolRunner is primarily responsible for feeding a ProtocolEngine | ||
The AbstractRunner is primarily responsible for feeding a ProtocolEngine | ||
with commands and control signals. These commands and signals are | ||
generated by protocol files, hardware signals, or externally via |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
# TODO(mc, 2022-01-11): this class has become bloated. Split into an abstract | ||
# interfaces and several concrete implementations per protocol type | ||
class ProtocolRunner: | ||
class AbstractRunner(ABC): |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
def play(self) -> None: # noqa: D102 | ||
self._protocol_engine.play() | ||
|
||
def pause(self) -> None: # noqa: D102 | ||
self._protocol_engine.pause() | ||
|
||
async def stop(self) -> None: # noqa: D102 | ||
if self.was_started(): | ||
await self._protocol_engine.stop() | ||
else: | ||
await self._protocol_engine.finish( | ||
drop_tips_and_home=False, | ||
set_run_status=False, | ||
) |
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 think we can implement these in the abstract itself.
self._protocol_engine.add_plugin( | ||
LegacyContextPlugin(broker=broker, equipment_broker=equipment_broker) | ||
async def load(self, protocol_source: ProtocolSource) -> None: # noqa: D102 | ||
raise NotImplementedError( |
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.
Raise a more appropriate error
async def create_simulating_runner(robot_type: RobotType) -> ProtocolRunner: | ||
"""Create a ProtocolRunner wired to a simulating HardwareControlAPI. | ||
async def create_simulating_runner( | ||
robot_type: RobotType, protocol_config: ProtocolConfig |
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.
See if accepting a protocol_type
makes more sense here.
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.
Adding a TODO to address later.
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.
Tested via App branch build, successfully analyzed python and json protocols. ✅
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.
Comments from live review.
await self._protocol_engine.stop() | ||
else: | ||
await self._protocol_engine.finish( | ||
drop_tips_and_home=False, |
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.
Investigate if this should be actually true.
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.
Our current code in edge does tip drop only after a clean protocol run finish and not in runner.stop
(run cancellation) so this keeps that behavior as is and is correct.
api/tests/opentrons/protocol_runner/smoke_tests/test_protocol_runner.py
Outdated
Show resolved
Hide resolved
from opentrons.protocol_runner import create_simulating_runner | ||
from opentrons.protocols.api_support.types import APIVersion | ||
|
||
|
||
# TODO (tz, 6-17-22): API version 3.x in-development. |
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.
Check what's going on here. Why's this xfailing?
@@ -1,6 +1,6 @@ | |||
"""Smoke tests for the ProtocolRunner and ProtocolEngine classes. | |||
"""Smoke tests for the AbstractRunner and ProtocolEngine classes. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
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.
There's an integration test for LiveRunner which covers the requirement.
api/tests/opentrons/protocol_runner/test_legacy_command_mapper.py
Outdated
Show resolved
Hide resolved
|
||
|
||
@pytest.fixture | ||
def legacy_subject( |
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.
Rename to python_runner_subject
?
await runner.load(protocol.source) | ||
else: # Why does linter not like `else:`..? |
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 think this is outdated comment.
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.
This looks like a big improvement, thanks @TamarZanzouri and @sanni-t. It's nice that JSON runs don't have to care about dependencies for Python runs anymore, and vice-versa. Looks good to me to merge once comments are resolved.
Here are a bunch of little things, sorry for the spam!
api/tests/opentrons/protocol_runner/smoke_tests/test_legacy_command_mapper.py
Outdated
Show resolved
Hide resolved
api/tests/opentrons/protocol_runner/smoke_tests/test_legacy_custom_labware.py
Outdated
Show resolved
Hide resolved
api/tests/opentrons/protocol_runner/smoke_tests/test_legacy_module_commands.py
Outdated
Show resolved
Hide resolved
api/tests/opentrons/protocol_runner/smoke_tests/test_protocol_runner.py
Outdated
Show resolved
Hide resolved
api/tests/opentrons/protocol_runner/smoke_tests/test_protocol_runner.py
Outdated
Show resolved
Hide resolved
robot-server/tests/integration/http_api/runs/test_run_queued_protocol_commands.tavern.yaml
Outdated
Show resolved
Hide resolved
@@ -96,6 +96,8 @@ def read( | |||
) | |||
|
|||
|
|||
# TODO (spp, 2023-04-05): Remove 'legacy' wording since this is the context we are using |
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.
👍
Totally agree with the changes added. Makes sense to move common implementations to the abstract. Thank you for fixing this @sanni-t |
- Use `protocol_source.config` where possible - Some docstring corrections - other small misc cleanup in tests Co-authored-by: Max Marrone <[email protected]>
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.
Woohoo! -=≡ヘ(*・ω・)ノ
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 good!
Overview
Closes RSS-200.
create an abstract interface for
ProtocolRunner
and implement perJsonRunner
PythonAndLegacyRunner
andLiveRunner
.Also fixes a bug that was causing live http runs to finish executing the run after the first command (RSS-214).
Test Plan
Changelog
JsonRunner
PythonAndLegacyRunner
andLiveRunner
.create_simulating_runner
is now constructed per file type.ProtocolAnalyzer
to create on the fly the simulating runner instead of injecting it.Review requests
Risk assessment
Medium-high. need to make sure nothing is effected from the refactor for all protocol types and for posting commands/runs with no protocol.