Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b71358e2cc |
@@ -458,6 +458,13 @@ func putOfTheBus(t *testing.T) {
|
||||
if got := step(); got.Step != puts.Released {
|
||||
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"})
|
||||
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)
|
||||
|
||||
@@ -130,6 +130,9 @@ type putAnswer struct {
|
||||
Module string `json:"module"`
|
||||
puts.Put
|
||||
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.
|
||||
@@ -249,6 +252,8 @@ func (s *putTools) doPuts(args map[string]any) (any, error) {
|
||||
}
|
||||
sort.Strings(keys)
|
||||
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 {
|
||||
node, module, err := puts.ParseKey(key)
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
func applied(w PutWorld, p puts.Put) puts.Put {
|
||||
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
|
||||
}
|
||||
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}
|
||||
return w
|
||||
}, 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},
|
||||
}
|
||||
for _, c := range cases {
|
||||
|
||||
Reference in New Issue
Block a user