Hold a refused manifest in the bus reader instead of ending the whole read (ADR 0578 §3)
Issue 1585, S2: one refused manifest silenced disk-load for 45 hours. frombus decodes leniently, takes the indexer's verdict, stands a refused module in as its stub and names it in Input.Refused; DataItemsHeld names it. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -37,6 +37,7 @@ func aNodeRefusedWholeSaysWhatItHeld(t *testing.T) {
|
||||
refused := `{"module":"power","version":"1","items":[{"collection":"contribution:node-bar:block","attributes":{"shows":"state"},"template":"files/a"}]}`
|
||||
needs := `{"module":"lamp","version":"1","requires":["nothing-provides-this"]}`
|
||||
b, fps := aNode(t, refused, needs)
|
||||
refuse(b, "power", `"shows" is none of them`)
|
||||
_, _, held, err := Compose(context.Background(), b, Mesh{}, Scope{Node: "n1"}, fps)
|
||||
if err == nil || !strings.Contains(err.Error(), "nothing provides") || !strings.Contains(err.Error(), `held before: power: `) ||
|
||||
!strings.Contains(err.Error(), `"shows" is none of them`) {
|
||||
@@ -44,6 +45,48 @@ func aNodeRefusedWholeSaysWhatItHeld(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// refuse writes the indexer's refusal of module's manifest into its modules value (novox/hq ADR 0578 §1).
|
||||
func refuse(b *bus, module string, problems ...string) {
|
||||
m := b.modules[module]
|
||||
m.Verdict, m.Problems = delivery.VerdictRefused, problems
|
||||
b.modules[module] = m
|
||||
}
|
||||
|
||||
// ADR 0578 §3: the bus reader never ends a whole read on a refused manifest. Input, Plans and DataItems compose the rest
|
||||
// and hold the refused module, named with the indexer's words in Refused; a field the decoder does not know is set aside
|
||||
// and named, and its module composed.
|
||||
func aRefusedManifestNeverEndsTheRead(t *testing.T) {
|
||||
ok := `{"module":"lamp","version":"1","resources":[{"id":"d","type":"directory","path":"/srv/lamp","mode":"0700"}],` +
|
||||
`"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`
|
||||
bad := `{"module":"power","version":"1","resources":[{"id":"d","type":"directory","path":"/srv/power","mode":"0700"}],` +
|
||||
`"data":{"own":[{"id":"d","path":"${dir:d}","class":"valuable"}]}}`
|
||||
later := `{"module":"later","version":"1","a-field-from-later":1}`
|
||||
b, _ := aNode(t, ok, bad, later)
|
||||
refuse(b, "power", "removes a stream it may not")
|
||||
ctx := context.Background()
|
||||
in, err := Input(ctx, b, Mesh{}, Scope{Node: "n1"})
|
||||
if err != nil {
|
||||
t.Fatalf("one refused manifest ended the read: %v", err)
|
||||
}
|
||||
if why := in.Refused["power"]; !strings.Contains(why, "refused the manifest of power: removes a stream it may not") ||
|
||||
len(in.Refused) != 1 {
|
||||
t.Fatalf("refused: %v", in.Refused)
|
||||
}
|
||||
if aside := in.SetAside["later"]; !strings.Contains(aside, "a-field-from-later") {
|
||||
t.Fatalf("set aside: %v", in.SetAside)
|
||||
}
|
||||
if !in.Catalogue["power"].Stubbed || in.Catalogue["lamp"].Stubbed || in.Catalogue["later"].Module != "later" {
|
||||
t.Fatalf("the catalogue: %+v", in.Catalogue)
|
||||
}
|
||||
if _, err := Plans(ctx, b, Mesh{}, Scope{Node: "n1"}); err != nil {
|
||||
t.Fatalf("plans: %v", err)
|
||||
}
|
||||
items, _, held, err := DataItemsHeld(ctx, b, Mesh{}, Scope{Node: "n1"})
|
||||
if err != nil || len(items["lamp"]) != 1 || items["power"] != nil || !strings.Contains(held["power"], "removes a stream") {
|
||||
t.Fatalf("data items %v held %v: %v", items, held, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 774: the culprit rule takes a module whose stub composes or fails otherwise; the runtime only where its stub
|
||||
// composes, since its stub always fails otherwise.
|
||||
func theRuntimeIsBlamedOnlyWhereItsStubComposes(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user