Read this node's placement from its node and module keys, or its placement.<node> before the holder converts it, so a write of the holder's is composed only once its node key lands (issue 774, research 072 row 37)

This commit is contained in:
2026-10-31 09:37:23 +01:00
parent bb8383b065
commit a4c0cee251
8 changed files with 176 additions and 42 deletions
+57 -4
View File
@@ -550,7 +550,50 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) {
// secrets. A key written again with what it held, or a want whose words moved and not its build, makes none.
worded, _ := delivery.EncodeWant(delivery.Want{FP: fp, Self: true, Words: "lemurs is held at aaaaaaaaaaaa"})
elsewhere, _ := delivery.EncodeWant(delivery.Want{FP: delivery.SourcePrefix2 + strings.Repeat("e", 64), Self: true})
for _, row := range []struct {
// Research 072 row 37: the placement converted to one key per module and node moves nothing composed; a write in
// keys makes its pass at its node key, the commit, and not at a module key written before it nor at the mirror.
placeBase := delivery.Placement{Node: "n1", Decided: delivery.NodeDecided{Hub: true, Address: "10.77.0.1"},
Modules: []delivery.PlacedModule{{Module: "lemurs"}, {Module: "oldie"}}}
placeKeys := delivery.NewPlacementKeys()
keyRows := func(after delivery.Placement, what string) []struct {
name, bucket, key string
value []byte
pass bool
} {
writes, err := placeKeys.Writes("n1", &after)
if err != nil {
t.Fatal(err)
}
var rows []struct {
name, bucket, key string
value []byte
pass bool
}
for i, w := range writes {
_, _ = placeKeys.Put(w.Key, w.Value, uint64(i+1), w.Value == nil)
rows = append(rows, struct {
name, bucket, key string
value []byte
pass bool
}{what + ": " + w.Key, delivery.PlacementBucket, w.Key, w.Value, w.Commit && what != "converted"})
}
return rows
}
_, _ = placeKeys.Put("placement.n1", place, 1, false)
lemursMoved := placeBase
lemursMoved.Modules = []delivery.PlacedModule{{Module: "lemurs", Values: map[string]any{"greeting": "hoi"}}, {Module: "oldie"}}
var placementRows []struct {
name, bucket, key string
value []byte
pass bool
}
for _, step := range []struct {
what string
p delivery.Placement
}{{"converted", placeBase}, {"lemurs moved", lemursMoved}, {"lemurs back", placeBase}} {
placementRows = append(placementRows, keyRows(step.p, step.what)...)
}
for _, row := range append([]struct {
name, bucket, key string
value []byte
pass bool
@@ -562,7 +605,7 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) {
{"lemurs's module again", delivery.ModulesBucket, "lemurs", mod, false},
{"lemurs's want at another build", delivery.AssignerWantsBucket, "want.n1.lemurs", elsewhere, true},
{"lemurs's want back at its build", delivery.AssignerWantsBucket, "want.n1.lemurs", want, true},
} {
}, placementRows...) {
before := passes()
b.put(t, row.bucket, row.key, row.value)
if !row.pass {
@@ -690,7 +733,17 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) {
both, _ := delivery.EncodePlacement(delivery.Placement{Node: "n1", Decided: delivery.NodeDecided{Hub: true, Address: "10.77.0.1"},
Modules: []delivery.PlacedModule{{Module: "lemurs"}, {Module: "oldie"}, {Module: "keeper"}}})
b.put(t, delivery.ModulesBucket, "keeper", kmod)
b.put(t, delivery.PlacementBucket, "placement.n1", both)
// n1 is held in keys per module and node since the rows above, which a legacy key no longer moves.
bothPlaced, _ := delivery.DecodePlacement(both)
bothWrites, err := placeKeys.Writes("n1", &bothPlaced)
if err != nil {
t.Fatal(err)
}
for _, w := range bothWrites {
if w.Value != nil {
b.put(t, delivery.PlacementBucket, w.Key, w.Value)
}
}
b.put(t, delivery.AssignerWantsBucket, "want.n1.keeper", want)
keeperKey, _ := delivery.ComposedKey("n1", "keeper", fp)
var handed string
@@ -1227,7 +1280,7 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) {
}{
"switched: placed after two failures": {answers: []error{fmt.Errorf("nats: timeout"), fmt.Errorf("nats: timeout")}, value: []byte(`{}`), placed: true, tries: 3, switched: true},
"never switched: a timeout is not placed, said once": {answers: []error{fmt.Errorf("nats: timeout")}, placed: false, tries: 1},
"no key": {placed: false, tries: 1},
"no key": {placed: false, tries: 2}, // its node key, then its legacy key (research 072 row 37)
"no placement state yet": {answers: []error{fmt.Errorf("the bucket %s: %w", delivery.PlacementBucket, nats.ErrBucketNotFound)}, placed: false, tries: 1, quiet: true},
"switched: failing until the link ends": {answers: []error{fmt.Errorf("jetstream not ready"), fmt.Errorf("jetstream not ready"),
fmt.Errorf("jetstream not ready")}, end: true, tries: 3, switched: true},