Skip to content

Commit 412a58b

Browse files
peterschmidt85Andrey Cheptsov
andauthored
Optimize /api/runs/list job loading (dstackai#3986)
* Optimize runs list job loading * Refine runs list job loading * Document ps JSON submissions follow-up * Address runs list review comments --------- Co-authored-by: Andrey Cheptsov <andrey.cheptsov@github.com>
1 parent 79e04fd commit 412a58b

9 files changed

Lines changed: 574 additions & 40 deletions

File tree

frontend/src/layouts/AppLayout/TutorialPanel/hooks.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const useTutorials = () => {
4747
const { data: projectData } = useGetProjectsQuery({});
4848
const { data: runsData } = useGetRunsQuery({
4949
limit: 1,
50+
job_submissions_limit: 1,
5051
});
5152

5253
const completeIsChecked = useRef<boolean>(false);

frontend/src/pages/Project/Details/Settings/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export const ProjectSettings: React.FC = () => {
8686
const { data: runsData } = useGetRunsQuery({
8787
project_name: paramProjectName,
8888
limit: 1,
89+
job_submissions_limit: 1,
8990
});
9091

9192
useEffect(() => {

src/dstack/_internal/cli/commands/ps.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def _command(self, args: argparse.Namespace):
6767
if args.watch and args.format == "json":
6868
raise CLIError("JSON output is not supported together with --watch")
6969

70+
# TODO: Add a `ps --json` option to control how many job submissions are returned.
7071
runs = self.api.runs.list(all=args.all, limit=args.last)
7172
deprecated_router_runs = [
7273
run._run.run_spec.run_name

src/dstack/_internal/server/services/projects.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -469,19 +469,24 @@ async def list_user_project_models(
469469
user: UserModel,
470470
only_names: bool = False,
471471
include_members: bool = False,
472+
project_names: Optional[List[str]] = None,
472473
) -> List[ProjectModel]:
473474
load_only_attrs = []
474475
if only_names:
475476
load_only_attrs += [ProjectModel.id, ProjectModel.name]
476477
if user.global_role == GlobalRole.ADMIN:
477478
return await list_project_models(
478-
session=session, load_only_attrs=load_only_attrs, include_members=include_members
479+
session=session,
480+
load_only_attrs=load_only_attrs,
481+
include_members=include_members,
482+
project_names=project_names,
479483
)
480484
return await list_member_project_models(
481485
session=session,
482486
user=user,
483487
load_only_attrs=load_only_attrs,
484488
include_members=include_members,
489+
project_names=project_names,
485490
)
486491

487492

@@ -490,6 +495,7 @@ async def list_member_project_models(
490495
user: UserModel,
491496
include_members: bool = False,
492497
load_only_attrs: Optional[List[QueryableAttribute]] = None,
498+
project_names: Optional[List[str]] = None,
493499
) -> List[ProjectModel]:
494500
"""
495501
List project models for a user where they are a member.
@@ -499,15 +505,14 @@ async def list_member_project_models(
499505
options.append(joinedload(ProjectModel.members))
500506
if load_only_attrs:
501507
options.append(load_only(*load_only_attrs))
502-
res = await session.execute(
503-
select(ProjectModel)
504-
.where(
505-
MemberModel.project_id == ProjectModel.id,
506-
MemberModel.user_id == user.id,
507-
ProjectModel.deleted == False,
508-
)
509-
.options(*options)
510-
)
508+
filters = [
509+
MemberModel.project_id == ProjectModel.id,
510+
MemberModel.user_id == user.id,
511+
ProjectModel.deleted == False,
512+
]
513+
if project_names is not None:
514+
filters.append(ProjectModel.name.in_(project_names))
515+
res = await session.execute(select(ProjectModel).where(*filters).options(*options))
511516
return list(res.scalars().unique().all())
512517

513518

@@ -547,15 +552,17 @@ async def list_project_models(
547552
session: AsyncSession,
548553
load_only_attrs: Optional[List[QueryableAttribute]] = None,
549554
include_members: bool = False,
555+
project_names: Optional[List[str]] = None,
550556
) -> List[ProjectModel]:
551557
options = []
552558
if include_members:
553559
options.append(joinedload(ProjectModel.members))
554560
if load_only_attrs:
555561
options.append(load_only(*load_only_attrs))
556-
res = await session.execute(
557-
select(ProjectModel).where(ProjectModel.deleted == False).options(*options)
558-
)
562+
filters = [ProjectModel.deleted == False]
563+
if project_names is not None:
564+
filters.append(ProjectModel.name.in_(project_names))
565+
res = await session.execute(select(ProjectModel).where(*filters).options(*options))
559566
return list(res.scalars().unique().all())
560567

561568

0 commit comments

Comments
 (0)