diff --git a/modules/mesh-delivery-assigner/internal/assign/wants.go b/modules/mesh-delivery-assigner/internal/assign/wants.go index c53f67d..8d0daff 100644 --- a/modules/mesh-delivery-assigner/internal/assign/wants.go +++ b/modules/mesh-delivery-assigner/internal/assign/wants.go @@ -226,7 +226,15 @@ func Wants(m Module, n Nodes, wants map[string]delivery.Want, lastHealthy map[st } before, had := wants[node] var next delivery.Want - if p, put := m.Puts[node]; put { + p, put := m.Puts[node] + if !put && had && before.Put && before.Hold { + // The want is the truth (ADR 0546 clause 5): a want marked put and held stands while its put is not heard (the + // puts not open, or not yet handed after a start); only a put heard released gives it back to the rules. A put + // without hold is not kept this way: its put takes it further once heard. + p, put = delivery.Put{FP: before.FP, Composed: before.Composed, Hold: true, Why: strings.TrimPrefix(before.Words, "put: "), + Step: delivery.PutHolding}, true + } + if put { if want, owns := PutOwns(p); owns { if want != nil { w := *want diff --git a/modules/mesh-delivery-assigner/internal/assign/wants_test.go b/modules/mesh-delivery-assigner/internal/assign/wants_test.go index 7c213b4..69deb19 100644 --- a/modules/mesh-delivery-assigner/internal/assign/wants_test.go +++ b/modules/mesh-delivery-assigner/internal/assign/wants_test.go @@ -397,10 +397,15 @@ func TestTheBusIsNotMovedButItsUserListRevisionIsWrittenAtOnce(t *testing.T) { {"wanted", delivery.PutWanted, wantedOld(), &delivery.Want{FP: fNew, Composed: dig(fNew), Put: true, Hold: true, Words: "put: the bus's user list"}}, {"holding, written already", delivery.PutHolding, map[string]delivery.Want{"ace": PutWant(put)}, nil}, {"released: the rules again", delivery.PutReleased, map[string]delivery.Want{"ace": PutWant(put)}, &delivery.Want{FP: fNew, Composed: dig(fNew)}}, + {"not heard: a held want at an older fingerprint stands", "", map[string]delivery.Want{"ace": {FP: fOld, Composed: dig(fOld), Put: true, Hold: true, Words: "put: back"}}, nil}, + {"not heard: a held want the rules would rewrite stands", "", map[string]delivery.Want{"ace": PutWant(put)}, nil}, } { p := put p.Step = c.step m.Puts = map[string]delivery.Put{"ace": p} + if c.step == "" { + m.Puts = nil + } out := Wants(m, n, c.wanted, nil) got, wrote := out.Wants["ace"] switch {