Build a key done before R4e again once, so every bundle and archive the controller delivers names its stored reference (issue 1587, B2, ADR 0498 §8)
This commit is contained in:
@@ -85,9 +85,26 @@ func Unpublished(b delivery.BuilderBuild) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Unreferenced is whether a done build holds a bundle, an archive or an upstream copy that names no reference: a key done
|
||||
// before R4e, whose artifacts stayed on their build nodes (ADR 0498 clause 8). An artifact of no kind (a key written before
|
||||
// kinds) is one too. Claim takes such a key again, once: its new revision names them.
|
||||
func Unreferenced(b delivery.BuilderBuild) bool {
|
||||
if b.State != delivery.BuildDone {
|
||||
return false
|
||||
}
|
||||
for _, a := range b.Artifacts {
|
||||
if a.Reference == "" && (a.Kind == "" || stored(a.Kind)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Claim takes the build of module at fingerprint, or answers nil when it is not this builder's to build now:
|
||||
// - no key: it is created building, by this builder; a create that finds the key made meanwhile gets nothing;
|
||||
// - a done key is not taken again (the same source is never built twice), except one built on one node only (OneNodePrefix)
|
||||
// - a done key is not taken again (the same source is never built twice), except one whose bundle, archive or upstream
|
||||
// copy names no reference (Unreferenced, a key done before R4e: ADR 0498 clause 8), which is claimed building as a new
|
||||
// revision and built whole, and one built on one node only (OneNodePrefix)
|
||||
// when a second node qualifies now (ClaimOptions.MoreNodes): that is taken as it stands, with the done value, and its
|
||||
// builder writes the new revision when the second build ends (ADR 0478 clause 4);
|
||||
// - a failed key is taken again as a new revision of the same key (ADR 0429 clause 18), except one failed for a kind no
|
||||
@@ -115,6 +132,9 @@ func (c Claimer) Claim(ctx context.Context, module, fingerprint, manifest string
|
||||
}
|
||||
switch {
|
||||
case cur.State == delivery.BuildDone:
|
||||
if Unreferenced(cur) {
|
||||
return c.write(ctx, key, building, func(data []byte) (uint64, error) { return c.Store.Update(ctx, key, data, rev) })
|
||||
}
|
||||
if modules := OneNodeModules(cur); len(modules) > 0 && opt.MoreNodes != nil && opt.MoreNodes(modules) {
|
||||
return &Claim{Key: key, Rev: rev, Build: cur}, nil
|
||||
}
|
||||
|
||||
@@ -125,9 +125,9 @@ func TestClaimLosingTheCreateRaceGetsNothing(t *testing.T) { // 1607/AC3
|
||||
}
|
||||
}
|
||||
|
||||
func TestADoneKeyIsNeverTakenAgain(t *testing.T) { // 1607/AC3
|
||||
func TestADoneKeyIsNeverTakenAgain(t *testing.T) { // 1607/AC3; a key whose artifacts name references (ADR 0498 clause 8)
|
||||
st := newMem()
|
||||
seed(t, st, delivery.BuilderBuild{State: delivery.BuildDone, By: "novox.a", Manifest: hex64('a'), Artifacts: []delivery.BuiltArtifact{{Name: "x", Digest: digest}}})
|
||||
seed(t, st, delivery.BuilderBuild{State: delivery.BuildDone, By: "novox.a", Manifest: hex64('a'), Artifacts: []delivery.BuiltArtifact{{Name: "x", Kind: "bundle", Digest: digest, Reference: "artifact-store://m/x/blobs/" + digest}}})
|
||||
writes := st.writes
|
||||
got, err := Claimer{Store: st, By: "novox.a"}.Claim(context.Background(), "m", fp1, hex64('a'), ClaimOptions{})
|
||||
if err != nil || got != nil || st.writes != writes {
|
||||
|
||||
@@ -74,3 +74,34 @@ func TestOnlyATrunkKeysBuildsAreAskedToPublish(t *testing.T) { // B1, the lead's
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// putBuild writes a builder key's value as the store would hold it.
|
||||
func putBuild(t *testing.T, st *memStore, key string, b delivery.BuilderBuild) uint64 {
|
||||
t.Helper()
|
||||
data, err := delivery.EncodeBuilderBuild(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st.mu.Lock()
|
||||
defer st.mu.Unlock()
|
||||
return st.put(key, data)
|
||||
}
|
||||
|
||||
func TestADoneKeyWrittenBeforeR4eIsBuiltAgainOnceAsANewRevision(t *testing.T) { // B2, ADR 0498 clause 8
|
||||
r := newRig(t, goBundle, archiveA)
|
||||
rev := putBuild(t, r.st, r.key, delivery.BuilderBuild{State: delivery.BuildDone, By: "novox.builder", Manifest: manifestD, Step: "built mesh-build-go on ace and novox",
|
||||
Artifacts: []delivery.BuiltArtifact{{Name: "files", Kind: "archive", Digest: digest}, {Name: "tool", Kind: "bundle", Digest: digest}}})
|
||||
v := r.consider(t, "modules/m")
|
||||
if v.State != delivery.BuildDone || r.st.revs[r.key] <= rev {
|
||||
t.Fatalf("build = %+v at revision %d (was %d), want built again as a new revision", v, r.st.revs[r.key], rev)
|
||||
}
|
||||
if ok, missing := v.Referenced(); !ok {
|
||||
t.Fatalf("the new revision names no reference for %v", missing)
|
||||
}
|
||||
rev = r.st.revs[r.key]
|
||||
r.b.tried = map[string]bool{} // a builder started anew looks again
|
||||
r.consider(t, "modules/m")
|
||||
if r.st.revs[r.key] != rev {
|
||||
t.Errorf("a key whose artifacts all name references was built again (revision %d, was %d): once only", r.st.revs[r.key], rev)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user