Merge pull request 'A put without a hold ends once the node runs its fingerprint healthy' (#192) from fix/1966-put-ends into main
This commit was merged in pull request #192.
This commit is contained in:
@@ -458,6 +458,13 @@ func putOfTheBus(t *testing.T) {
|
|||||||
if got := step(); got.Step != puts.Released {
|
if got := step(); got.Step != puts.Released {
|
||||||
t.Fatalf("released, the put stands at %s", got.Step)
|
t.Fatalf("released, the put stands at %s", got.Step)
|
||||||
}
|
}
|
||||||
|
// A put that stands at an older version than the newest says so (issue 1966): it pins the node's want.
|
||||||
|
okey, _ := puts.Key("g14", "mesh-catalog")
|
||||||
|
older, _ := puts.Encode(puts.Put{FP: meshcatalogclient.SourcePrefix2 + strings.Repeat("b", 64), Why: "old"}.Said(now, puts.Wanted, "wanted"))
|
||||||
|
putsKV.values[okey] = older
|
||||||
|
if l, _ := s.doPuts(map[string]any{"module": "mesh-catalog"}); l.(map[string]any)["puts"].([]putAnswer)[0].Older != fp {
|
||||||
|
t.Errorf("a put older than the newest build says %+v", l)
|
||||||
|
}
|
||||||
listed, _ := s.doPuts(map[string]any{"module": "nats"})
|
listed, _ := s.doPuts(map[string]any{"module": "nats"})
|
||||||
if l := listed.(map[string]any)["puts"].([]putAnswer); len(l) != 1 || l[0].Step != puts.Released || len(l[0].Steps) < 6 {
|
if l := listed.(map[string]any)["puts"].([]putAnswer); len(l) != 1 || l[0].Step != puts.Released || len(l[0].Steps) < 6 {
|
||||||
t.Errorf("puts lists %+v", l)
|
t.Errorf("puts lists %+v", l)
|
||||||
|
|||||||
@@ -130,6 +130,9 @@ type putAnswer struct {
|
|||||||
Module string `json:"module"`
|
Module string `json:"module"`
|
||||||
puts.Put
|
puts.Put
|
||||||
Follow string `json:"follow,omitempty"`
|
Follow string `json:"follow,omitempty"`
|
||||||
|
// Older says a put that has not ended stands at an older version than the newest build, and which that is: it pins the
|
||||||
|
// node's want until it ends or is released.
|
||||||
|
Older string `json:"older-than-newest,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// doPut is the tool assigner_put.
|
// doPut is the tool assigner_put.
|
||||||
@@ -249,6 +252,8 @@ func (s *putTools) doPuts(args map[string]any) (any, error) {
|
|||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
out := []putAnswer{}
|
out := []putAnswer{}
|
||||||
|
newest := map[string]string{} // the indexer's newest fingerprint by module, asked once and only for a put that stands
|
||||||
|
asked := false
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
node, module, err := puts.ParseKey(key)
|
node, module, err := puts.ParseKey(key)
|
||||||
if err != nil || (arg(args, "node") != "" && node != arg(args, "node")) || (arg(args, "module") != "" && module != arg(args, "module")) {
|
if err != nil || (arg(args, "node") != "" && node != arg(args, "node")) || (arg(args, "module") != "" && module != arg(args, "module")) {
|
||||||
@@ -262,7 +267,23 @@ func (s *putTools) doPuts(args map[string]any) (any, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
out = append(out, putAnswer{Node: node, Module: module, Put: p})
|
a := putAnswer{Node: node, Module: module, Put: p}
|
||||||
|
if !puts.Ended(p.Step) {
|
||||||
|
if !asked {
|
||||||
|
asked = true
|
||||||
|
if mods, err := indexerView(s.ask, indexerModules); err == nil {
|
||||||
|
for name, raw := range mods {
|
||||||
|
if m, err := meshcatalogclient.DecodeModule(raw); err == nil {
|
||||||
|
newest[name] = m.Fp2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n := newest[module]; n != "" && n != p.FP {
|
||||||
|
a.Older = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out = append(out, a)
|
||||||
}
|
}
|
||||||
return map[string]any{"puts": out}, nil
|
return map[string]any{"puts": out}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,15 @@ func StepPut(w PutWorld) PutNext {
|
|||||||
// applied is a wanted put once the node's have says how it went: holding or done when it runs the composition healthy.
|
// applied is a wanted put once the node's have says how it went: holding or done when it runs the composition healthy.
|
||||||
func applied(w PutWorld, p puts.Put) puts.Put {
|
func applied(w PutWorld, p puts.Put) puts.Put {
|
||||||
h := w.Have
|
h := w.Have
|
||||||
if h == nil || h.Fp != p.FP || h.Composed != p.Composed {
|
if h == nil || h.Fp != p.FP {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
// A put without a hold ends on the fingerprint alone: a node that composes its own digests no composition of the put's, and
|
||||||
|
// a put that waits for that one pins the module's want for good (issue 1966). A held put keeps its composition.
|
||||||
|
if !p.Hold && h.Phase == nodeengineclient.PhaseRunning && h.Health == nodeengineclient.HealthOK {
|
||||||
|
return p.Said(w.Now, puts.Done, fmt.Sprintf("%s runs %s at %s healthy; the rules write its want again", w.Node, w.Module, short(p.FP)))
|
||||||
|
}
|
||||||
|
if h.Composed != p.Composed {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
|
|||||||
@@ -933,6 +933,21 @@ func stepsOfAPut(t *testing.T) {
|
|||||||
w.Have = &nodeengine.HaveByNodeModuleValue{Fp: fNew, Composed: d.Digest, Phase: nodeengineclient.PhaseRunning, Health: nodeengineclient.HealthOK}
|
w.Have = &nodeengine.HaveByNodeModuleValue{Fp: fNew, Composed: d.Digest, Phase: nodeengineclient.PhaseRunning, Health: nodeengineclient.HealthOK}
|
||||||
return w
|
return w
|
||||||
}, puts.Done, "the rules write its want again", false, false, false},
|
}, puts.Done, "the rules write its want again", false, false, false},
|
||||||
|
{"wanted without hold, the node composes its own: done at the fingerprint", func() PutWorld {
|
||||||
|
w := bus()
|
||||||
|
w.Put.Hold = false
|
||||||
|
w.Put = w.Put.Said(now, puts.Wanted, "wanted")
|
||||||
|
w.Put.Composed = d.Digest
|
||||||
|
w.Have = &nodeengine.HaveByNodeModuleValue{Fp: fNew, Composed: dig(fOld), Phase: nodeengineclient.PhaseRunning, Health: nodeengineclient.HealthOK}
|
||||||
|
return w
|
||||||
|
}, puts.Done, "the rules write its want again", false, false, false},
|
||||||
|
{"wanted with hold, the node composes its own: stays wanted", func() PutWorld {
|
||||||
|
w := bus()
|
||||||
|
w.Put = w.Put.Said(now, puts.Wanted, "wanted")
|
||||||
|
w.Put.Composed = d.Digest
|
||||||
|
w.Have = &nodeengine.HaveByNodeModuleValue{Fp: fNew, Composed: dig(fOld), Phase: nodeengineclient.PhaseRunning, Health: nodeengineclient.HealthOK}
|
||||||
|
return w
|
||||||
|
}, puts.Wanted, "wanted", false, false, false},
|
||||||
{"released: nothing more", func() PutWorld { w := bus(); w.Put = w.Put.Said(now, puts.Released, "released"); return w }, puts.Released, "released", false, false, false},
|
{"released: nothing more", func() PutWorld { w := bus(); w.Put = w.Put.Said(now, puts.Released, "released"); return w }, puts.Released, "released", false, false, false},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
|
|||||||
Reference in New Issue
Block a user