Files
mesh-delivery/modules/mesh-delivery-indexer/internal/index/builds.go
T
2026-10-22 18:09:56 +02:00

91 lines
2.9 KiB
Go

package index
import (
"encoding/json"
"strings"
"sync"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// Builds holds the controller's build records (mesh-controller_builds) for the two things the indexer still reads from
// them until release R4g, when build-agent goes (the lead's decision of R4e, 2026-10-22):
// - the Builder input of the builder's own module, which build-agent builds (TrunkOf; novox/hq ADR 0453 clause 5,
// issue 1727);
// - the directory of a module whose modules key has none (PathOf; issue 1614), filled once and changing no fingerprint.
//
// It lists no module and maps no directory to a module: the indexer's modules are those its own messages and bucket name
// (ADR 0501 clause 6, issue 1851). Safe for use from a watch and from the message handler at once.
type Builds struct {
mu sync.Mutex
records map[string]delivery.BuildRecord // by bucket key
}
// NewBuilds is an empty Builds.
func NewBuilds() *Builds { return &Builds{records: map[string]delivery.BuildRecord{}} }
// Put takes a key of the builds bucket and its value. Only a build record of a module (key `<module>.build.<id>`,
// delivery.BuildKey) counts; the newest-pointer keys and requests that knew no module are not records of one.
func (b *Builds) Put(key string, value []byte) {
if !strings.Contains(key, ".build.") {
return
}
var r delivery.BuildRecord
if err := json.Unmarshal(value, &r); err != nil || r.Module == "" || r.Repository == "" {
return
}
b.mu.Lock()
defer b.mu.Unlock()
b.records[key] = r
}
// Delete takes a key out.
func (b *Builds) Delete(key string) {
b.mu.Lock()
defer b.mu.Unlock()
delete(b.records, key)
}
func newer(a, b delivery.BuildRecord) bool {
return a.At.After(b.At) || (a.At.Equal(b.At) && a.ID > b.ID)
}
// TrunkOf is the newest successful trunk build record of a module, in whatever repository it was built from; nil when
// there is none (issue 1727).
func (b *Builds) TrunkOf(module string) *delivery.BuildRecord {
var best *delivery.BuildRecord
b.mu.Lock()
defer b.mu.Unlock()
for _, r := range b.records {
if r.Module == module && r.IsTrunkBuild() && (best == nil || newer(r, *best)) {
c := r
best = &c
}
}
return best
}
// PathOf is the directory of a module of the repository as its newest build record of that repository names it, its
// newest successful trunk build's first ("." for the repository's root), and false when no record of the repository
// names the module (issue 1614).
func (b *Builds) PathOf(module, repository string) (string, bool) {
var best *delivery.BuildRecord
trunk := false
b.mu.Lock()
defer b.mu.Unlock()
for _, r := range b.records {
if r.Module != module || !delivery.SameRepository(r.Repository, repository) {
continue
}
t := r.IsTrunkBuild()
if best == nil || (t && !trunk) || (t == trunk && newer(r, *best)) {
c := r
best, trunk = &c, t
}
}
if best == nil {
return "", false
}
return pathOf(strings.Trim(best.Path, "/")), true
}