The bus module's have names what its server runs, and a node's have what its agent keeps (ADR 0594 §4, §8)
This commit is contained in:
+23
-1
@@ -360,6 +360,12 @@ type Have struct {
|
||||
// slot that holds it, so a provider and a consumer of one value on one node each keep their own. Written in Sealed's
|
||||
// place by a node-engine that knows it; Sealed is read only from a have written before.
|
||||
SealedAt Seals `json:"sealed-at,omitempty"`
|
||||
// Server is, in the have of the bus module, what the bus server runs (novox/hq ADR 0594 §4): the fingerprint whose
|
||||
// server the node agent last made, or, from the take-over of a server a node's own composition made, that old-form
|
||||
// build's name (`build-...`). FP is the fingerprint applied: the two differ while a build changed the server and no
|
||||
// warranted want replaced it yet. Empty on every other have, and on a bus module's have from a node agent that does
|
||||
// not keep the server.
|
||||
Server string `json:"server,omitempty"`
|
||||
}
|
||||
|
||||
// UserListWritten is the bus's user list as the node-engine of the bus node wrote it to the bus module's file, applied
|
||||
@@ -421,8 +427,15 @@ type HaveNode struct {
|
||||
// controller ended may still say `controller` (composedByTheEndedController), which is read and never written.
|
||||
Composes string `json:"composes,omitempty"`
|
||||
ComposesWhy string `json:"composes-why,omitempty"`
|
||||
// Keeps names what the node agent keeps as it runs on a want without the warrant's mark (novox/hq ADR 0594 §8):
|
||||
// KeepsBusServer for a node agent that leaves the bus server alone. Written at each start; the assigner writes the
|
||||
// bus module's want only to a node whose have names it. Empty from a node agent before it.
|
||||
Keeps []string `json:"keeps,omitempty"`
|
||||
}
|
||||
|
||||
// KeepsBusServer is a node agent that keeps the bus server unless a want is warranted (HaveNode.Keeps, ADR 0594 §8).
|
||||
const KeepsBusServer = "bus-server"
|
||||
|
||||
// ComposesOwn is a node applying its own compositions (HaveNode.Composes).
|
||||
const ComposesOwn = "own"
|
||||
|
||||
@@ -494,6 +507,10 @@ func (h Have) check() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if h.Server != "" && checkFingerprint(h.Server, "the bus server's fingerprint") != nil &&
|
||||
(!strings.HasPrefix(h.Server, "build-") || checkName("bus server's build", h.Server) != nil) {
|
||||
return fmt.Errorf("delivery: the bus server runs %q, neither a fingerprint nor a build's name", h.Server)
|
||||
}
|
||||
switch h.Health {
|
||||
case HealthOK, HealthFailed, HealthWaits, HealthUnknown:
|
||||
default:
|
||||
@@ -529,6 +546,11 @@ func (n HaveNode) check() error {
|
||||
default:
|
||||
return fmt.Errorf("delivery: a node composes %q, not %s", n.Composes, ComposesOwn)
|
||||
}
|
||||
for _, k := range n.Keeps {
|
||||
if k == "" {
|
||||
return fmt.Errorf("delivery: a node keeps an empty name")
|
||||
}
|
||||
}
|
||||
for group, a := range n.Candidates {
|
||||
if group == "" {
|
||||
return fmt.Errorf("delivery: a node's candidate answer names no group")
|
||||
@@ -615,7 +637,7 @@ func SameHaveNode(a, b HaveNode) bool {
|
||||
sameJSON(a.Strays, b.Strays) && sameJSON(a.Filters, b.Filters) && sameJSON(a.Profile, b.Profile) &&
|
||||
(a.Record == nil) == (b.Record == nil) && (a.Record == nil || SameNodeRecord(*a.Record, *b.Record)) &&
|
||||
jsonEqual(a.Sealed, b.Sealed) && maps.Equal(a.SealedAt, b.SealedAt) && jsonEqual(a.Candidates, b.Candidates) && a.Composes == b.Composes &&
|
||||
a.ComposesWhy == b.ComposesWhy
|
||||
a.ComposesWhy == b.ComposesWhy && slices.Equal(a.Keeps, b.Keeps)
|
||||
}
|
||||
|
||||
// SamePresence says whether two presences are the same value.
|
||||
|
||||
@@ -282,6 +282,51 @@ func TestRoundTrip(t *testing.T) {
|
||||
t.Error("a list was sealed to no key")
|
||||
}
|
||||
})
|
||||
// 774/S2: the bus module's have names the fingerprint applied and what the server runs, a fingerprint or, at the
|
||||
// take-over, an old-form build's name (ADR 0594 §4); a have written before decodes as it was.
|
||||
t.Run("have of the bus with its server", func(t *testing.T) {
|
||||
fpA, fpB := fp2of('a'), fp2of('b')
|
||||
for _, server := range []string{fpA, "build-1792674595610176744"} {
|
||||
in := Have{FP: fpB, Server: server, Phase: PhaseRunning, Health: HealthOK}
|
||||
b, err := EncodeHave(in)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(b), `"server":"`+server+`"`) {
|
||||
t.Errorf("the have says %s", b)
|
||||
}
|
||||
out, err := DecodeHave(b)
|
||||
in.V = Version
|
||||
if err != nil || !SameHave(out, in) || SameHave(out, Have{V: Version, FP: fpB, Phase: PhaseRunning, Health: HealthOK}) {
|
||||
t.Errorf("got %+v, %v", out, err)
|
||||
}
|
||||
}
|
||||
for _, server := range []string{"nats", "build-a.b", "src2:abc"} {
|
||||
if _, err := EncodeHave(Have{FP: fpB, Server: server, Phase: PhaseRunning, Health: HealthOK}); err == nil {
|
||||
t.Errorf("a server running %q was encoded", server)
|
||||
}
|
||||
}
|
||||
old, err := DecodeHave([]byte(`{"v":1,"build":"build-17","phase":"running","health":"ok"}`))
|
||||
if err != nil || old.Server != "" || !SameHave(old, Have{V: Version, Build: "build-17", Phase: PhaseRunning, Health: HealthOK}) {
|
||||
t.Errorf("an old have read %+v, %v", old, err)
|
||||
}
|
||||
keeper := HaveNode{Composes: ComposesOwn, Keeps: []string{KeepsBusServer}}
|
||||
b, err := EncodeHaveNode(keeper)
|
||||
if err != nil || !strings.Contains(string(b), `"keeps":["bus-server"]`) {
|
||||
t.Fatalf("the keeper's have is %s, %v", b, err)
|
||||
}
|
||||
back, err := DecodeHaveNode(b)
|
||||
keeper.V = Version
|
||||
if err != nil || !SameHaveNode(back, keeper) || SameHaveNode(back, HaveNode{V: Version, Composes: ComposesOwn}) {
|
||||
t.Errorf("the keeper came back %+v, %v", back, err)
|
||||
}
|
||||
if older, err := DecodeHaveNode([]byte(`{"v":1,"composes":"own"}`)); err != nil || older.Keeps != nil {
|
||||
t.Errorf("an older node's have read %+v, %v", older, err)
|
||||
}
|
||||
if _, err := EncodeHaveNode(HaveNode{Keeps: []string{""}}); err == nil {
|
||||
t.Error("a node keeping an empty name was encoded")
|
||||
}
|
||||
})
|
||||
t.Run("have node", func(t *testing.T) {
|
||||
in := HaveNode{Windows: json.RawMessage(`{"a":1}`), Busy: json.RawMessage(`true`)}
|
||||
b, err := EncodeHaveNode(in)
|
||||
|
||||
Reference in New Issue
Block a user