Let platform manifests go only on a confirmed collect, and copy again what a sweep took
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

An unrecorded index or a copy in progress can name a platform the records do not see, so
only a person's collect, after its dry run, takes an index's platforms, and only once every
kept index of each repository it touches was read. A copy missing a platform is copied
again, and a copy a build holds again is no longer recorded as collected (review of #144).
This commit is contained in:
jochen
2026-10-08 15:32:10 +02:00
parent 7edfb56e7a
commit 1cdd9df581
12 changed files with 485 additions and 48 deletions
+38 -28
View File
@@ -169,44 +169,54 @@ func (s Store) Platforms(ctx context.Context, repository, digest string) ([]stri
return out, nil
}
// SpareKeptIndexes is a Spare for a sweep: the platform manifests the kept references of each
// repository name, read from the store once per repository and remembered for the sweep. A kept
// reference itself is spared too. A kept index the store does not hold names nothing.
func (s Store) SpareKeptIndexes(kept []string) func(ctx context.Context, repository string) (map[string]bool, error) {
byRepository := map[string][]string{}
for _, reference := range kept {
// SpareKeptIndexes is a Spare for a sweep, read whole before it starts: for every repository an
// image reference of `touching` is in, each kept manifest there and every platform manifest a kept
// index there names. Any read that fails is an error, and the sweep lets nothing go. A repository not
// read here is answered with an error, so an index in it is kept. A kept index the store no longer
// holds names nothing.
func (s Store) SpareKeptIndexes(ctx context.Context, kept, touching []string) (func(context.Context, string) (map[string]bool, error), error) {
imageIn := func(reference string) (repository, digest string, ok bool) {
path, ours := catalogue.InArtifactStore(reference)
if !ours {
continue
return "", "", false
}
repository, kind, digest, err := split(path)
if err != nil || kind != "manifests" {
continue
return "", "", false
}
byRepository[repository] = append(byRepository[repository], digest)
return repository, digest, true
}
read := map[string]map[string]bool{}
return func(ctx context.Context, repository string) (map[string]bool, error) {
if spared, done := read[repository]; done {
return spared, nil
for _, reference := range touching {
if repository, _, ok := imageIn(reference); ok {
read[repository] = map[string]bool{}
}
spared := map[string]bool{}
for _, digest := range byRepository[repository] {
spared[digest] = true
children, err := s.Platforms(ctx, repository, digest)
if errors.Is(err, Gone) {
continue
}
if err != nil {
return nil, err
}
for _, c := range children {
spared[c] = true
}
}
read[repository] = spared
return spared, nil
}
for _, reference := range kept {
repository, digest, ok := imageIn(reference)
spared, touched := read[repository]
if !ok || !touched {
continue
}
spared[digest] = true
children, err := s.Platforms(ctx, repository, digest)
if errors.Is(err, Gone) {
continue
}
if err != nil {
return nil, fmt.Errorf("reading the kept %s@%s: %w", repository, digest, err)
}
for _, c := range children {
spared[c] = true
}
}
return func(_ context.Context, repository string) (map[string]bool, error) {
spared, done := read[repository]
if !done {
return nil, fmt.Errorf("%s was not read before the sweep began", repository)
}
return spared, nil
}, nil
}
// remove asks the store to delete what is at url. Gone when it has no such thing.