Keep a fresh build's archives from the controller's own sweep (issue 1933)
mesh/delivery delivered
mesh/check checking 0741880d3137 on 760351b4ae1b

A sweep read what it keeps before what was ever recorded, so a take-in's
build recorded between the two reads, by a concurrent take-in off the
plans' hold, was eligible and let go of seconds after the take-in read
it; a new module's build is unkept until it is registered. Now the sweep
reads the records first and keeps what a build recorded within the hour
or an open plan names, and names every reference it lets go of; a take-in
holds every artifact in the store before recording, failing on one the
store lacks; and RecordBuild clears artifact_collected as RecordMirrored
does.
This commit is contained in:
2026-10-24 02:44:20 +02:00
parent fdf26a1fe2
commit 0741880d31
9 changed files with 431 additions and 12 deletions
+55
View File
@@ -288,3 +288,58 @@ func TestKeptArchivesAreTheKeptBlobsOnly(t *testing.T) {
}
}
}
// 1933/AC1: a new module's first build, recorded and not yet registered (its take-in still runs), is not offered to
// let go of while it was recorded within the hour; turned off, the window shows what it guards.
func TestANewModulesBuildIsKeptWhileItsTakeInRuns(t *testing.T) {
inv := fresh(t)
ctx := context.Background()
made := built(t, inv, "key-new-1", "brand-new", 1)
inv.keptLately = 0 // KeptLately, as the controller runs
eligible, err := inv.ToCollect(ctx)
if err != nil {
t.Fatal(err)
}
for _, r := range eligible {
if r == made {
t.Fatalf("a build recorded a moment ago, its module not yet registered, is offered: %v", eligible)
}
}
keep, err := inv.KeepSet(ctx)
if err != nil {
t.Fatal(err)
}
if !has(keep[made], KeptByRecentRecord) {
t.Errorf("the keep set says %v of a build recorded a moment ago", keep[made])
}
inv.keptLately = -1
if eligible, err = inv.ToCollect(ctx); err != nil || len(eligible) != 1 || eligible[0] != made {
t.Errorf("without the window the unregistered module's build is offered (the fault of issue 1933): %v %v", eligible, err)
}
}
// 1933/AC3: a reference the records say was collected, and a build then records again, is no longer collected: it is
// held by the keep set and offered again once nothing keeps it.
func TestABuildRecordingACollectedReferenceHoldsItAgain(t *testing.T) {
inv := fresh(t)
ctx := context.Background()
holding(t, inv, "web")
reference := built(t, inv, "b01", "web", 1)
if err := inv.MarkCollected(ctx, []string{reference}); err != nil {
t.Fatal(err)
}
again := aBuild("b02", "web", "")
again.Made = []Artifact{{Name: "app", Kind: "image", Reference: reference}}
if err := inv.RecordBuild(ctx, again); err != nil {
t.Fatal(err)
}
collected, err := inv.alreadyCollected(ctx)
if err != nil {
t.Fatal(err)
}
if collected[reference] {
t.Errorf("a reference a build recorded again is still collected")
}
}