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

feat(robot-server): Return a currentlyRecoveringFrom command pointer #15198

Merged
merged 11 commits into from
May 21, 2024
24 changes: 12 additions & 12 deletions api/src/opentrons/protocol_engine/state/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,13 +606,13 @@ def get_current(self) -> Optional[CurrentCommand]:
index=running_command.index,
)

final_command = self.get_final_command()
if final_command:
most_recently_finalized_command = self.get_most_recently_finalized_command()
if most_recently_finalized_command:
return CurrentCommand(
command_id=final_command.command.id,
command_key=final_command.command.key,
created_at=final_command.command.createdAt,
index=final_command.index,
command_id=most_recently_finalized_command.command.id,
command_key=most_recently_finalized_command.command.key,
created_at=most_recently_finalized_command.command.createdAt,
index=most_recently_finalized_command.index,
)

return None
Expand Down Expand Up @@ -676,7 +676,7 @@ def get_is_running(self) -> bool:
"""Get whether the protocol is running & queued commands should be executed."""
return self._state.queue_status == QueueStatus.RUNNING

def get_final_command(self) -> Optional[CommandEntry]:
def get_most_recently_finalized_command(self) -> Optional[CommandEntry]:
"""Get the most recent command that has reached its final `status`. See get_command_is_final."""
run_requested_to_stop = self._state.run_result is not None

Expand All @@ -689,22 +689,22 @@ def get_final_command(self) -> Optional[CommandEntry]:
else:
return self._state.command_history.get_prev(tail_command.command.id)
else:
final_command = self._state.command_history.get_terminal_command()
most_recently_finalized = self._state.command_history.get_terminal_command()
# This iteration is effectively O(1) as we'll only ever have to iterate one or two times at most.
while final_command is not None:
while most_recently_finalized is not None:
next_command = self._state.command_history.get_next(
final_command.command.id
most_recently_finalized.command.id
)
if (
next_command is not None
and next_command.command.status != CommandStatus.QUEUED
and next_command.command.status != CommandStatus.RUNNING
):
final_command = next_command
most_recently_finalized = next_command
else:
break

return final_command
return most_recently_finalized

def get_command_is_final(self, command_id: str) -> bool:
"""Get whether a given command has reached its final `status`.
Expand Down
27 changes: 20 additions & 7 deletions robot-server/robot_server/runs/command_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""

from datetime import datetime
from textwrap import dedent
from typing import Optional

from pydantic import BaseModel, Field
Expand All @@ -29,18 +30,17 @@ class CommandLinkMeta(BaseModel):

runId: str = Field(..., description="The ID of the command's run.")
commandId: str = Field(..., description="The ID of the command.")
index: int = Field(..., description="Index of the command in the overall list.")
key: str = Field(..., description="Value of the current command's `key` field.")
createdAt: datetime = Field(
...,
description="When the current command was created.",
index: int = Field(
..., description="The index of the command in the run's overall command list."
)
key: str = Field(..., description="The value of the command's `key` field.")
createdAt: datetime = Field(..., description="When the command was created.")


class CommandLink(BaseModel):
"""A link to a command resource."""

href: str = Field(..., description="The path to a command")
href: str = Field(..., description="The HTTP API path to the command")
meta: CommandLinkMeta = Field(..., description="Information about the command.")


Expand All @@ -49,5 +49,18 @@ class CommandCollectionLinks(BaseModel):

current: Optional[CommandLink] = Field(
None,
description="Path to the currently running or next queued command.",
description="Information about the currently running or next queued command.",
)

recoveryTarget: Optional[CommandLink] = Field(
SyntaxColoring marked this conversation as resolved.
Show resolved Hide resolved
None,
description=dedent(
"""\
Information about the command currently undergoing error recovery.

This is basically the most recent protocol command to have failed,
except that once you complete error recovery (see `GET /runs/{id}/actions`),
this goes back to being `null` or omitted.
"""
),
)
Loading