Builder: the start's sweep keeps a key of a fingerprint a followed half's picture holds
The follower closes Ready before it tells its entries, so the sweep at ready could close a building key whose entry was not taken in yet and the entry then asked again (four asks where two). The sweep now takes the fingerprints of the halves' pictures as current. Builds: design 47 G §348, §479 (the builder reads the catalog half per watched branch), issue 1660's sweep Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
"mesh-delivery-builder/internal/build"
|
||||
@@ -184,6 +185,29 @@ func (c *catalogHalf) dropped(state string) {
|
||||
c.checkReady()
|
||||
}
|
||||
|
||||
// pictured are the build keys of the fingerprints the adopted halves' pictures hold, whether or not their entries were told yet.
|
||||
func (c *catalogHalf) pictured() []string {
|
||||
c.mu.Lock()
|
||||
halves := make([]*views.Follower, 0, len(c.halves))
|
||||
for _, f := range c.halves {
|
||||
halves = append(halves, f)
|
||||
}
|
||||
c.mu.Unlock()
|
||||
var keys []string
|
||||
for _, f := range halves {
|
||||
for module, raw := range f.Values() {
|
||||
var e meshcatalog.CatalogEntry
|
||||
if json.Unmarshal(raw, &e) != nil || e.Fp == "" {
|
||||
continue
|
||||
}
|
||||
if k, err := builds.BuilderBuildKey(module, e.Fp); err == nil {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// checkReady calls ready once every adopted half's first view is in.
|
||||
func (c *catalogHalf) checkReady() {
|
||||
c.mu.Lock()
|
||||
|
||||
@@ -433,7 +433,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
// a holder of the seat that is down holds no other part of it).
|
||||
half.b = b
|
||||
half.ready = func() {
|
||||
if err := b.Sweep(ctx); err != nil {
|
||||
if err := b.Sweep(ctx, half.pictured()...); err != nil {
|
||||
errs <- err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,3 +46,22 @@ func TestSweepLeavesAKeyOfTheModulesCurrentFingerprintForTheBuildToTakeOver(t *t
|
||||
t.Errorf("build = %+v, want done by novox.builder", v)
|
||||
}
|
||||
}
|
||||
|
||||
// A key of a fingerprint a followed half's picture holds is not closed at start, though its entry is not taken in yet: the
|
||||
// follower is ready before it tells its entries (design 47 G A-107's restart case: the builder put its asks a second time).
|
||||
func TestSweepLeavesAKeyOfAPicturedFingerprintBuildingBeforeItsEntryIsTakenIn(t *testing.T) {
|
||||
r := newRig(t, goBundle)
|
||||
seed(t, r.st, builds.BuilderBuild{State: builds.BuildBuilding, By: "ace.builder", Manifest: manifestD})
|
||||
if err := r.b.Sweep(context.Background(), r.key); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v := valueOf(t, r.st, r.key); v.State != builds.BuildBuilding {
|
||||
t.Errorf("build = %+v, want it left building for the entry to take over", v)
|
||||
}
|
||||
if err := r.b.Sweep(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v := valueOf(t, r.st, r.key); v.State != builds.BuildFailed {
|
||||
t.Errorf("without a picture naming it the key is closed: %+v", v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +321,11 @@ func (b *Builder) NodesChanged(ctx context.Context) { b.Reconsider(ctx) }
|
||||
// module no longer has (issue 1660, ADR 0478 clause 6): the key can never be built, since nothing asks for it, and would
|
||||
// stay building for ever. It fails the key naming who left it. A key of the fingerprint the module has now is not
|
||||
// touched: the build takes it over. Call it once the modules bucket has been read, so every module is known.
|
||||
func (b *Builder) Sweep(ctx context.Context) error {
|
||||
//
|
||||
// pictured are the build keys the followed halves' pictures name as current: a follower is ready before it has told its
|
||||
// entries (views.Follower closes Ready, then calls Changed), so at ready the entries may not be taken in yet, and a key of
|
||||
// a fingerprint a picture holds is never closed for want of the entry's arrival (the restart that put its asks a second time).
|
||||
func (b *Builder) Sweep(ctx context.Context, pictured ...string) error {
|
||||
b.init()
|
||||
keys, err := b.Claimer.Store.Keys(ctx)
|
||||
if err != nil {
|
||||
@@ -329,6 +333,9 @@ func (b *Builder) Sweep(ctx context.Context) error {
|
||||
}
|
||||
b.mu.Lock()
|
||||
current := map[string]bool{}
|
||||
for _, k := range pictured {
|
||||
current[k] = true
|
||||
}
|
||||
// What every followed branch carries now is current, not only the first branch's (design 47 G §348).
|
||||
for _, held := range []map[string]meshcatalog.ModulesByModuleValue{b.known, b.heard} {
|
||||
for hk, m := range held {
|
||||
|
||||
Reference in New Issue
Block a user