-
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.
refactor(robot-server): split apart experimental sessions router (#8057)
Co-authored-by: Sanniti Pimpley <[email protected]>
- Loading branch information
Showing
11 changed files
with
985 additions
and
965 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
"""Sessions router.""" | ||
from fastapi import APIRouter | ||
|
||
from .base_router import base_router | ||
from .commands_router import commands_router | ||
from .actions_router import actions_router | ||
|
||
sessions_router = APIRouter() | ||
|
||
sessions_router.include_router(base_router) | ||
sessions_router.include_router(commands_router) | ||
sessions_router.include_router(actions_router) | ||
|
||
__all__ = ["sessions_router"] |
89 changes: 89 additions & 0 deletions
89
robot-server/robot_server/sessions/router/actions_router.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 |
---|---|---|
@@ -0,0 +1,89 @@ | ||
"""Router for /sessions actions endpoints.""" | ||
from fastapi import APIRouter, Depends, status | ||
from datetime import datetime | ||
from typing_extensions import Literal | ||
|
||
from robot_server.errors import ErrorDetails, ErrorResponse | ||
from robot_server.service.dependencies import get_current_time, get_unique_id | ||
from robot_server.service.task_runner import TaskRunner | ||
from robot_server.service.json_api import RequestModel, ResponseModel | ||
|
||
from ..session_store import SessionStore, SessionNotFoundError | ||
from ..session_view import SessionView | ||
from ..action_models import SessionAction, SessionActionCreateData | ||
from ..engine_store import EngineStore, EngineMissingError | ||
from ..dependencies import get_session_store, get_engine_store | ||
from .base_router import SessionNotFound | ||
|
||
actions_router = APIRouter() | ||
|
||
|
||
class SessionActionNotAllowed(ErrorDetails): | ||
"""An error if one tries to issue an unsupported session action.""" | ||
|
||
id: Literal["SessionActionNotAllowed"] = "SessionActionNotAllowed" | ||
title: str = "Session Action Not Allowed" | ||
|
||
|
||
@actions_router.post( | ||
path="/sessions/{sessionId}/actions", | ||
summary="Issue a control action to the session", | ||
description=( | ||
"Provide an action to the session in order to control execution of the run." | ||
), | ||
status_code=status.HTTP_201_CREATED, | ||
response_model=ResponseModel[SessionAction], | ||
responses={ | ||
status.HTTP_400_BAD_REQUEST: {"model": ErrorResponse[SessionActionNotAllowed]}, | ||
status.HTTP_404_NOT_FOUND: {"model": ErrorResponse[SessionNotFound]}, | ||
}, | ||
) | ||
async def create_session_action( | ||
sessionId: str, | ||
request_body: RequestModel[SessionActionCreateData], | ||
session_view: SessionView = Depends(SessionView), | ||
session_store: SessionStore = Depends(get_session_store), | ||
engine_store: EngineStore = Depends(get_engine_store), | ||
action_id: str = Depends(get_unique_id), | ||
created_at: datetime = Depends(get_current_time), | ||
task_runner: TaskRunner = Depends(TaskRunner), | ||
) -> ResponseModel[SessionAction]: | ||
"""Create a session control action. | ||
Arguments: | ||
sessionId: Session ID pulled from the URL. | ||
request_body: Input payload from the request body. | ||
session_view: Resource model builder. | ||
session_store: Session storage interface. | ||
engine_store: Protocol engine and runner storage. | ||
action_id: Generated ID to assign to the control action. | ||
created_at: Timestamp to attach to the control action. | ||
task_runner: Background task runner. | ||
""" | ||
try: | ||
prev_session = session_store.get(session_id=sessionId) | ||
|
||
action, next_session = session_view.with_action( | ||
session=prev_session, | ||
action_id=action_id, | ||
action_data=request_body.data, | ||
created_at=created_at, | ||
) | ||
|
||
# TODO(mc, 2021-06-11): support actions other than `start` | ||
# TODO(mc, 2021-06-24): ensure the engine homes pipette plungers | ||
# before starting the protocol run | ||
# TODO(mc, 2021-06-30): capture errors (e.g. uncaught Python raise) | ||
# and place them in the session response | ||
task_runner.run(engine_store.runner.run) | ||
|
||
except SessionNotFoundError as e: | ||
raise SessionNotFound(detail=str(e)).as_error(status.HTTP_404_NOT_FOUND) | ||
except EngineMissingError as e: | ||
raise SessionActionNotAllowed(detail=str(e)).as_error( | ||
status.HTTP_400_BAD_REQUEST | ||
) | ||
|
||
session_store.upsert(session=next_session) | ||
|
||
return ResponseModel(data=action) |
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.