Record the bases a build copies, keep them by the builds that stood on them, and copy each image once
A copied base was named only in what a build stood on, and nowhere when the build failed, so the store's sweep could never let one go (hq issue 321). One repository per upstream image stops each module asking the public registry for the same image again, and letting an index go now takes its own platform manifests, which otherwise kept every byte. A person can record the copies no record names through the new mirrors verb (hq ADR 0257). The forge test fix is the same commit as on feat/plain-notifications: main fails without it.
This commit is contained in:
@@ -37,6 +37,10 @@ const (
|
||||
// KeptUnaddressable: it names no digest, so nothing here can speak for it, and it is kept rather
|
||||
// than guessed about.
|
||||
KeptUnaddressable = "unaddressable"
|
||||
// KeptStoodOn: it is a base the mesh copied in, and one of the KeptBuilds most recent successful
|
||||
// builds of a module the mesh still holds stood on it (novox/hq ADR 0257). A copy has no builds of
|
||||
// its own; it is kept by the builds that used it.
|
||||
KeptStoodOn = "stood-on"
|
||||
)
|
||||
|
||||
// The states an artifact the mesh recorded making is in (novox/hq ADR 0251).
|
||||
@@ -77,7 +81,7 @@ func (i *Inventory) Artifacts(ctx context.Context) ([]ArtifactState, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
all, err := i.everyReferenceMade(ctx)
|
||||
all, err := i.everyReferenceRecorded(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -156,8 +160,9 @@ func (i *Inventory) KeepSet(ctx context.Context) (map[string][]string, error) {
|
||||
// join every module ever built kept five builds' artifacts for ever — and once the store's
|
||||
// collector runs for real, what the keep set says is what the disk holds.
|
||||
recent, err := i.store.Pool().Query(ctx,
|
||||
`select made from (
|
||||
select b.made, row_number() over (partition by b.module order by b.at desc, b.id desc) as back
|
||||
`select made, built_against from (
|
||||
select b.made, b.built_against,
|
||||
row_number() over (partition by b.module order by b.at desc, b.id desc) as back
|
||||
from build b
|
||||
join module m on m.name = b.module
|
||||
where b.failed = '' and b.module is not null and b.module <> ''
|
||||
@@ -166,18 +171,26 @@ func (i *Inventory) KeepSet(ctx context.Context) (map[string][]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer recent.Close()
|
||||
var stoodOn []string
|
||||
for recent.Next() {
|
||||
var raw []byte
|
||||
if err := recent.Scan(&raw); err != nil {
|
||||
var raw, against []byte
|
||||
if err := recent.Scan(&raw, &against); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var made []Artifact
|
||||
if err := json.Unmarshal(raw, &made); err != nil {
|
||||
continue
|
||||
if err := json.Unmarshal(raw, &made); err == nil {
|
||||
for _, a := range made {
|
||||
if reference := asRecorded(a.Reference); reference != "" {
|
||||
because(reference, KeptByRecentBuild)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, a := range made {
|
||||
if reference := asRecorded(a.Reference); reference != "" {
|
||||
because(reference, KeptByRecentBuild)
|
||||
var bases []string
|
||||
if err := json.Unmarshal(against, &bases); err == nil {
|
||||
for _, b := range bases {
|
||||
if reference := asRecorded(b); reference != "" {
|
||||
stoodOn = append(stoodOn, reference)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,6 +198,27 @@ func (i *Inventory) KeepSet(ctx context.Context) (map[string][]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// **A copied base is kept by the kept builds that stood on it, and by nothing else** (novox/hq
|
||||
// ADR 0257). It has no builds of its own to count five of, and no machine is ever handed a base,
|
||||
// so a definition is never its reason: a definition names the image upstream, by the digest every
|
||||
// copy of it shares, and read as a reason it would keep every module's copy for as long as any
|
||||
// module stood on that image. A copy already let go of stays let go of.
|
||||
mirrored, err := i.mirroredSet(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(mirrored) > 0 {
|
||||
collected, err := i.alreadyCollected(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, reference := range stoodOn {
|
||||
if mirrored[reference] && !collected[reference] {
|
||||
because(reference, KeptStoodOn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And anything a manifest mentions — every reference ever made, the recent ones included, so a
|
||||
// kept artifact carries each of its reasons and the operator reads why, not only that (novox/hq
|
||||
// ADR 0251). A manifest holds a reference composed with the store's address or kept bare, so the
|
||||
@@ -195,6 +229,9 @@ func (i *Inventory) KeepSet(ctx context.Context) (map[string][]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
for _, reference := range all {
|
||||
if mirrored[reference] {
|
||||
continue
|
||||
}
|
||||
digest := digestIn(reference)
|
||||
if digest == "" {
|
||||
// Not something the store holds by digest; nothing here can speak for it, so it
|
||||
@@ -237,6 +274,72 @@ func (i *Inventory) KeptArchives(ctx context.Context) ([]string, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// KeptImages is every image the mesh keeps, in a stated order: the manifests whose platform manifests
|
||||
// a sweep spares when it lets an index of the same repository go (novox/hq ADR 0257).
|
||||
func (i *Inventory) KeptImages(ctx context.Context) ([]string, error) {
|
||||
keep, err := i.KeepSet(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []string
|
||||
for reference := range keep {
|
||||
if path, ours := catalogue.InArtifactStore(reference); ours && strings.Contains(path, "@sha256:") {
|
||||
out = append(out, reference)
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// everyReferenceRecorded is every artifact the mesh recorded putting in its store: what each
|
||||
// successful build made, and every base a build — or a person — recorded copying in (novox/hq ADR
|
||||
// 0257). Oldest first, a copy placed at the moment it was recorded.
|
||||
func (i *Inventory) everyReferenceRecorded(ctx context.Context) ([]string, error) {
|
||||
made, err := i.everyReferenceMade(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows, err := i.store.Pool().Query(ctx, `select reference from artifact_mirrored order by at asc, reference asc`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
seen := map[string]bool{}
|
||||
for _, r := range made {
|
||||
seen[r] = true
|
||||
}
|
||||
out := made
|
||||
for rows.Next() {
|
||||
var reference string
|
||||
if err := rows.Scan(&reference); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reference = asRecorded(reference); reference != "" && !seen[reference] {
|
||||
seen[reference] = true
|
||||
out = append(out, reference)
|
||||
}
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// mirroredSet is every base the records say the mesh copied in, as recorded.
|
||||
func (i *Inventory) mirroredSet(ctx context.Context) (map[string]bool, error) {
|
||||
rows, err := i.store.Pool().Query(ctx, `select reference from artifact_mirrored`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
out := map[string]bool{}
|
||||
for rows.Next() {
|
||||
var reference string
|
||||
if err := rows.Scan(&reference); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[asRecorded(reference)] = true
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// everyReferenceMade is every artifact reference any successful build recorded, oldest build first.
|
||||
func (i *Inventory) everyReferenceMade(ctx context.Context) ([]string, error) {
|
||||
rows, err := i.store.Pool().Query(ctx,
|
||||
@@ -331,3 +434,8 @@ func (i *Inventory) MarkCollected(ctx context.Context, references []string) erro
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mirrored is every base the records say the mesh copied into its store (novox/hq ADR 0257).
|
||||
func (i *Inventory) Mirrored(ctx context.Context) (map[string]bool, error) {
|
||||
return i.mirroredSet(ctx)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user