102 lines
3.7 KiB
Go
102 lines
3.7 KiB
Go
package index
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
|
|
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/views"
|
|
)
|
|
|
|
// BusStateTool is the indexer's tool the bus module's keeper takes its first view from (design 25 § 12.2; DLV-I11):
|
|
// every trunk module whose accepted manifest asks for bus state, then each manifest-accepted after its revision.
|
|
const BusStateTool = "indexer_bus_state"
|
|
|
|
// BusStateModule is one module of BusStateAnswer: the digest of its trunk's accepted manifest, the verdicts state's
|
|
// revision of that verdict (the one its manifest-accepted carries, ADR 0622 §2), and its bus-state entries whole.
|
|
type BusStateModule struct {
|
|
Module string `json:"module"`
|
|
Digest string `json:"digest"`
|
|
Revision uint64 `json:"revision"`
|
|
BusState []catalogue.BusStateEntry `json:"bus-state"`
|
|
}
|
|
|
|
// BusStateAnswer is indexer_bus_state's answer: Revision is the verdicts state's mark, read before anything else, so
|
|
// every manifest-accepted above it is a change after this answer (ADR 0615 §4); Modules in module order.
|
|
type BusStateAnswer struct {
|
|
Revision uint64 `json:"revision"`
|
|
Modules []BusStateModule `json:"modules"`
|
|
}
|
|
|
|
// BusStateOf answers indexer_bus_state from the indexer's own states: its trunk modules, the judge's verdicts and the
|
|
// manifests it keeps, and the marks the views family says them up to. A module refused or waiting, or whose manifest
|
|
// asks for no bus state, is left out; a value that cannot be read is an error, never a module silently left out.
|
|
func BusStateOf(modules, verdicts, manifests, marks views.Source) (BusStateAnswer, error) {
|
|
out := BusStateAnswer{Modules: []BusStateModule{}}
|
|
if marks != nil {
|
|
if e, ok, err := marks.Get(VerdictsState); err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("the mark of %s cannot be read: %w", VerdictsState, err)
|
|
} else if ok {
|
|
m, err := views.DecodeMark(e.Value)
|
|
if err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("the mark of %s: %w", VerdictsState, err)
|
|
}
|
|
out.Revision = m.Revision
|
|
}
|
|
}
|
|
names, err := modules.Keys()
|
|
if err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("the modules state cannot be listed: %w", err)
|
|
}
|
|
slices.Sort(names)
|
|
for _, name := range names {
|
|
e, ok, err := modules.Get(name)
|
|
if err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("modules.%s cannot be read: %w", name, err)
|
|
}
|
|
if !ok {
|
|
continue
|
|
}
|
|
mod, err := meshcatalogclient.DecodeModule(e.Value)
|
|
if err != nil || mod.Manifest == "" {
|
|
continue // no manifest held for it, so no verdict
|
|
}
|
|
key, err := meshcatalogclient.VerdictsKey(mod.Manifest)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
ve, ok, err := verdicts.Get(key)
|
|
if err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("the verdict on %s cannot be read: %w", name, err)
|
|
}
|
|
if !ok {
|
|
continue
|
|
}
|
|
v, err := meshcatalogclient.DecodeVerdict(ve.Value)
|
|
if err != nil || v.State != meshcatalogclient.VerdictAccepted {
|
|
continue
|
|
}
|
|
me, ok, err := manifests.Get(mod.Manifest)
|
|
if err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("the manifest of %s cannot be read: %w", name, err)
|
|
}
|
|
if !ok {
|
|
continue
|
|
}
|
|
kept, err := meshcatalogclient.DecodeManifest(me.Value)
|
|
if err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("the manifest of %s: %w", name, err)
|
|
}
|
|
m, err := catalogue.Decode([]byte(kept.Manifest))
|
|
if err != nil {
|
|
return BusStateAnswer{}, fmt.Errorf("the accepted manifest of %s does not read: %w", name, err)
|
|
}
|
|
if len(m.BusState) == 0 {
|
|
continue
|
|
}
|
|
out.Modules = append(out.Modules, BusStateModule{Module: name, Digest: mod.Manifest, Revision: ve.Revision, BusState: m.BusState})
|
|
}
|
|
return out, nil
|
|
}
|