Assigner: the backup row proves the ask and its condition go with the move (issue 1966 note 165, review round 1)
mesh/delivery merged: source.main moved to novox/mesh-delivery@7ba8449ff67c
mesh/check checking 3841a950685b on 7ba8449ff67c

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-10 11:01:56 +01:00
parent 1d654b286d
commit 3841a95068
2 changed files with 12 additions and 17 deletions
@@ -42,7 +42,6 @@ import (
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-teller/tellerevents"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/announce"
"git.novox.be/novox/mesh-sdk/go/buscompose"
@@ -1038,25 +1037,21 @@ func TestABackupAnswerIsWrittenIntoTheNodesWant(t *testing.T) {
if w2.Words == w1.Words {
t.Errorf("the second answer left the want as it was: %+v", w2)
}
// Issue 1966 note 165 (AC165-1, AC165-4): the move is superseded, the trunk and then the want naming another build; the pass takes the backup
// ask away, and the teller's ask-ended for it, said after, writes nothing.
// Issue 1966 note 165 (AC165-1): the move is superseded, the trunk and then the want naming another build; the pass takes
// the backup ask away and clears the condition of the failed backup.
fOther := meshcatalogclient.SourcePrefix2 + strings.Repeat("c", 64)
b.fixture(t, "web", fOther, `{"module":"web","version":"2"}`) // the trunk moves on: the want follows
for deadline := time.Now().Add(15 * time.Second); b.hasKey(buckets.Asks, akey); time.Sleep(50 * time.Millisecond) {
for deadline := time.Now().Add(15 * time.Second); ; time.Sleep(50 * time.Millisecond) {
cleared := false
for k, c := range b.conditionsSaid(t) {
cleared = cleared || (strings.Contains(k, "backup") && c.State == occ.StateCleared)
}
if !b.hasKey(buckets.Asks, akey) && cleared {
break
}
if time.Now().After(deadline) {
t.Fatal("the backup ask of a move the want left behind was not taken away")
t.Fatalf("the backup of a move the want left behind: ask there %v, condition cleared %v", b.hasKey(buckets.Asks, akey), cleared)
}
}
body, err := tellerevents.EncodeEnded(tellerevents.Ended{Key: akey, Ask: a2.Ask.ID, Outcome: occ.OutcomeExpired})
if err != nil {
t.Fatal(err)
}
if _, err := b.js.Publish(b.ctx, askEndedSubject, body); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
if b.hasKey(buckets.Asks, akey) {
t.Error("an ended backup ask whose want moved on was written again")
}
}
@@ -774,7 +774,7 @@ func (p *passer) fingerprintsOf(node, module, trunkFP string) []string {
return out
}
// staleAsks takes away, at every pass, each hold, restore and record ask that staleAsk names (issue 1906, note 28): an ask
// staleAsks takes away, at every pass, each hold, restore, record and backup ask that staleAsk names (issue 1906, note 28): an ask
// outlived its fingerprint, and the teller takes its router ask back from the operator when the key goes. With the trunk not
// read at all (no module), nothing is taken away.
func (p *passer) staleAsks(ctx context.Context, trunk map[string]meshcatalog.ModulesByModuleValue) {