-
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.
feat(robot-server): Add
PATCH /errorRecovery/settings
endpoint with…
… `enableErrorRecovery` setting (#16355)
- Loading branch information
1 parent
61aa51f
commit 141b2fe
Showing
17 changed files
with
293 additions
and
41 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,5 @@ | ||
"""The implementation of the `/errorRecovery` routes. | ||
Note that much of the code for the overall error recovery feature lives elsewhere, | ||
e.g. in `robot_server.runs`. | ||
""" |
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 @@ | ||
"""The implementation of the `/errorRecovery/settings` routes.""" |
46 changes: 46 additions & 0 deletions
46
robot-server/robot_server/error_recovery/settings/models.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,46 @@ | ||
"""HTTP request/response models for error recovery settings.""" | ||
|
||
|
||
import textwrap | ||
from typing import Annotated | ||
import pydantic | ||
|
||
|
||
class ResponseData(pydantic.BaseModel): | ||
"""Response body data from the `/errorRecovery/settings` endpoints.""" | ||
|
||
enabled: Annotated[ | ||
bool, | ||
pydantic.Field( | ||
description=textwrap.dedent( | ||
"""\ | ||
Whether error recovery mode is globally enabled. | ||
See `PATCH /errorRecovery/settings`. | ||
""" | ||
) | ||
), | ||
] | ||
|
||
|
||
class RequestData(pydantic.BaseModel): | ||
"""Request body data for `PATCH /errorRecovery/settings`.""" | ||
|
||
enabled: Annotated[ | ||
bool | None, | ||
pydantic.Field( | ||
description=textwrap.dedent( | ||
"""\ | ||
If provided, globally enables or disables error recovery mode. | ||
If this is `true`, a run (see the `/runs` endpoints) will *potentially* | ||
enter recovery mode when an error happens, depending on the details of | ||
the error and depending on `/runs/{runId}/errorRecoveryPolicy`. | ||
If this is `false`, a run will just fail if it encounters an error. | ||
The default is `true`. This currently only has an effect on Flex robots. | ||
On OT-2s, error recovery is not supported. | ||
""" | ||
) | ||
), | ||
] = None |
70 changes: 70 additions & 0 deletions
70
robot-server/robot_server/error_recovery/settings/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,70 @@ | ||
"""FastAPI endpoint functions to implement `/errorRecovery/settings`.""" | ||
|
||
|
||
from typing import Annotated | ||
|
||
import fastapi | ||
|
||
from robot_server.service.json_api import PydanticResponse, RequestModel, SimpleBody | ||
from .models import RequestData, ResponseData | ||
from .store import ErrorRecoverySettingStore, get_error_recovery_setting_store | ||
|
||
|
||
router = fastapi.APIRouter() | ||
_PATH = "/errorRecovery/settings" | ||
|
||
|
||
@PydanticResponse.wrap_route( | ||
router.get, | ||
path=_PATH, | ||
summary="Get current error recovery settings", | ||
) | ||
async def get_error_recovery_settings( # noqa: D103 | ||
store: Annotated[ | ||
ErrorRecoverySettingStore, fastapi.Depends(get_error_recovery_setting_store) | ||
] | ||
) -> PydanticResponse[SimpleBody[ResponseData]]: | ||
return await _get_current_response(store) | ||
|
||
|
||
@PydanticResponse.wrap_route( | ||
router.patch, | ||
path=_PATH, | ||
summary="Set error recovery settings", | ||
) | ||
async def patch_error_recovery_settings( # noqa: D103 | ||
request_body: RequestModel[RequestData], | ||
store: Annotated[ | ||
ErrorRecoverySettingStore, fastapi.Depends(get_error_recovery_setting_store) | ||
], | ||
) -> PydanticResponse[SimpleBody[ResponseData]]: | ||
if request_body.data.enabled is not None: | ||
store.set_is_enabled(request_body.data.enabled) | ||
return await _get_current_response(store) | ||
|
||
|
||
@PydanticResponse.wrap_route( | ||
router.delete, | ||
path=_PATH, | ||
summary="Reset error recovery settings to defaults", | ||
) | ||
async def delete_error_recovery_settings( # noqa: D103 | ||
store: Annotated[ | ||
ErrorRecoverySettingStore, fastapi.Depends(get_error_recovery_setting_store) | ||
], | ||
) -> PydanticResponse[SimpleBody[ResponseData]]: | ||
store.set_is_enabled(None) | ||
return await _get_current_response(store) | ||
|
||
|
||
async def _get_current_response( | ||
store: ErrorRecoverySettingStore, | ||
) -> PydanticResponse[SimpleBody[ResponseData]]: | ||
is_enabled = store.get_is_enabled() | ||
if is_enabled is None: | ||
# todo(mm, 2024-09-30): This defaulting will probably need to move down a layer | ||
# when we connect this setting to `POST /runs`. | ||
is_enabled = True | ||
return await PydanticResponse.create( | ||
SimpleBody.construct(data=ResponseData.construct(enabled=is_enabled)) | ||
) |
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
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 @@ | ||
# noqa: D104 |
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 @@ | ||
# noqa: D104 |
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,29 @@ | ||
"""Tests for the error recovery settings store.""" | ||
|
||
|
||
from robot_server.error_recovery.settings.store import ErrorRecoverySettingStore | ||
|
||
import pytest | ||
import sqlalchemy | ||
|
||
|
||
@pytest.fixture | ||
def subject( | ||
sql_engine: sqlalchemy.engine.Engine, | ||
) -> ErrorRecoverySettingStore: | ||
"""Return a test subject.""" | ||
return ErrorRecoverySettingStore(sql_engine=sql_engine) | ||
|
||
|
||
def test_error_recovery_setting_store(subject: ErrorRecoverySettingStore) -> None: | ||
"""Test `ErrorRecoverySettingStore`.""" | ||
assert subject.get_is_enabled() is None | ||
|
||
subject.set_is_enabled(is_enabled=False) | ||
assert subject.get_is_enabled() is False | ||
|
||
subject.set_is_enabled(is_enabled=True) | ||
assert subject.get_is_enabled() is True | ||
|
||
subject.set_is_enabled(is_enabled=None) | ||
assert subject.get_is_enabled() is None |
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
Empty file.
88 changes: 88 additions & 0 deletions
88
robot-server/tests/integration/http_api/error_recovery/test_settings.tavern.yaml
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,88 @@ | ||
test_name: Test the /errorRecovery/settings endpoints | ||
|
||
marks: | ||
- usefixtures: | ||
- ot3_server_base_url | ||
|
||
stages: | ||
- name: Get default settings | ||
request: | ||
method: GET | ||
url: '{ot3_server_base_url}/errorRecovery/settings' | ||
response: | ||
status_code: 200 | ||
json: &initial_get_settings_response | ||
data: | ||
enabled: true | ||
|
||
- name: Change settings | ||
request: | ||
method: PATCH | ||
url: '{ot3_server_base_url}/errorRecovery/settings' | ||
json: | ||
data: | ||
enabled: false | ||
response: | ||
status_code: 200 | ||
json: &patch_settings_response | ||
data: | ||
enabled: false | ||
|
||
- name: Get the settings again and make sure they're still changed | ||
request: | ||
method: GET | ||
url: '{ot3_server_base_url}/errorRecovery/settings' | ||
response: | ||
status_code: 200 | ||
json: *patch_settings_response | ||
|
||
- name: Restore defaults | ||
request: | ||
method: DELETE | ||
url: '{ot3_server_base_url}/errorRecovery/settings' | ||
response: | ||
status_code: 200 | ||
json: *initial_get_settings_response | ||
|
||
- name: Get the settings again and make sure they're still the defaults | ||
request: | ||
method: GET | ||
url: '{ot3_server_base_url}/errorRecovery/settings' | ||
response: | ||
status_code: 200 | ||
json: *initial_get_settings_response | ||
|
||
--- | ||
test_name: Test no-op PATCH requests | ||
|
||
marks: | ||
- usefixtures: | ||
- ot3_server_base_url | ||
- parametrize: | ||
key: enabled | ||
vals: | ||
- true | ||
- false | ||
|
||
stages: | ||
- name: Set initial settings | ||
request: | ||
method: PATCH | ||
url: '{ot3_server_base_url}/errorRecovery/settings' | ||
json: | ||
data: | ||
enabled: '{enabled}' | ||
response: | ||
save: | ||
json: | ||
initial_response: data | ||
|
||
- name: Send a no-op PATCH and make sure it doesn't change anything | ||
request: | ||
method: PATCH | ||
url: '{ot3_server_base_url}/errorRecovery/settings' | ||
json: | ||
data: {} | ||
response: | ||
json: | ||
data: !force_original_structure '{initial_response}' |
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.