Skip to content

Commit

Permalink
Append query param to /runs, run_ids and latest
Browse files Browse the repository at this point in the history
  • Loading branch information
suecharo committed Jul 16, 2024
1 parent 279168a commit fa37a6d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
35 changes: 31 additions & 4 deletions sapporo-wes-spec-2.0.0.yml
Original file line number Diff line number Diff line change
Expand Up @@ -947,9 +947,9 @@ info:
## Executive Summary
he Workflow Execution Service (WES) API provides a standard way for users to submit
workflow requests to workflow execution systems and monitor their execution. This
API lets users run a single workflow (currently [**CWL**](https://www.commonwl.org/)
The Workflow Execution Service (WES) API provides a standard way for users to
submit workflow requests to workflow execution systems and monitor their execution.
This API lets users run a single workflow (currently [**CWL**](https://www.commonwl.org/)
or [**WDL**](http://www.openwdl.org/) formatted workflows, with other types potentially
supported in the future) on multiple different platforms, clouds, and environments.
Expand Down Expand Up @@ -1094,7 +1094,7 @@ paths:
may not represent the latest state.
- If you want to get the latest state of run, use `GET /runs/{run_id}` or
`GET /runs/{run_id}/status`.'
`GET /runs/{run_id}/status` or use `latest=true` query parameter.'
operationId: list_runs_runs_get
parameters:
- description: OPTIONAL The preferred number of workflow runs to return in a
Expand Down Expand Up @@ -1156,6 +1156,33 @@ paths:
description: '**sapporo-wes-2.0.0 extension:**: Filter the runs based on
the state (e.g., "COMPLETE", "RUNNING", etc.).'
title: State
- description: '**sapporo-wes-2.0.0 extension:**: A list of run IDs to retrieve
specific runs.'
in: query
name: run_ids
required: false
schema:
anyOf:
- items:
type: string
type: array
- type: 'null'
description: '**sapporo-wes-2.0.0 extension:**: A list of run IDs to retrieve
specific runs.'
title: Run Ids
- description: '**sapporo-wes-2.0.0 extension:**: If True, return the latest
state of runs instead of the snapshot.'
in: query
name: latest
required: false
schema:
anyOf:
- type: boolean
- type: 'null'
default: false
description: '**sapporo-wes-2.0.0 extension:**: If True, return the latest
state of runs instead of the snapshot.'
title: Latest
responses:
'200':
content:
Expand Down
4 changes: 4 additions & 0 deletions sapporo/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ def list_runs_db(
page_token: Optional[str] = None,
sort_order: Literal["asc", "desc"] = "desc",
state: Optional[State] = None,
run_ids: Optional[List[str]] = None,
username: Optional[str] = None,
) -> Tuple[List[Run], Optional[str]]:
query = select(Run)
Expand All @@ -165,6 +166,9 @@ def list_runs_db(
else:
query = query.order_by(Run.start_time.desc(), Run.run_id.desc()) # type: ignore # pylint: disable=E1101

if run_ids is not None:
query = query.where(Run.run_id.in_(run_ids)) # type: ignore # pylint: disable=E1101

if page_token is not None:
token_data = _decode_page_token(page_token)
start_time = datetime.fromisoformat(token_data["start_time"])
Expand Down
18 changes: 15 additions & 3 deletions sapporo/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async def get_service_info() -> ServiceInfo:
**sapporo-wes-2.0.0 extension:**
- This endpoint returns a snapshot that is aggregated every 30 minutes. It may not represent the latest state.
- If you want to get the latest state of run, use `GET /runs/{run_id}` or `GET /runs/{run_id}/status`.
- If you want to get the latest state of run, use `GET /runs/{run_id}` or `GET /runs/{run_id}/status` or use `latest=true` query parameter.
""",
response_model=RunListResponse,
)
Expand All @@ -72,12 +72,24 @@ async def list_runs(
None,
description='**sapporo-wes-2.0.0 extension:**: Filter the runs based on the state (e.g., "COMPLETE", "RUNNING", etc.).',
),
run_ids: Optional[List[str]] = Query(
None,
description='**sapporo-wes-2.0.0 extension:**: A list of run IDs to retrieve specific runs.',
),
latest: Optional[bool] = Query(
False,
description='**sapporo-wes-2.0.0 extension:**: If True, return the latest state of runs instead of the snapshot.',
),
token: Optional[str] = auth_depends_factory(),
) -> RunListResponse:
username = token and extract_username(decode_token(token))
(db_runs, next_page_token) = list_runs_db(page_size, page_token, sort_order, state, username)
(db_runs, next_page_token) = list_runs_db(page_size, page_token, sort_order, state, run_ids, username)
if latest:
runs = [create_run_summary(run.run_id) for run in db_runs]
else:
runs = db_runs_to_run_summaries(db_runs)
return RunListResponse(
runs=db_runs_to_run_summaries(db_runs),
runs=runs,
next_page_token=next_page_token,
)

Expand Down
22 changes: 22 additions & 0 deletions tests/py_tests/test_get_runs.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,25 @@ def test_get_runs_state(mocker, tmpdir): # type: ignore
assert response.status_code == 200
data = response.json()
assert len(data["runs"]) == 2


def test_get_runs_run_ids(mocker, tmpdir): # type: ignore
client = anyhow_get_test_client(None, mocker, tmpdir)
add_dummy_data() # type: ignore

response = client.get("/runs?run_ids=63d1f6b7-1cfe-44b3-9f66-1640496b1b01&run_ids=4f3de7a3-acb2-4568-b046-5bb7e63fa84c")
assert response.status_code == 200
data = response.json()
assert len(data["runs"]) == 2


def test_get_runs_latest(mocker, tmpdir): # type: ignore
client = anyhow_get_test_client(None, mocker, tmpdir)
run_id = run_cwltool_remote_wf(client) # type: ignore

response = client.get("/runs?latest=true")
assert response.status_code == 200
data = response.json()

assert len(data["runs"]) == 1
assert data["runs"][0]["run_id"] == run_id

0 comments on commit fa37a6d

Please sign in to comment.