diff --git a/node-tools/internal/console/firstviews.go b/node-tools/internal/console/firstviews.go index 4a36fe1..16f44e6 100644 --- a/node-tools/internal/console/firstviews.go +++ b/node-tools/internal/console/firstviews.go @@ -6,6 +6,7 @@ import ( "log" "strings" + "git.novox.be/novox/mesh-sdk/go/process" "git.novox.be/novox/mesh-sdk/go/views" ) @@ -20,6 +21,10 @@ type FirstViewer interface { // state and since when. type entryLister interface{ Entries() any } +// ownBuilder is a FirstViewer that also says the build the tool runner itself was started with (design 47 G §205, §424): +// mesh_first_views names it, or says `own build unknown` and why. +type ownBuilder interface{ OwnBuild() process.Build } + // firstViewsAnswer is mesh_first_views and mesh_first_view_again. func (s *Surface) firstViewsAnswer(ctx context.Context, name string, args map[string]any) map[string]any { fv, ok := s.src.(FirstViewer) @@ -29,6 +34,9 @@ func (s *Surface) firstViewsAnswer(ctx context.Context, name string, args map[st } if name == verbFirstViews { out := map[string]any{"first views": fv.Status()} + if ob, ok := fv.(ownBuilder); ok { + out["own build"] = ob.OwnBuild().String() + } if el, ok := fv.(entryLister); ok { out["entries"] = el.Entries() } diff --git a/node-tools/internal/console/firstviews_test.go b/node-tools/internal/console/firstviews_test.go index abd7af9..5192c3a 100644 --- a/node-tools/internal/console/firstviews_test.go +++ b/node-tools/internal/console/firstviews_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "git.novox.be/novox/mesh-sdk/go/process" "git.novox.be/novox/mesh-sdk/go/views" ) @@ -14,12 +15,16 @@ import ( type viewer struct { busSource asked []string + build process.Build } func (v *viewer) Status() []views.Status { return []views.Status{{Owner: "mesh-delivery-assigner", Tool: "assignments", State: "assignments", Revision: 4, Asks: 1}} } +// OwnBuild is the build the viewer was started with. +func (v *viewer) OwnBuild() process.Build { return v.build } + // Entries are the entries by fingerprint the viewer keeps (design 47 G A-103). func (v *viewer) Entries() any { return []string{"fp:a asked"} } @@ -41,6 +46,13 @@ func TestTheConsoleShowsAndAsksAgainTheRunnersFirstViews(t *testing.T) { if got := text(s.discover(context.Background(), "mesh_first_views", nil)); !strings.Contains(got, "mesh-delivery-assigner") || !strings.Contains(got, "assignments") || !strings.Contains(got, "fp:a asked") { t.Errorf("mesh_first_views shows %s", got) } + // The tool runner's own build is named, or said unknown with the reason (design 47 G §205, §424). + for build, want := range map[string]string{"abcd1234": "abcd1234", "": "own build unknown"} { + v.build = process.ReadOwnBuild(func(string) string { return build }) + if got := text(s.discover(context.Background(), "mesh_first_views", nil)); !strings.Contains(got, `own build`) || !strings.Contains(got, want) { + t.Errorf("mesh_first_views with the build %q shows %s", build, got) + } + } got := s.discover(context.Background(), "mesh_first_view_again", map[string]any{"why": "doubted"}) if len(v.asked) != 1 || v.asked[0] != "doubted" || !strings.Contains(text(got), "asked again") { t.Errorf("mesh_first_view_again asked %v and answered %s", v.asked, text(got)) diff --git a/node-tools/internal/firstview/firstview.go b/node-tools/internal/firstview/firstview.go index 706c5d7..21f4a2f 100644 --- a/node-tools/internal/firstview/firstview.go +++ b/node-tools/internal/firstview/firstview.go @@ -27,6 +27,7 @@ import ( stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/keys" + "git.novox.be/novox/mesh-sdk/go/process" "git.novox.be/novox/mesh-sdk/go/views" "github.com/novox/mesh-tools/node-tools/internal/bus" @@ -86,6 +87,9 @@ type Deps struct { Findings FindingWriter // StartFindings starts that writer, and its stop ends it; nil starts none. StartFindings func(ctx context.Context) (stop func(), err error) + // Build is the build this process was started with (process.OwnBuild, read once at the start): its fingerprint, or + // why it is unknown (design 47 G §205, §424). + Build process.Build // Node is the machine the runner is on, named in its findings' subject. Node string // Bound and Wait are the follower's (zero: two minutes, five seconds). @@ -108,7 +112,7 @@ func Start(parent context.Context, conn *bus.Conn, logf func(string, ...any)) (* // state adapter, JetStream and node are this connection's, in this one place (design 47 G A-16, A-27). func DepsOf(conn *bus.Conn, logf func(string, ...any)) Deps { me := conn.Module() - d := Deps{Module: me, Node: conn.Node(), + d := Deps{Module: me, Node: conn.Node(), Build: process.OwnBuild(), Ask: func(address string, body any) (json.RawMessage, error) { got, err := conn.Ask(address, body, "") return got.Result, err @@ -287,6 +291,10 @@ func (v *Views) Status() []views.Status { return out } +// OwnBuild is the build the tool runner was started with: the fingerprint of the want its node-engine applied, or why it is +// unknown (`own build unknown: started without MESH_FINGERPRINT`). +func (v *Views) OwnBuild() process.Build { return v.deps.Build } + // Entries are the entries by fingerprint the catalog half's follower keeps, with their state and since when (design 47 G A-103). func (v *Views) Entries() any { if v.branches == nil {