Files
mesh-delivery/modules/mesh-delivery-indexer/internal/index/oldsections.go
T

79 lines
2.9 KiB
Go

package index
import (
"context"
"encoding/json"
"fmt"
"maps"
"slices"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/delivery"
"mesh-delivery-indexer/judge"
)
// How many accepted modules use each old section (issue 1966 D4; novox/hq ADR 0595 §11): the indexer counts them, the
// foundation left out, as it judges, keeps the count in its state oldsections under one key, and the tool
// indexer_old_sections reads it. The judge refuses a manifest of another module that uses a section whose count is 0.
const (
// OldSectionsTool is the tool that reads the count.
OldSectionsTool = "indexer_old_sections"
// OldSectionsState is the indexer's state of the count: the bucket mesh-delivery-indexer_oldsections.
OldSectionsState = "oldsections"
OldSectionsBucket = delivery.IndexerModule + "_" + OldSectionsState
// OldSectionsKey is the one key it holds.
OldSectionsKey = "counts"
)
// OldSectionsCount is the value of the oldsections state: per old section, the accepted modules outside the foundation using it.
type OldSectionsCount struct {
V int `json:"v"`
Counts map[string]int `json:"counts"`
}
// DecodeOldSections reads the oldsections value.
func DecodeOldSections(value []byte) (OldSectionsCount, error) {
var c OldSectionsCount
if err := json.Unmarshal(value, &c); err != nil {
return c, fmt.Errorf("the count of the old sections cannot be read: %w", err)
}
if c.V != 1 {
return c, fmt.Errorf("a count of the old sections of version %d, not 1", c.V)
}
return c, nil
}
// countBefore counts the accepted modules using each old section as the pass starts: those whose verdict held says accepted,
// or which have none and are not fresh (acceptedBefore). A manifest is read leniently, since a module the judge now finds
// a problem in is still accepted (ADR 0579 §1) and still counts.
func (ix *Indexer) countBefore(ctx context.Context, raws map[string][]byte, digests map[string]string, fresh map[string]bool) judge.OldSectionCounts {
var accepted []catalogue.Manifest
for _, name := range slices.Sorted(maps.Keys(raws)) {
if !ix.acceptedBefore(ctx, digests[name], fresh) {
continue
}
if m, err := catalogue.Decode(raws[name]); err == nil {
m.Module = name
accepted = append(accepted, m)
}
}
return judge.CountOldSections(accepted)
}
// keepOldSections writes the counts under OldSectionsKey when they differ from the ones held.
func (ix *Indexer) keepOldSections(ctx context.Context, counts judge.OldSectionCounts) error {
if ix.OldSections == nil {
return nil
}
return write(ctx, ix.OldSections, OldSectionsKey, func(value []byte, found bool) ([]byte, bool, error) {
if found {
if cur, err := DecodeOldSections(value); err == nil && maps.Equal(cur.Counts, counts) {
return nil, false, nil
}
}
next, err := json.Marshal(OldSectionsCount{V: 1, Counts: counts})
return next, false, err
})
}