Keep a consumer bound where its data is; only a pin moves it (hq ADR 0232, issue 273)
Issue 258's fix let a mesh seat's holder elsewhere answer before this machine's own provider. Right for the resolver, which any provider answers alike; for the store's seat it re-bound every database consumer on a machine running its own store to the holder on another, each was given a fresh, empty database there, and nothing said so for twenty hours. - An offer says whether it keeps its consumers' data (`keeps-consumer-data`); unsaid, a provider that grants each consumer a credential does. For such a provision the seat's holder no longer overrules a provider beside the consumer; a pin still does. - Where each such consumer was sent is recorded (migration 0071). A resolution that would bind it elsewhere keeps the recorded provider and says the move; one whose provider is gone is refused, never answered by another. - A push says a kept move and raises it as an urgent condition at once; the self-check's D12 raises it every run, with a pinned move not yet sent as a warning and any unasked move as urgent.
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/novox/mesh-controller/internal/catalogue"
|
||||
)
|
||||
|
||||
// Where a consumer of data was bound is kept, and a move keeps where it was (novox/hq ADR 0232).
|
||||
func TestABindingIsRecordedAndAMoveKeepsWhereItWas(t *testing.T) {
|
||||
inv := fresh(t)
|
||||
ctx := t.Context()
|
||||
for _, n := range []string{"home", "anchor"} {
|
||||
if _, err := inv.AddNode(ctx, n); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
home := catalogue.Chosen{Node: "home", Module: "store"}
|
||||
anchor := catalogue.Chosen{Node: "anchor", Module: "store"}
|
||||
if err := inv.RecordBindings(ctx, "home", []Binding{
|
||||
{Consumer: "board", Provision: "postgres-database", Provider: home},
|
||||
{Consumer: "game", Provision: "postgres-database", Provider: home},
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := inv.BindingsFor(ctx, "home")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got["board"]["postgres-database"] != home || got["game"]["postgres-database"] != home {
|
||||
t.Fatalf("recorded %+v", got)
|
||||
}
|
||||
first, err := inv.Bindings(ctx)
|
||||
if err != nil || len(first) != 2 {
|
||||
t.Fatalf("%+v, %v", first, err)
|
||||
}
|
||||
|
||||
// Sent again where it is: only marked sent.
|
||||
if err := inv.RecordBindings(ctx, "home", []Binding{{Consumer: "board", Provision: "postgres-database", Provider: home}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Moved by a pin and sent: bound anew, with where it was.
|
||||
if err := inv.RecordBindings(ctx, "home", []Binding{{Consumer: "game", Provision: "postgres-database", Provider: anchor}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
all, err := inv.Bindings(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, b := range all {
|
||||
switch b.Consumer {
|
||||
case "board":
|
||||
if b.Provider != home || b.MovedFrom != "" || !b.BoundAt.Equal(first[0].BoundAt) || b.Machine != "home" {
|
||||
t.Errorf("a binding sent again where it is changed: %+v (was %+v)", b, first[0])
|
||||
}
|
||||
case "game":
|
||||
if b.Provider != anchor || b.MovedFrom != "home/store" || !b.BoundAt.After(first[1].BoundAt) {
|
||||
t.Errorf("a moved binding: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A provider machine leaving keeps the record of where the data is.
|
||||
if _, err := inv.store.Pool().Exec(ctx, `delete from node where name = 'anchor'`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err = inv.BindingsFor(ctx, "home")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got["game"]["postgres-database"] != anchor {
|
||||
t.Fatalf("the record went with the provider's machine: %+v", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user