Skip to content

Commit 20ae79f

Browse files
committed
[DOP-34830] Add job to GET /v1/runs response
1 parent 94a3eaf commit 20ae79f

12 files changed

Lines changed: 125 additions & 21 deletions

File tree

data_rentgen/db/repositories/run.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from sqlalchemy.dialects.postgresql import insert
1818
from sqlalchemy.orm import aliased, selectinload
1919

20-
from data_rentgen.db.models import Job, Run, RunStartReason, RunStatus, User
20+
from data_rentgen.db.models import Job, Location, Run, RunStartReason, RunStatus, User
2121
from data_rentgen.db.repositories.base import Repository
2222
from data_rentgen.db.utils.search import make_tsquery, ts_match, ts_rank
2323
from data_rentgen.dto import PaginationDTO, RunDTO
@@ -33,6 +33,7 @@
3333
Run.created_at <= bindparam("until"),
3434
Run.id == any_(bindparam("run_ids")),
3535
)
36+
.options(selectinload(Run.job).joinedload(Job.location).selectinload(Location.addresses))
3637
.options(selectinload(Run.started_by_user))
3738
)
3839

@@ -43,6 +44,7 @@
4344
Run.created_at >= bindparam("since"),
4445
Run.job_id == any_(bindparam("job_ids")),
4546
)
47+
.options(selectinload(Run.job).joinedload(Job.location).selectinload(Location.addresses))
4648
.options(selectinload(Run.started_by_user))
4749
)
4850

@@ -253,7 +255,10 @@ async def paginate( # noqa: PLR0912, C901, PLR0915
253255
# place the most recent runs on top
254256
order_by = [desc("search_rank"), desc("created_at"), desc("id")]
255257

256-
options = [selectinload(Run.started_by_user)]
258+
options = [
259+
selectinload(Run.job).joinedload(Job.location).selectinload(Location.addresses),
260+
selectinload(Run.started_by_user),
261+
]
257262
return await self._paginate_by_query(
258263
query=query,
259264
order_by=order_by,

data_rentgen/server/schemas/v1/job.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,12 @@
66

77
from pydantic import BaseModel, ConfigDict, Field
88

9-
from data_rentgen.server.schemas.v1.location import LocationResponseV1
9+
from data_rentgen.server.schemas.v1.job_response import JobResponseV1
1010
from data_rentgen.server.schemas.v1.pagination import PaginateQueryV1
1111
from data_rentgen.server.schemas.v1.run import RunResponseV1
1212
from data_rentgen.server.schemas.v1.tag import TagResponseV1
1313

1414

15-
class JobResponseV1(BaseModel):
16-
"""Job response"""
17-
18-
id: str = Field(description="Job id", coerce_numbers_to_str=True)
19-
parent_job_id: str | None = Field(description="Parent job id", coerce_numbers_to_str=True, default=None)
20-
location: LocationResponseV1 = Field(description="Corresponding Location")
21-
name: str = Field(description="Job name")
22-
type: str = Field(description="Job type")
23-
24-
model_config = ConfigDict(from_attributes=True)
25-
26-
2715
class JobDetailedResponseV1(BaseModel):
2816
id: str = Field(description="Job id", coerce_numbers_to_str=True)
2917
data: JobResponseV1 = Field(description="Job data")
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# SPDX-FileCopyrightText: 2024-present MTS PJSC
2+
# SPDX-License-Identifier: Apache-2.0
3+
from __future__ import annotations
4+
5+
from pydantic import BaseModel, ConfigDict, Field
6+
7+
from data_rentgen.server.schemas.v1.location import LocationResponseV1
8+
9+
10+
class JobResponseV1(BaseModel):
11+
"""Job response"""
12+
13+
id: str = Field(description="Job id", coerce_numbers_to_str=True)
14+
parent_job_id: str | None = Field(description="Parent job id", coerce_numbers_to_str=True, default=None)
15+
location: LocationResponseV1 = Field(description="Corresponding Location")
16+
name: str = Field(description="Job name")
17+
type: str = Field(description="Job type")
18+
19+
model_config = ConfigDict(from_attributes=True)

data_rentgen/server/schemas/v1/run.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
model_validator,
1818
)
1919

20+
from data_rentgen.server.schemas.v1.job_response import JobResponseV1
2021
from data_rentgen.server.schemas.v1.pagination import PaginateQueryV1
2122
from data_rentgen.server.schemas.v1.user import UserResponseV1
2223

@@ -125,6 +126,7 @@ class RunDetailedResponseV1(BaseModel):
125126

126127
id: UUID = Field(description="Run id")
127128
data: RunResponseV1 = Field(description="Run data")
129+
job: JobResponseV1 = Field(description="Job the run is belongs to")
128130
statistics: RunStatisticsReponseV1 = Field(description="Run statistics")
129131

130132
model_config = ConfigDict(from_attributes=True)

data_rentgen/server/services/run.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from fastapi import Depends
1010
from sqlalchemy import Row
1111

12-
from data_rentgen.db.models import Run, RunStatus
12+
from data_rentgen.db.models import Job, Run, RunStatus
1313
from data_rentgen.dto.pagination import PaginationDTO
1414
from data_rentgen.services.uow import UnitOfWork
1515

@@ -59,6 +59,7 @@ class RunServiceStatistics:
5959
class RunServicePageItem:
6060
id: UUID
6161
data: Run
62+
job: Job
6263
statistics: RunServiceStatistics
6364

6465

@@ -120,6 +121,7 @@ async def paginate(
120121
RunServicePageItem(
121122
id=run.id,
122123
data=run,
124+
job=run.job,
123125
statistics=RunServiceStatistics(
124126
inputs=RunServiceIOStatistics.from_row(input_stats.get(run.id)),
125127
outputs=RunServiceIOStatistics.from_row(output_stats.get(run.id)),
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
Add ``job`` to ``GET /v1/runs`` response.
2+
3+
Before:
4+
5+
.. code:: json
6+
7+
{
8+
"meta": {
9+
"page": 1,
10+
"page_size": 20,
11+
"total_count": 1,
12+
"pages_count": 1,
13+
"has_next": False,
14+
"has_previous": False,
15+
"next_page": None,
16+
"previous_page": None,
17+
},
18+
"items": [
19+
{
20+
"id": "01908224-8410-79a2-8de6-a769ad6944c9",
21+
"data": {
22+
"id": "01908224-8410-79a2-8de6-a769ad6944c9",
23+
"created_at": "2024-07-05T09:05:49.584000",
24+
"job_id": "123",
25+
...
26+
},
27+
"statistics": { ... }
28+
}
29+
]
30+
}
31+
32+
33+
After:
34+
35+
.. code:: json
36+
37+
{
38+
"meta": {
39+
"page": 1,
40+
"page_size": 20,
41+
"total_count": 1,
42+
"pages_count": 1,
43+
"has_next": False,
44+
"has_previous": False,
45+
"next_page": None,
46+
"previous_page": None,
47+
},
48+
"items": [
49+
{
50+
"id": "01908224-8410-79a2-8de6-a769ad6944c9",
51+
"data": {
52+
"id": "01908224-8410-79a2-8de6-a769ad6944c9",
53+
"created_at": "2024-07-05T09:05:49.584000",
54+
"job_id": "123",
55+
...
56+
},
57+
"job": {
58+
"id": "123",
59+
"name": "myjob",
60+
...
61+
},
62+
"statistics": { ... }
63+
}
64+
]
65+
}

tests/test_server/fixtures/factories/run.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ async def runs_with_same_parent(
159159
request: pytest.FixtureRequest,
160160
async_session_maker: Callable[[], AbstractAsyncContextManager[AsyncSession]],
161161
user: User,
162+
job: Job,
162163
) -> AsyncGenerator[list[Run], None]:
163164
size, params = request.param
164165
started_at = datetime.now(tz=UTC)
@@ -169,6 +170,7 @@ async def runs_with_same_parent(
169170
await create_run(
170171
async_session,
171172
run_kwargs={
173+
"job_id": job.id,
172174
"parent_run_id": parent_run_id,
173175
# To be sure runs has different timestamps
174176
"created_at": started_at + timedelta(seconds=s),

tests/test_server/test_runs/test_get_runs.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from data_rentgen.db.models.run import Run
1010
from data_rentgen.utils.uuid import generate_new_uuid
1111
from tests.fixtures.mocks import MockedUser
12-
from tests.test_server.utils.convert_to_json import run_to_json
12+
from tests.test_server.utils.convert_to_json import job_to_json, run_to_json
1313
from tests.test_server.utils.enrich import enrich_runs
1414

1515
pytestmark = [pytest.mark.server, pytest.mark.asyncio]
@@ -119,6 +119,7 @@ async def test_get_runs_with_since(
119119
{
120120
"id": str(run.id),
121121
"data": run_to_json(run),
122+
"job": job_to_json(run.job),
122123
"statistics": {
123124
"inputs": {
124125
"total_datasets": 0,
@@ -179,6 +180,7 @@ async def test_get_runs_with_until(
179180
{
180181
"id": str(run.id),
181182
"data": run_to_json(run),
183+
"job": job_to_json(run.job),
182184
"statistics": {
183185
"inputs": {
184186
"total_datasets": 0,
@@ -243,6 +245,7 @@ async def test_get_runs_with_job_type(
243245
{
244246
"id": str(run.id),
245247
"data": run_to_json(run),
248+
"job": job_to_json(run.job),
246249
"statistics": {
247250
"inputs": {
248251
"total_datasets": 0,
@@ -292,6 +295,7 @@ async def test_get_runs_with_job_type(
292295
{
293296
"id": str(run.id),
294297
"data": run_to_json(run),
298+
"job": job_to_json(run.job),
295299
"statistics": {
296300
"inputs": {
297301
"total_datasets": 0,
@@ -356,6 +360,7 @@ async def test_get_runs_with_status(
356360
{
357361
"id": str(run.id),
358362
"data": run_to_json(run),
363+
"job": job_to_json(run.job),
359364
"statistics": {
360365
"inputs": {
361366
"total_datasets": 0,
@@ -404,6 +409,7 @@ async def test_get_runs_with_status(
404409
{
405410
"id": str(run.id),
406411
"data": run_to_json(run),
412+
"job": job_to_json(run.job),
407413
"statistics": {
408414
"inputs": {
409415
"total_datasets": 0,
@@ -469,6 +475,7 @@ async def test_get_runs_with_started_at(
469475
{
470476
"id": str(run.id),
471477
"data": run_to_json(run),
478+
"job": job_to_json(run.job),
472479
"statistics": {
473480
"inputs": {
474481
"total_datasets": 0,
@@ -535,6 +542,7 @@ async def test_get_runs_with_ended_at(
535542
{
536543
"id": str(run.id),
537544
"data": run_to_json(run),
545+
"job": job_to_json(run.job),
538546
"statistics": {
539547
"inputs": {
540548
"total_datasets": 0,
@@ -601,6 +609,7 @@ async def test_get_runs_with_location_id(
601609
{
602610
"id": str(run.id),
603611
"data": run_to_json(run),
612+
"job": job_to_json(run.job),
604613
"statistics": {
605614
"inputs": {
606615
"total_datasets": 0,
@@ -650,6 +659,7 @@ async def test_get_runs_with_location_id(
650659
{
651660
"id": str(run.id),
652661
"data": run_to_json(run),
662+
"job": job_to_json(run.job),
653663
"statistics": {
654664
"inputs": {
655665
"total_datasets": 0,
@@ -715,6 +725,7 @@ async def test_get_runs_with_started_by_user(
715725
{
716726
"id": str(run.id),
717727
"data": run_to_json(run),
728+
"job": job_to_json(run.job),
718729
"statistics": {
719730
"inputs": {
720731
"total_datasets": 0,
@@ -764,6 +775,7 @@ async def test_get_runs_with_started_by_user(
764775
{
765776
"id": str(run.id),
766777
"data": run_to_json(run),
778+
"job": job_to_json(run.job),
767779
"statistics": {
768780
"inputs": {
769781
"total_datasets": 0,

tests/test_server/test_runs/test_get_runs_by_id.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from data_rentgen.db.models import Run
99
from tests.fixtures.mocks import MockedUser
10-
from tests.test_server.utils.convert_to_json import run_to_json
10+
from tests.test_server.utils.convert_to_json import job_to_json, run_to_json
1111
from tests.test_server.utils.enrich import enrich_runs
1212
from tests.test_server.utils.lineage_result import LineageResult
1313

@@ -71,6 +71,7 @@ async def test_get_runs_by_one_id(
7171
{
7272
"id": str(run.id),
7373
"data": run_to_json(run),
74+
"job": job_to_json(run.job),
7475
"statistics": {
7576
"inputs": {
7677
"total_datasets": 0,
@@ -124,6 +125,7 @@ async def test_get_runs_by_multiple_ids(
124125
{
125126
"id": str(run.id),
126127
"data": run_to_json(run),
128+
"job": job_to_json(run.job),
127129
"statistics": {
128130
"inputs": {
129131
"total_datasets": 0,
@@ -222,6 +224,7 @@ async def test_get_runs_by_multiple_ids_with_stats(
222224
{
223225
"id": str(run.id),
224226
"data": run_to_json(run),
227+
"job": job_to_json(run.job),
225228
"statistics": {
226229
"inputs": input_stats[run.id],
227230
"outputs": output_stats[run.id],

tests/test_server/test_runs/test_get_runs_by_job_id.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from data_rentgen.db.models import Job, Run
99
from tests.fixtures.mocks import MockedUser
10-
from tests.test_server.utils.convert_to_json import run_to_json
10+
from tests.test_server.utils.convert_to_json import job_to_json, run_to_json
1111
from tests.test_server.utils.enrich import enrich_runs
1212

1313
pytestmark = [pytest.mark.server, pytest.mark.asyncio]
@@ -126,6 +126,7 @@ async def test_get_runs_by_job_id(
126126
{
127127
"id": str(run.id),
128128
"data": run_to_json(run),
129+
"job": job_to_json(run.job),
129130
"statistics": {
130131
"inputs": {
131132
"total_datasets": 0,
@@ -187,6 +188,7 @@ async def test_get_runs_by_job_id_with_until(
187188
{
188189
"id": str(run.id),
189190
"data": run_to_json(run),
191+
"job": job_to_json(run.job),
190192
"statistics": {
191193
"inputs": {
192194
"total_datasets": 0,

0 commit comments

Comments
 (0)