Files
mesh-delivery/modules/mesh-delivery-indexer/internal/index/open_asks.go
T
jschoubben 5b13cc7ab1 IX24: the indexer's four kept calls are asked again only while their ask is open
messageVia, stepsVia, sourceVia and versionsVia go through CallKeptWhileOpen: open while the commit's take-in
is pending, the candidate is held, the branch is watched, the module is in the newest view. A call that ends
with its ask closed is index.ErrAskClosed, not an unanswered call.

Builds: design 47 G §351, §367, §460, §531; A-190

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:53:45 +01:00

105 lines
3.7 KiB
Go

package index
import (
"context"
"errors"
"fmt"
"slices"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-sdk/go/keys"
)
// ErrAskClosed is what a kept call answers when its ask was closed while it was made again (design 47 G §351, §460, A-190):
// what the ask served no longer stands, so the call stopped and is not said unanswered.
var ErrAskClosed = errors.New("the ask is closed: what it served no longer stands")
// takingIn marks a context as the take-in of one commit's merged message, which is pending while that context lives.
type takingIn struct{ repository, merge string }
type takingInKey struct{}
// forTakeIn is ctx marked as the take-in of the merged message of repository's commit merge.
func forTakeIn(ctx context.Context, repository, merge string) context.Context {
return context.WithValue(ctx, takingInKey{}, takingIn{repository, merge})
}
// TakeInPending says the take-in of the commit merge of repository is still pending (A-190, for the forge bridge's
// merged_message): its take-in is the one ctx is made for, or a pending entry names it.
func (ix *Indexer) TakeInPending(ctx context.Context, repository, merge string) (bool, error) {
if ctx.Err() != nil {
return false, nil
}
if t, ok := ctx.Value(takingInKey{}).(takingIn); ok && t.repository == repository && t.merge == merge {
return true, nil
}
if ix.Pending == nil {
return false, nil
}
entries, err := ReadPending(ctx, ix.Pending, ix.logf)
if err != nil {
return false, err
}
return slices.ContainsFunc(entries, func(e PendingEntry) bool {
return e.Forge.Merge == merge && e.Forge.Repository == repository
}), nil
}
// SeedEntryHeld says the newest trunk revision still holds the entry of module at the fingerprint fp, the candidate the
// seed asks steps for (A-190).
func (ix *Indexer) SeedEntryHeld(ctx context.Context, module, fp string) (bool, error) {
if ctx.Err() != nil || ix.Revisions == nil {
return false, ctx.Err()
}
rev, found, err := newestTrunk(ctx, ix.Revisions)
if err != nil || !found {
return false, err
}
_, entries, err := ReadRevision(ctx, ix.Revisions, fmt.Sprintf("trunk.%d", rev.Revision))
if err != nil {
return false, err
}
return slices.ContainsFunc(entries, func(e meshcatalog.CatalogEntry) bool { return e.Module == module && e.Fp == fp }), nil
}
// ModuleInNewestView says module is among the entries of the newest trunk revision, the view the versions are filled for (A-190).
func (ix *Indexer) ModuleInNewestView(ctx context.Context, module string) (bool, error) {
if ctx.Err() != nil || ix.Revisions == nil {
return false, ctx.Err()
}
rev, found, err := newestTrunk(ctx, ix.Revisions)
if err != nil || !found {
return false, err
}
_, entries, err := ReadRevision(ctx, ix.Revisions, fmt.Sprintf("trunk.%d", rev.Revision))
if err != nil {
return false, err
}
return slices.ContainsFunc(entries, func(e meshcatalog.CatalogEntry) bool { return e.Module == module }), nil
}
// BranchWatched says branch (as the source's key names it, escaped; empty asks the list of every branch) is watched: the
// trunk always, another branch while a registration names it (A-190). With no registry, every branch is.
func (ix *Indexer) BranchWatched(ctx context.Context, branch string) (bool, error) {
if ctx.Err() != nil {
return false, nil
}
if isTrunkBranch(branch) || ix.Registry == nil || ix.Registry.Registrations == nil {
return true, nil
}
name, err := keys.UnescapeName(branch)
if err != nil {
return false, nil
}
regs, err := ix.Registry.RegistrationsAnswer(ctx, meshcatalog.RegistrationsInput{})
if err != nil {
return false, err
}
for _, r := range regs.Registrations {
if slices.Contains(r.Branches, name) {
return true, nil
}
}
return false, nil
}