feat: server-side pagination for job list APIs (#193)#436
Draft
Jinghao-coding wants to merge 3 commits into
Draft
feat: server-side pagination for job list APIs (#193)#436Jinghao-coding wants to merge 3 commits into
Jinghao-coding wants to merge 3 commits into
Conversation
added 3 commits
June 19, 2026 22:19
Backend (backwards compatible): - payload: add ListPageQuery + Normalize/IsPagingRequested helpers - resputil: add optional Facets field to List[T] - vcjob: rewrite 6 list/billing handlers with errgroup-based concurrent rows / total / status+jobType+queue facet queries; legacy callers that don't pass page/page_size still get the full array response - aijob/spjob: accept page/page_size, fall back to legacy ListAll/ListByQueue - aitaskctl: add ListByQueuePaged / ListAllPaged Frontend: - query-table: add serverDriven mode (manual pagination/sorting/filtering, custom facetedUniqueValues provider so filter dropdowns keep "Running (12)" badges, rowCount injection for the pagination summary) - vcjob/billing services: add *Paged variants returning IListResponse<T> - admin-jobs page: opt into serverDriven mode; page/sort/filter/search/days are pushed into the backend request, billing query keyed by the same params - other list pages stay on the legacy client-side path
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary / 摘要
Closes #193 — 为作业列表接口引入服务端分页,并把 admin 作业总览页(
/admin/jobs)切换为服务端驱动的DataTable。其余列表页保留客户端模式。后端完全向后兼容:调用方不传
page/page_size时,仍然返回老的 JSON 数组形态;任意一个传了,就返回{ items, total, facets? }的新信封。中文说明
背景
/v1/vcjobs、/v1/vcjobs/all、/v1/admin/vcjobs、/v1/vcjobs/user/{username}等作业列表接口此前一次性返回全量数据,作业量大的环境(admin 作业管理页)会出现明显延迟。本 PR 把分页下沉到后端,同时通过errgroup并发返回status / job_type / queue三个维度的 facet 计数,前端筛选下拉里Running (12)这种数字徽标的视觉表现保持不变。后端改动
backend/internal/payload/list.go新增:ListPageQuery{Page,PageSize,SortBy,Order}与Normalize() (offset,limit,order)IsPagingRequested()判断调用方是否显式开启分页MaxListPageSize = 200backend/internal/resputil/response.go:List[T]结构增加可选Facets map[string]map[string]int64backend/internal/handler/vcjob/pagination.go(新文件):parseJobFilters把请求拆成 scope 谓词 + 维度谓词fetchJobsPaged用errgroup并发跑「分页 rows / 总数 / 三维 facet GROUP BY」backend/internal/handler/vcjob/vcjob.go:6 个 list / billing handler 共用上面的工具,不传page/page_size时退回原有数组返回,避免破坏现有调用方backend/internal/handler/aijob/emias.go、backend/internal/handler/spjob/spjob.go:新增page/page_size入参,未传时走老逻辑backend/pkg/aitaskctl/task.go:补ListByQueuePaged/ListAllPagedbackend/internal/payload/list_test.go单元测试覆盖Normalize前端改动
frontend/src/services/types.ts:新增IListResponse<T>与IListQueryfrontend/src/services/api/{vcjob,billing}.ts:新增*Paged调用方,老函数保留frontend/src/components/query-table/index.tsx:新增可选的serverDriven模式manualPagination/manualSorting/manualFilteringpageCount/rowCountgetFacetedUniqueValuesprovider 接住后端 facet map,让筛选下拉的Running (12)计数继续显示pagination / sorting / columnFilters / globalFilter状态frontend/src/components/query-table/pagination.tsx:底部计数改用table.getRowCount(),server 模式取后端 total,客户端模式仍取过滤后行数frontend/src/components/job/overview/admin-jobs.tsx:迁移到 server-driven 模式;page / sort / filter / search / days 全部下沉到后端请求;billing 子查询用同一份 params;两个查询都开keepPreviousData让翻页不闪烁视觉与体验
Running (12)计数徽标保留(由后端 facet 提供)keepPreviousData旧数据先撑住,不闪屏total向后兼容性
page/page_sizedata: IJobInfo[](老数组)page=1&page_size=20data: { items, total, facets }(新信封)craterCLI 当前没有 list-jobs 命令,因此不受影响。范围控制
custom-jobs.tsx/emias-jobs.tsx/user-jobs.tsx/portal/overview/portal/jobs/inter仍走客户端模式 + 老接口,依赖isInteracitveJob客户端二次过滤;待后端补interactiveboolean 过滤后再迁移验证步骤
后端:
前端:
Test plan
/v1/admin/vcjobs?page=1&page_size=20应返回{ items, total, facets }IJobInfo[]/admin/jobs:翻页、按 status / jobType / queue 过滤、按 jobName 搜索、按 createdAt 排序,每步在 Network 中应看到带正确 query 的新请求;过滤下拉的计数徽标继续显示/portal/overview、/portal/jobs/inter、custom-jobs、user-jobs)渲染不变craterCLI 不受影响后续
interactive过滤后,迁移custom-jobs.tsx/emias-jobs.tsx(account_id, created_at)、(user_id, created_at)、(status)、(job_type)、(queue)增加索引English summary
This PR introduces server-side pagination for job list APIs and migrates the admin job overview page to a server-driven
DataTable. The backend stays fully backwards-compatible: requests withoutpage/page_sizekeep the legacy array response; either field flips the response into{ items, total, facets? }. Faceted counts are computed concurrently viaerrgroupso the toolbar's "Running (12)" badges remain accurate without extra round trips.Other list pages (
custom-jobs,emias-jobs,user-jobs,portal/overview,portal/jobs/inter) intentionally stay on the client-side path until the backend grows aninteractivefilter; they currently rely on a client-sideisInteracitveJobfilter that does not have a clean server-side equivalent.