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

fix(api): Filter out air_gap() calls as higher-order commands #14985

Merged
merged 5 commits into from
Apr 23, 2024

Conversation

SyntaxColoring
Copy link
Contributor

@SyntaxColoring SyntaxColoring commented Apr 23, 2024

Overview

This fixes RQA-2621.

Test Plan

  • Follow the steps to reproduce in RQA-2621.

This PR adds unit tests and a "mid-level" integration test. @y3rsh mentioned he's working on adding an analysis snapshot test.

Details

Before ~v5.0, Python protocols reported their activity as a nested tree, roughly like this:

  1. Transfer
    1. Aspirate
    2. Dispense
  2. Mix
    1. Aspirate
    2. Dispense

But the Protocol-Engine–based HTTP API introduced in v5.0 could only represent a flat list of the innermost commands. So our mapping logic in LegacyCommandMapper had to filter out the "higher-order" things like transfers and mixes, leaving only the "atomic" things like aspirates and dispenses.

We apparently forgot to filter out air_gap(), which looks like this:

  1. Air gap
    1. Aspirate

The effect of forgetting to filter it out was that the engine would have two commands running at the same time: the outer air gap and the inner aspirate. This was a dormant bug; Protocol Engine is certainly not meant for that to work.

In #14726, we started being stricter about things like not having more than one command running at a time, so this started to raise an AssertionError (correctly, but confusingly).

The fix is just to filter out air gaps, like we filter out transfers, mixes, etc.

Review requests

We should be on the lookout for any other higher-order commands that aren't being filtered out properly.

We should think about ways to make this inherently safer. Like, instead of mapping every command by default and filtering out the ones that we know to be higher-order, we might want to omit commands by default and only map the ones that we know to be at the deepest level of nesting. Or, we might want to defensively code LegacyCommandMapper to automatically close the last command before starting a new one.

Risk assessment

Low risk to the fix, but there's definitely some risk that we're missing similar bugs.

@SyntaxColoring SyntaxColoring requested review from y3rsh and a team April 23, 2024 16:38
@SyntaxColoring SyntaxColoring requested a review from a team as a code owner April 23, 2024 16:38
Copy link
Member

@sanni-t sanni-t left a comment

Choose a reason for hiding this comment

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

LGTM!

assert isinstance(load_well_plate, commands.LoadLabware)
assert isinstance(load_pipette, commands.LoadPipette)
assert isinstance(pick_up_tip, commands.PickUpTip)
# TODO(mm, 2024-04-23): This commands.Custom looks wrong. This should be a commands.MoveToWell.
Copy link
Member

Choose a reason for hiding this comment

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

👀
Might be worth ticketing out if it looks like another bug.

@SyntaxColoring SyntaxColoring merged commit daa51dd into edge Apr 23, 2024
26 checks passed
@SyntaxColoring SyntaxColoring deleted the rqa_2621 branch April 23, 2024 17:05
y3rsh added a commit that referenced this pull request Apr 23, 2024
* edge: (194 commits)
  fix(app): clone run with RTPs from HistoricalProtocolRun (#14959)
  fix(api): Filter out `air_gap()` calls as higher-order commands (#14985)
  fix(app): fix infinitely re-rendering/never rendering firmware success toasts (#14981)
  feat(api): add option to ignore different tip presence states (#14980)
  feat(opentrons-ai-client) add input textbox to container (#14968)
  fix(app): add robotSerialNumber to proceedToRun event (#14976)
  fix(api): remove homing patch fix for right mount when a 96-channel is attached (#14975)
  feat(api-client,app,react-api-client): upload splash logo from desktop app (#14941)
  fix(robot-server): notify /runs when a non-current run is deleted (#14974)
  feature(api, robot-server): Allow fixit commands to recover from an error (#14908)
  feat(hardware-testing): enable multi sensor processing in liquid probe (#14883)
  fix(app): prevent "run again" banner from rendering after navigating away from the current run (#14973)
  refactor(components): refactor roundtab stories (#14956)
  refactor(protocol-designer): assign module slot in createFileWizard instead of modal (#14951)
  fix(app, api-client): fix choose protocol slideout issue (#14949)
  refactor(protocol-designer): tip position modal max values round down (#14972)
  feat(app): add tiprack selection step to quick transfer flow (#14950)
  ci(shared-data): install dependencies in workflow (#14958)
  fix(components): fix icon stories (#14969)
  feat(opentrons-ai-client): introduce react-markdown to chat display component (#14965)
  ...
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.

None yet

2 participants