Files
mesh-delivery/modules/mesh-delivery-assigner/internal/assigngraph/revert.go
T

82 lines
2.5 KiB
Go

package assigngraph
import (
"context"
"encoding/json"
"fmt"
"slices"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// Reverted says a want of module on node at wantFp is a revert (design 47 G §298, §300, A-217): the module had wantFp in an earlier
// assignment graph revision than the one it now runs from, by the revisions' own numbers. The revision it runs from is the first kept
// that lists runFp for the module on the node; a want is a revert when it was listed before that, and never listed since.
func Reverted(ctx context.Context, o Objects, node, module, runFp, wantFp string) (bool, error) {
if runFp == "" || wantFp == "" || runFp == wantFp {
return false, nil
}
names, err := o.Names(ctx)
if err != nil {
return false, fmt.Errorf("the objects %s: %w", RevisionsObjects, err)
}
var numbers []int64
for _, n := range names {
if r, ok := trunkOf(n); ok {
numbers = append(numbers, r)
}
}
slices.Sort(numbers)
var ranFrom, lastWanted int64
for _, r := range numbers {
rev, err := ReadRevision(ctx, o, r)
if err != nil {
return false, err
}
for _, ref := range rev.Entries {
if ref.Node != node || ref.Module != module {
continue
}
e, err := ReadEntry(ctx, o, ref.Digest)
if err != nil {
return false, err
}
switch e.Fp {
case runFp:
if ranFrom == 0 {
ranFrom = r
}
case wantFp:
lastWanted = r
}
}
}
return ranFrom != 0 && lastWanted != 0 && lastWanted < ranFrom, nil
}
// FormChanges are the kept data whose `form` differs between the running entry's manifest and the want's (design 47 G §295 to §298,
// A-217): the entry's manifest whole is read as a manifest and compared by catalogue.FormChanges, so a kept data's form is read from
// the entry's kept declarations (catalogue.KeptDeclarations), never from a field of the want.
func FormChanges(running, applied meshcatalog.CatalogEntry) ([]catalogue.FormChange, error) {
before, err := manifestOf(running)
if err != nil {
return nil, fmt.Errorf("the running manifest of %s: %w", running.Module, err)
}
after, err := manifestOf(applied)
if err != nil {
return nil, fmt.Errorf("the manifest of %s: %w", applied.Module, err)
}
return catalogue.FormChanges(before, after), nil
}
func manifestOf(e meshcatalog.CatalogEntry) (catalogue.Manifest, error) {
var m catalogue.Manifest
raw, err := json.Marshal(e.Manifest)
if err != nil {
return m, err
}
err = json.Unmarshal(raw, &m)
return m, err
}