Check that the catalogue holds no module mesh-delivery but through the names its handover needs, and say how the seat passes (issue 1351)
This commit is contained in:
@@ -19,3 +19,22 @@ module and the backup's words, and the pull request's comment shows it. The hold
|
||||
of such a delivery asks the controller (`delivery-backups-again`) to take the backups again and the delivery goes on
|
||||
delivering; a record from before the controller cleared the failure does not hold it again. A held delivery already
|
||||
ends as covered or delivered when a later merge covers it.
|
||||
|
||||
## Taking the seat over from today's module
|
||||
|
||||
The gate claims the seat `mesh-delivery` beside the module `mesh-delivery`, which the catalogue no longer holds. The controller
|
||||
keeps a module that is assigned (it refuses to forget it), so the running module goes by a handover of verbs after the merge,
|
||||
never by hand on a machine (novox/hq ADR 0449 §4, ADR 0450 §6):
|
||||
|
||||
1. assign `mesh-delivery-gate` to the machine that holds the seat (`mesh-controller.assign`);
|
||||
2. check that `mesh-controller.seats` still names `mesh-delivery`, held by the running module;
|
||||
3. unassign `mesh-delivery` from that machine (`mesh-controller.unassign`) and push it (`mesh-controller.push`);
|
||||
4. the seat passes: the gate reads the controller's assignments and the node-engine's have keys, finds the module on no machine,
|
||||
carries its deliveries, groups and pull keys over once (the key `carried` in its `deliveries` says it did), reads the controller's
|
||||
walks and the forge's open pull requests, and acts.
|
||||
|
||||
Until then the gate is silent: it takes no event, writes no key, asks nothing and answers no verb but `delivery_status`, which
|
||||
says why (`holds-the-seat`, `seat-waits`).
|
||||
|
||||
The catalogue holds the names of the old module that the handover needs, and no others: the three buckets the gate carries
|
||||
over, and the event the issue tracker and the tool runner hear until the module is forgotten (`catalogue_test.go`).
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// **Today's module is gone from the catalogue** (novox/hq ADR 0437 §1, issue 1351; how it is checked): no `modules/mesh-delivery`
|
||||
// is held, no manifest declares the module `mesh-delivery`, and no manifest names the module in what it reads, hears or
|
||||
// calls but through the seat's name (`mesh-delivery` as a seat or a repository, `seat:mesh-delivery.<verb>`) and through
|
||||
// the names below, each of which stays until today's module is forgotten by the controller, because it is the only way to
|
||||
// reach what that module left: the three buckets the gate carries over (ADR 0450 §6) and the event the trackers hear
|
||||
// (issue 1350). Removing the module from the catalogue does not stop the running module: the controller keeps it until it is
|
||||
// unassigned (mesh-controller upgrades.go retireDeleted), and the handover follows the merge by verbs.
|
||||
var oldModuleNames = map[string][]string{
|
||||
"mesh-delivery-gate": {"mesh-delivery.deliveries", "mesh-delivery.groups", "mesh-delivery.pulls"},
|
||||
"mesh-issues": {"mesh-delivery.transition"},
|
||||
}
|
||||
|
||||
func TestTheCatalogueHoldsNoModuleMeshDeliveryButThroughTheNamesItsHandoverNeeds(t *testing.T) {
|
||||
modules := filepath.Join("..", "..", "..")
|
||||
if _, err := os.Stat(filepath.Join(modules, "mesh-delivery")); err == nil {
|
||||
t.Fatal("modules/mesh-delivery is still in the catalogue: its code is the gate's now")
|
||||
}
|
||||
dirs, err := os.ReadDir(modules)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
read := 0
|
||||
for _, dir := range dirs {
|
||||
raw, err := os.ReadFile(filepath.Join(modules, dir.Name(), "module.json"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
read++
|
||||
var manifest any
|
||||
if err := json.Unmarshal(raw, &manifest); err != nil {
|
||||
t.Fatalf("%s: %v", dir.Name(), err)
|
||||
}
|
||||
if m, _ := manifest.(map[string]any); m["module"] == "mesh-delivery" {
|
||||
t.Errorf("%s declares the module mesh-delivery", dir.Name())
|
||||
}
|
||||
var walk func(v any)
|
||||
walk = func(v any) {
|
||||
switch x := v.(type) {
|
||||
case string:
|
||||
if strings.HasPrefix(x, "mesh-delivery.") && !slices.Contains(oldModuleNames[dir.Name()], x) {
|
||||
t.Errorf("%s names the module mesh-delivery in %q: through the seat, or the gate's name", dir.Name(), x)
|
||||
}
|
||||
case []any:
|
||||
for _, e := range x {
|
||||
walk(e)
|
||||
}
|
||||
case map[string]any:
|
||||
for _, e := range x {
|
||||
walk(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
walk(manifest)
|
||||
}
|
||||
if read < 20 {
|
||||
t.Fatalf("only %d manifests were read: the catalogue is not where the test looks", read)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user