feat(workload): switch buildActiveImagesSet to containers index

First consumer migration off the instances table. The image
prune logic now walks the normalized containers.image_ref
column directly — one DB pass against a single table instead
of joining instances against projects to reconstruct the full
"image:tag" string. Demonstrates the consumer-switch pattern
the remaining read sites (proxies, stale scanner, webhook
matcher) will follow.

The legacy `projects []store.Project` parameter is kept on the
function signature for now so call sites don't change in this
commit; the underscore-discard in the body makes it explicit
that it's no longer load-bearing.
This commit is contained in:
2026-05-09 13:47:20 +03:00
parent af82be3fb8
commit 7f2d1bdae1
+13 -17
View File
@@ -245,28 +245,24 @@ func sanitizeDockerLogLine(line string) string {
}
// buildActiveImagesSet returns the set of "image:tag" strings currently used
// by any instance, computed in a single DB pass instead of N×K queries.
// Returning an error (rather than swallowing) prevents prune logic from
// treating a transient DB failure as "nothing is active".
// by any container, computed in a single DB pass against the normalized
// containers index. Returning an error (rather than swallowing) prevents
// prune logic from treating a transient DB failure as "nothing is active".
func buildActiveImagesSet(st *store.Store, projects []store.Project) (map[string]bool, error) {
imageByProject := make(map[string]string, len(projects))
for _, p := range projects {
imageByProject[p.ID] = p.Image
}
instances, err := st.ListAllInstances()
// `projects` is unused now — kept in the signature for back-compat with
// callers that already happen to have the slice. The image_ref column
// holds the full "image:tag" string written by the deployer.
_ = projects
containers, err := st.ListContainers(store.ContainerFilter{})
if err != nil {
return nil, fmt.Errorf("list instances: %w", err)
return nil, fmt.Errorf("list containers: %w", err)
}
active := make(map[string]bool, len(instances))
for _, inst := range instances {
if inst.ImageTag == "" {
active := make(map[string]bool, len(containers))
for _, c := range containers {
if c.ImageRef == "" {
continue
}
image := imageByProject[inst.ProjectID]
if image == "" {
continue
}
active[image+":"+inst.ImageTag] = true
active[c.ImageRef] = true
}
return active, nil
}