Fix 9.4e: the four readers use the branch follower's Entry, Ready, entries rows, entry-not-found finding and entry_again tool; their copies are deleted
Builds: design 47 G A-103, A-15, §614 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -6,10 +6,6 @@ package main
|
||||
// `manifests`.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
)
|
||||
|
||||
@@ -20,41 +16,3 @@ type CatalogHalf interface {
|
||||
// Ready is nil once every watched branch has its first view (none-yet counting as one), else says what it waits for.
|
||||
Ready() error
|
||||
}
|
||||
|
||||
// branchesHalf is the CatalogHalf over the follower of the watched branches.
|
||||
type branchesHalf struct{ b *meshcatalogclient.Branches }
|
||||
|
||||
func (h branchesHalf) Ready() error {
|
||||
followed := h.b.Followed()
|
||||
if len(followed) == 0 {
|
||||
return fmt.Errorf("the catalog half names no watched branch yet (the seat mesh-catalog's registrations are asked until they answer)")
|
||||
}
|
||||
var waiting []string
|
||||
for _, branch := range followed {
|
||||
if c, ok := h.b.Catalog(branch); ok {
|
||||
select {
|
||||
case <-c.Ready():
|
||||
default:
|
||||
waiting = append(waiting, branch)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(waiting) > 0 {
|
||||
return fmt.Errorf("the catalog half has no first view of %s yet", strings.Join(waiting, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h branchesHalf) Entry(module string) (catalog.CatalogEntry, bool, error) {
|
||||
if err := h.Ready(); err != nil {
|
||||
return catalog.CatalogEntry{}, false, err
|
||||
}
|
||||
for _, branch := range h.b.Followed() { // the branch followed first names a module more than one hold
|
||||
if c, ok := h.b.Catalog(branch); ok {
|
||||
if e, ok := c.Entry(module); ok {
|
||||
return e, true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return catalog.CatalogEntry{}, false, nil
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestCatalogHalfIsTheWatchedBranchesNewestRevision(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := branchesHalf{b}
|
||||
h := b
|
||||
if _, _, err := h.Entry("pg"); err == nil || !strings.Contains(err.Error(), "no watched branch") {
|
||||
t.Fatalf("before the registrations: %v, want an error naming the missing branch", err)
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"os"
|
||||
"reflect"
|
||||
"slices"
|
||||
@@ -14,6 +11,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/seatdef"
|
||||
"git.novox.be/novox/mesh-sdk/go/seatlist"
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
|
||||
@@ -488,7 +488,7 @@ func main() {
|
||||
default:
|
||||
}
|
||||
}
|
||||
meshCatalog = branchesHalf{branches}
|
||||
meshCatalog = branches
|
||||
if launched {
|
||||
fsys = FilesFor(p)
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -26,6 +24,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/seatdef"
|
||||
"git.novox.be/novox/mesh-sdk/go/seatlist"
|
||||
|
||||
@@ -2,11 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
)
|
||||
|
||||
// A section registered for the mesh before the controller's terminal took that over, or set at the terminal, is
|
||||
|
||||
@@ -7,8 +7,6 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
@@ -20,49 +18,7 @@ type CatalogHalf interface {
|
||||
Entry(module string) (catalog.CatalogEntry, bool, error)
|
||||
// Ready is nil once every watched branch has its first view (none-yet counting as one), else says what it waits for.
|
||||
Ready() error
|
||||
// ByFingerprint reads an entry by the fingerprint of a build: from a branch's half when one lists it, else asked of the
|
||||
// Resolve reads an entry by the fingerprint of a build: from a branch's half when one lists it, else asked of the
|
||||
// seat's verb `entry` once and kept (asked, answered or not found).
|
||||
ByFingerprint(ctx context.Context, fingerprint string) (catalog.CatalogEntry, meshcatalogclient.EntryState)
|
||||
}
|
||||
|
||||
// branchesHalf is the CatalogHalf over the follower of the watched branches.
|
||||
type branchesHalf struct{ b *meshcatalogclient.Branches }
|
||||
|
||||
func (h branchesHalf) Ready() error {
|
||||
followed := h.b.Followed()
|
||||
if len(followed) == 0 {
|
||||
return fmt.Errorf("the catalog half names no watched branch yet (the seat mesh-catalog's registrations are asked until they answer)")
|
||||
}
|
||||
var waiting []string
|
||||
for _, branch := range followed {
|
||||
if c, ok := h.b.Catalog(branch); ok {
|
||||
select {
|
||||
case <-c.Ready():
|
||||
default:
|
||||
waiting = append(waiting, branch)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(waiting) > 0 {
|
||||
return fmt.Errorf("the catalog half has no first view of %s yet", strings.Join(waiting, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h branchesHalf) Entry(module string) (catalog.CatalogEntry, bool, error) {
|
||||
if err := h.Ready(); err != nil {
|
||||
return catalog.CatalogEntry{}, false, err
|
||||
}
|
||||
for _, branch := range h.b.Followed() { // the branch followed first names a module more than one hold
|
||||
if c, ok := h.b.Catalog(branch); ok {
|
||||
if e, ok := c.Entry(module); ok {
|
||||
return e, true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return catalog.CatalogEntry{}, false, nil
|
||||
}
|
||||
|
||||
func (h branchesHalf) ByFingerprint(ctx context.Context, fingerprint string) (catalog.CatalogEntry, meshcatalogclient.EntryState) {
|
||||
return h.b.Resolve(ctx, fingerprint)
|
||||
Resolve(ctx context.Context, fingerprint string) (catalog.CatalogEntry, meshcatalogclient.EntryState)
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestCatalogHalfIsTheWatchedBranchesNewestRevision(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := branchesHalf{b}
|
||||
h := b
|
||||
if _, _, err := h.Entry("pg"); err == nil || !strings.Contains(err.Error(), "no watched branch") {
|
||||
t.Fatalf("before the registrations: %v, want an error naming the missing branch", err)
|
||||
}
|
||||
|
||||
@@ -5,15 +5,16 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
)
|
||||
|
||||
// memStore is the bus as mesh-config reaches it, in memory: its states and the mirrors it reads, its history log,
|
||||
@@ -43,7 +44,7 @@ func (m *memStore) Entry(module string) (catalog.CatalogEntry, bool, error) {
|
||||
|
||||
func (m *memStore) Ready() error { return m.notYet }
|
||||
|
||||
func (m *memStore) ByFingerprint(_ context.Context, fp string) (catalog.CatalogEntry, catalogclient.EntryState) {
|
||||
func (m *memStore) Resolve(_ context.Context, fp string) (catalog.CatalogEntry, catalogclient.EntryState) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if e, ok := m.byFp[fp]; ok {
|
||||
|
||||
@@ -6,9 +6,10 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
"strings"
|
||||
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
)
|
||||
|
||||
|
||||
@@ -152,13 +152,15 @@ func main() {
|
||||
default:
|
||||
}
|
||||
}
|
||||
branches.Entries.Changed = func(catalogclient.EntryRow) {
|
||||
// An entry the catalog holds none of is a finding `entry-not-found`, and a new pass starts at each answer (design 47 G A-103).
|
||||
branches.WriteEntryFindings(w, func(catalogclient.EntryRow) {
|
||||
select {
|
||||
case moved <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
c.Catalog = branchesHalf{branches}
|
||||
})
|
||||
theViews.entries = func() any { return branches.EntryStatuses() }
|
||||
c.Catalog = branches
|
||||
theViews.catalog = func() []*views.Follower {
|
||||
out := []*views.Follower{branches.Registrations.Follower}
|
||||
for _, b := range branches.Followed() {
|
||||
@@ -180,7 +182,7 @@ func main() {
|
||||
go resolving(c, moved)
|
||||
go hearing(c)
|
||||
go hearingDelivery(c)
|
||||
if err := stdio.Serve("", Tools(c)); err != nil {
|
||||
if err := stdio.Serve("", append(Tools(c), branches.EntryAgainTool("config", c.Store.HandAct))); err != nil {
|
||||
logf("%v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
@@ -62,6 +63,8 @@ func TestEveryStateAndActHasItsTool(t *testing.T) {
|
||||
for _, tool := range Tools(&Config{}) {
|
||||
served[tool.Name] = true
|
||||
}
|
||||
// the catalog half's follower serves the part's `entry_again` (design 47 G A-103), beside the module's own tools
|
||||
served[(&catalogclient.Branches{}).EntryAgainTool("config", nil).Name] = true
|
||||
if len(m.Claims) != 1 || m.Claims[0].Name != Seat || strings.Join(m.Claims[0].Serves, ",") != strings.Join(SeatVerbs, ",") {
|
||||
t.Errorf("claims %+v, want %s serving %v", m.Claims, Seat, SeatVerbs)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
)
|
||||
@@ -53,6 +54,8 @@ type ownerViews struct {
|
||||
// catalog is the followers of the catalog half (the registrations and each watched branch's revision view), which the
|
||||
// first-view tools list and ask again beside the owners' (design 47 G §614); nil before they are followed.
|
||||
catalog func() []*views.Follower
|
||||
// entries lists the entries by fingerprint the catalog half's follower keeps (design 47 G A-103).
|
||||
entries func() any
|
||||
}
|
||||
|
||||
// newOwnerViews makes a follower for each state; changed is told when any picture changes. findings is the module's writer,
|
||||
@@ -194,7 +197,11 @@ func viewTools(c *Config, o func() *ownerViews) []stdio.Tool {
|
||||
if ov == nil {
|
||||
return nil, errors.New("mesh-config reads its owners through views only when it runs as the module")
|
||||
}
|
||||
return map[string]any{"first-views": ov.statuses()}, nil
|
||||
out := map[string]any{"first-views": ov.statuses()}
|
||||
if ov.entries != nil {
|
||||
out["entries"] = ov.entries()
|
||||
}
|
||||
return out, nil
|
||||
}},
|
||||
{Name: FirstViewAgainTool,
|
||||
Description: "Ask a first view once more by hand, `<owner>.<state>` (all when not given), recorded as a hand act with " +
|
||||
|
||||
@@ -6,11 +6,12 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/meshconfigclient"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/meshconfigclient"
|
||||
)
|
||||
|
||||
// A config value held for the open pull request that introduces its key (novox/hq ADR 0502, issue 1826).
|
||||
|
||||
@@ -3,11 +3,12 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/meshconfigclient"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/meshconfigclient"
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
)
|
||||
|
||||
// The four sources (novox/hq ADR 0348 §2, §3, §9): a module's value on a node resolves, the most specific winning,
|
||||
|
||||
@@ -5,11 +5,12 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Reading the sources, writing the resolved values, and publishing the list of predefined keys.
|
||||
@@ -212,7 +213,7 @@ func (c *Config) trunkEntry(module string) (catalog.CatalogEntry, error) {
|
||||
// builtDeclarations is a module's declarations at a build: the manifest of the catalog entry of its fingerprint (design 47
|
||||
// G §594, §614); an entry still asked, or the seat's word that it holds none, is an error naming it.
|
||||
func (c *Config) builtDeclarations(module, fp string) (ModuleDeclarations, error) {
|
||||
e, state := c.Catalog.ByFingerprint(context.Background(), fp)
|
||||
e, state := c.Catalog.Resolve(context.Background(), fp)
|
||||
switch state {
|
||||
case catalogclient.EntryAnswered:
|
||||
if e.Module != module {
|
||||
|
||||
@@ -13,8 +13,9 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"time"
|
||||
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
)
|
||||
|
||||
// The states and reads.
|
||||
|
||||
@@ -2,9 +2,10 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
)
|
||||
|
||||
// The trunk's manifests aMesh declares.
|
||||
|
||||
@@ -18,13 +18,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
nodeengine "git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
delivery "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdelivery"
|
||||
"io"
|
||||
"maps"
|
||||
"os"
|
||||
@@ -36,6 +29,14 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
nodeengine "git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
delivery "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdelivery"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
|
||||
@@ -59,7 +59,8 @@
|
||||
"config_rename_close",
|
||||
"config_retiring",
|
||||
"config_first_views",
|
||||
"config_first_view_again"
|
||||
"config_first_view_again",
|
||||
"config_entry_again"
|
||||
],
|
||||
"state": [
|
||||
"values",
|
||||
|
||||
@@ -69,7 +69,7 @@ func (f *fakeCatalog) Ready() error {
|
||||
return f.notYet
|
||||
}
|
||||
|
||||
func (f *fakeCatalog) ByFingerprint(_ context.Context, fp string) (catalog.CatalogEntry, catalogclient.EntryState) {
|
||||
func (f *fakeCatalog) Resolve(_ context.Context, fp string) (catalog.CatalogEntry, catalogclient.EntryState) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if e, ok := f.byFp[fp]; ok {
|
||||
|
||||
@@ -7,8 +7,6 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
@@ -20,49 +18,7 @@ type CatalogHalf interface {
|
||||
Entry(module string) (catalog.CatalogEntry, bool, error)
|
||||
// Ready is nil once every watched branch has its first view (none-yet counting as one), else says what it waits for.
|
||||
Ready() error
|
||||
// ByFingerprint reads an entry by the fingerprint of a build: from a branch's half when one lists it, else asked of the
|
||||
// Resolve reads an entry by the fingerprint of a build: from a branch's half when one lists it, else asked of the
|
||||
// seat's verb `entry` once and kept (asked, answered or not found).
|
||||
ByFingerprint(ctx context.Context, fingerprint string) (catalog.CatalogEntry, meshcatalogclient.EntryState)
|
||||
}
|
||||
|
||||
// branchesHalf is the CatalogHalf over the follower of the watched branches.
|
||||
type branchesHalf struct{ b *meshcatalogclient.Branches }
|
||||
|
||||
func (h branchesHalf) Ready() error {
|
||||
followed := h.b.Followed()
|
||||
if len(followed) == 0 {
|
||||
return fmt.Errorf("the catalog half names no watched branch yet (the seat mesh-catalog's registrations are asked until they answer)")
|
||||
}
|
||||
var waiting []string
|
||||
for _, branch := range followed {
|
||||
if c, ok := h.b.Catalog(branch); ok {
|
||||
select {
|
||||
case <-c.Ready():
|
||||
default:
|
||||
waiting = append(waiting, branch)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(waiting) > 0 {
|
||||
return fmt.Errorf("the catalog half has no first view of %s yet", strings.Join(waiting, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h branchesHalf) Entry(module string) (catalog.CatalogEntry, bool, error) {
|
||||
if err := h.Ready(); err != nil {
|
||||
return catalog.CatalogEntry{}, false, err
|
||||
}
|
||||
for _, branch := range h.b.Followed() { // the branch followed first names a module more than one hold
|
||||
if c, ok := h.b.Catalog(branch); ok {
|
||||
if e, ok := c.Entry(module); ok {
|
||||
return e, true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return catalog.CatalogEntry{}, false, nil
|
||||
}
|
||||
|
||||
func (h branchesHalf) ByFingerprint(ctx context.Context, fingerprint string) (catalog.CatalogEntry, meshcatalogclient.EntryState) {
|
||||
return h.b.Resolve(ctx, fingerprint)
|
||||
Resolve(ctx context.Context, fingerprint string) (catalog.CatalogEntry, meshcatalogclient.EntryState)
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestCatalogHalfIsTheWatchedBranchesNewestRevision(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := branchesHalf{b}
|
||||
h := b
|
||||
if _, _, err := h.Entry("pg"); err == nil || !strings.Contains(err.Error(), "no watched branch") {
|
||||
t.Fatalf("before the registrations: %v, want an error naming the missing branch", err)
|
||||
}
|
||||
|
||||
@@ -12,16 +12,17 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogkey"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogkey"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
)
|
||||
|
||||
|
||||
@@ -31,17 +31,18 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogkey"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogkey"
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||
@@ -903,7 +904,7 @@ func (h *Holder) haveOutcome(p *meshprovisionerclient.Provision) {
|
||||
// read from the catalog entry of that fingerprint (design 47 G §594, §614); known is false while the entry is asked or when
|
||||
// the seat holds none (the caller then does not refuse).
|
||||
func (h *Holder) buildOffers(module, fingerprint, provision string) (offers, known bool) {
|
||||
entry, state := h.Catalog.ByFingerprint(context.Background(), fingerprint)
|
||||
entry, state := h.Catalog.Resolve(context.Background(), fingerprint)
|
||||
if state != catalogclient.EntryAnswered || entry.Module != module {
|
||||
return false, false
|
||||
}
|
||||
|
||||
@@ -14,12 +14,13 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
@@ -15,6 +13,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
|
||||
meshseat "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||
|
||||
@@ -10,13 +10,14 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
@@ -249,7 +250,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
branches.Logf = logf
|
||||
cat := branchesHalf{branches}
|
||||
cat := branches
|
||||
findings, err := newFindingsWriter()
|
||||
if err != nil {
|
||||
logf("%v", err)
|
||||
@@ -295,11 +296,12 @@ func main() {
|
||||
w.add(h.NodesOfModule(module)...)
|
||||
w.add(loads.heldBack(h)...)
|
||||
}
|
||||
branches.Entries.Changed = func(row catalogclient.EntryRow) {
|
||||
// An entry the catalog holds none of is a finding `entry-not-found` (design 47 G A-103).
|
||||
branches.WriteEntryFindings(findings, func(row catalogclient.EntryRow) {
|
||||
if row.Entry != nil {
|
||||
w.add(h.NodesOfModule(row.Entry.Module)...)
|
||||
}
|
||||
}
|
||||
})
|
||||
v.Start(context.Background())
|
||||
go w.run(h)
|
||||
go starting(h)
|
||||
@@ -350,7 +352,8 @@ func main() {
|
||||
time.Sleep(wait)
|
||||
}
|
||||
}()
|
||||
if err := stdio.Serve("", append(append(Tools(s), holderTools(h)...), v.Tools("provisioner")...)); err != nil {
|
||||
if err := stdio.Serve("", append(append(append(Tools(s), holderTools(h)...), v.Tools("provisioner")...),
|
||||
branches.EntryAgainTool("provisioner", handAct))); err != nil {
|
||||
logf("%v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -405,3 +408,9 @@ func Tools(s Store) []stdio.Tool {
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
// handAct records a hand act in the log of the seat mesh-hand-acts.
|
||||
func handAct(what, why, cause string) error {
|
||||
_, err := meshhandactsclient.Recorder{Ask: stdio.Ask}.Record(meshhandactsclient.Request{What: what, Why: why, Cause: cause})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"os"
|
||||
"regexp"
|
||||
"slices"
|
||||
@@ -348,6 +349,8 @@ func TestTheManifestDeclaresWhatTheCodeKeeps(t *testing.T) {
|
||||
for _, tool := range append(append(Tools(newStore()), holderTools(&Holder{})...), (&views.Reader{}).Tools("provisioner")...) {
|
||||
served[tool.Name] = true
|
||||
}
|
||||
// the catalog half's follower serves the part's `entry_again` (design 47 G A-103), beside the module's own tools
|
||||
served[(&catalogclient.Branches{}).EntryAgainTool("provisioner", nil).Name] = true
|
||||
for what, tool := range map[string]string{Registry: Seat + "." + Verb, Needs: Seat + "." + Verb,
|
||||
Applied: Seat + "." + Verb, Collect: Seat + "." + Verb, ProvisionsState: ProvisionsTool, PlansState: PlansTool,
|
||||
"a composition on a change": ComposeTool, "a decision on an answer": DecideTool} {
|
||||
|
||||
@@ -49,7 +49,8 @@
|
||||
"provisioner_decide",
|
||||
"provisioner_health",
|
||||
"provisioner_first_views",
|
||||
"provisioner_first_view_again"
|
||||
"provisioner_first_view_again",
|
||||
"provisioner_entry_again"
|
||||
],
|
||||
"state": [
|
||||
"registry",
|
||||
|
||||
@@ -5,9 +5,6 @@ package main
|
||||
// catalog graph entry carries whole (§443), never the indexer's state `modules` or `manifests`.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
)
|
||||
@@ -22,23 +19,15 @@ type CatalogHalf interface {
|
||||
type branchesHalf struct{ b *meshcatalogclient.Branches }
|
||||
|
||||
func (h branchesHalf) Modules() (map[string]catalog.CatalogEntry, error) {
|
||||
followed := h.b.Followed()
|
||||
if len(followed) == 0 {
|
||||
return nil, fmt.Errorf("the catalog half names no watched branch yet (the seat mesh-catalog's registrations are asked until they answer)")
|
||||
if err := h.b.Ready(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := map[string]catalog.CatalogEntry{}
|
||||
var waiting []string
|
||||
for _, branch := range followed {
|
||||
for _, branch := range h.b.Followed() {
|
||||
c, ok := h.b.Catalog(branch)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case <-c.Ready():
|
||||
default:
|
||||
waiting = append(waiting, branch)
|
||||
continue
|
||||
}
|
||||
half, _ := c.View() // a branch at none-yet is ready and empty (§614)
|
||||
for m, e := range half.Entries {
|
||||
if _, ok := out[m]; !ok { // the branch followed first names a module both hold
|
||||
@@ -46,8 +35,5 @@ func (h branchesHalf) Modules() (map[string]catalog.CatalogEntry, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(waiting) > 0 {
|
||||
return nil, fmt.Errorf("the catalog half has no first view of %s yet", strings.Join(waiting, ", "))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user