feat(api): 集群列表读改走 informer 缓存,审核队列、我的提交与备份列表改为服务端分页筛选并一次批量查构建,面板三页跟进

This commit is contained in:
Lemon-miaow committed 2026-09-25 18:13:21 +08:00
1 parent 0a66385d9f
commit 1054e62fa9
41 files changed
+1642 -295

No files matched your search

+21
View File
@@ -198,6 +198,9 @@ type Store interface {
CreateBuild(ctx context.Context, b *Build) error
// GetBuild loads one build, or ErrNotFound.
GetBuild(ctx context.Context, id string) (*Build, error)
// GetBuilds loads the builds among ids that exist, in no particular order and
// without their Dockerfile — one query for a whole list's worth of lookups.
GetBuilds(ctx context.Context, ids []string) ([]Build, error)
// SetBuildJob records the Job name and advances status to building.
SetBuildJob(ctx context.Context, id, jobName string) error
// FinishBuild sets a terminal status, an optional error, and finished_at.
@@ -519,6 +522,24 @@ func (b *Builder) Get(ctx context.Context, id string) (*Build, error) {
return b.Store.GetBuild(ctx, id)
}
// GetMany returns the builds among ids that exist, keyed by id, read as stored
// (no reconcile) and without their Dockerfile. An id with no row is absent from
// the map.
func (b *Builder) GetMany(ctx context.Context, ids []string) (map[string]Build, error) {
out := make(map[string]Build, len(ids))
if len(ids) == 0 {
return out, nil
}
builds, err := b.Store.GetBuilds(ctx, ids)
if err != nil {
return nil, err
}
for _, bld := range builds {
out[bld.ID] = bld
}
return out, nil
}
// ListBuilds pages the build history for the admin panel, so every admin sees
// every build (and can cancel a running one) from any browser. It reads rows as
// stored: reconcileBuilds advances them in the background, and GET
+38
View File
@@ -25,6 +25,8 @@ type fakeStore struct {
removeErr error
createErr error
listOpts ListOpts
getManyCalls int
}
func newFakeStore() *fakeStore {
@@ -49,6 +51,17 @@ func (f *fakeStore) GetBuild(_ context.Context, id string) (*Build, error) {
return &cp, nil
}
func (f *fakeStore) GetBuilds(_ context.Context, ids []string) ([]Build, error) {
f.getManyCalls++
var out []Build
for _, id := range ids {
if b, ok := f.builds[id]; ok {
out = append(out, *b)
}
}
return out, nil
}
func (f *fakeStore) SetBuildJob(_ context.Context, id, jobName string) error {
b, ok := f.builds[id]
if !ok {
@@ -776,3 +789,28 @@ func TestListBuildsBoundsThePage(t *testing.T) {
}
}
}
// GetMany answers a whole list's lookups with one store read, keys the rows by
// id, leaves an unknown id out, and asks nothing of the store for an empty list.
func TestGetManyIsOneRead(t *testing.T) {
b, st, _ := newBuilder()
st.builds["bld-1"] = &Build{ID: "bld-1", Status: StatusFailed, Error: "scan found a CRITICAL CVE"}
st.builds["bld-2"] = &Build{ID: "bld-2", Status: StatusSucceeded}
got, err := b.GetMany(context.Background(), []string{"bld-1", "bld-2", "bld-gone"})
if err != nil {
t.Fatalf("GetMany: %v", err)
}
if st.getManyCalls != 1 {
t.Fatalf("store reads = %d, want 1", st.getManyCalls)
}
if len(got) != 2 || got["bld-1"].Status != StatusFailed || got["bld-1"].Error != "scan found a CRITICAL CVE" ||
got["bld-2"].Status != StatusSucceeded {
t.Fatalf("GetMany = %+v, want bld-1 failed and bld-2 succeeded", got)
}
if _, ok := got["bld-gone"]; ok {
t.Fatal("an unknown id must be absent")
}
if got, err := b.GetMany(context.Background(), nil); err != nil || len(got) != 0 || st.getManyCalls != 1 {
t.Fatalf("GetMany(nil) = %v, %v with %d reads; want an empty map and no read", got, err, st.getManyCalls)
}
}
+10
View File
@@ -36,6 +36,16 @@ func (s *PGStore) GetBuild(ctx context.Context, id string) (*Build, error) {
return s.scanBuild(s.db.QueryRowContext(ctx, q, id))
}
func (s *PGStore) GetBuilds(ctx context.Context, ids []string) ([]Build, error) {
rows, err := s.db.QueryContext(ctx, `SELECT id, image_ref, status, '', context_ref, base_image,
requested_by, job_name, log_ref, error, created_at, finished_at, context_digest
FROM image_builds WHERE id = ANY($1::text[])`, ids)
if err != nil {
return nil, err
}
return scanBuilds(rows)
}
func (s *PGStore) scanBuild(row *sql.Row) (*Build, error) {
var (
b Build