From c81915b0391c1aec3352615d34899818a91cf116 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 11 Nov 2026 22:19:22 +0100 Subject: [PATCH] G findings: distribution-tools and package-registry make the held writer at once and start it after Serve, as it seeds at Start Builds: design 47 G A-40, A-32 --- .../cmd/distribution-tools/main.go | 19 +++++++------ .../distribution/internal/holder/findings.go | 28 ++----------------- .../gitea/cmd/package-registry/findings.go | 28 ++----------------- modules/gitea/cmd/package-registry/main.go | 19 +++++++------ 4 files changed, 26 insertions(+), 68 deletions(-) diff --git a/modules/distribution/cmd/distribution-tools/main.go b/modules/distribution/cmd/distribution-tools/main.go index af47a63f0..352dea76f 100644 --- a/modules/distribution/cmd/distribution-tools/main.go +++ b/modules/distribution/cmd/distribution-tools/main.go @@ -506,21 +506,22 @@ var findings = &holder.Findings{Logf: logf} func main() { // The tools bundle's findings go through the module's held writer (design 47 G §689, A-16, A-29, A-32); it owns the transfers' - // kinds, the program's writer the driver's. The runtime answers its state and subscription only once Serve has its channel, - // so it is made then. + // kinds, the program's writer the driver's. + w, err := views.NewStdioHeldWriter(views.WriterConfig[meshconditions.Finding, meshconditions.FindingCleared, meshconditions.FindingsStated, meshconditions.FindingsAskedEvent]{ + Asked: meshconditions.SubjectFindingsAsked, Module: holder.Self, State: stdio.State("findings"), Kinds: holder.TransferFindingKinds, Logf: logf}) + if err != nil { + logf("%v", err) + os.Exit(1) + } + findings.Writer = w + // the runtime answers the writer's state and subscription only once Serve has its channel go func() { <-stdio.Served() // the keys of the older form end in no kind the writer owns, so it does not clear them (A-31) if err := holder.DeleteOldFindings(stdio.State("findings"), holder.Self, holder.TransferFindingKinds); err != nil { logf("the old findings are not deleted: %v", err) } - w, err := views.NewStdioHeldWriter(views.WriterConfig[meshconditions.Finding, meshconditions.FindingCleared, meshconditions.FindingsStated, meshconditions.FindingsAskedEvent]{ - Asked: meshconditions.SubjectFindingsAsked, Module: holder.Self, State: stdio.State("findings"), Kinds: holder.TransferFindingKinds, Logf: logf}) - if err == nil { - findings.Use(w) - err = w.Start(context.Background()) - } - if err != nil { + if err := w.Start(context.Background()); err != nil { logf("%v", err) os.Exit(1) } diff --git a/modules/distribution/internal/holder/findings.go b/modules/distribution/internal/holder/findings.go index ffdb8f99f..e14a07b84 100644 --- a/modules/distribution/internal/holder/findings.go +++ b/modules/distribution/internal/holder/findings.go @@ -3,7 +3,6 @@ package holder import ( "context" "strings" - "sync" "time" meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" @@ -27,25 +26,9 @@ type FindingWriter interface { // Findings keeps a bundle's open findings and says them through the module's writer (design 47 G §689, A-14): its `Say` is // the Finding callback of the Driver and the Holder; the writer is the held writer (views.HeldWriter), which holds what is open (A-29, A-32). type Findings struct { - Writer FindingWriter // set by Use once the runtime has its channel (the held writer reads its state at its start) + Writer FindingWriter Logf func(string, ...any) Now func() time.Time - - mu sync.Mutex -} - -// Use sets the writer, once the runtime answers a bundle's state calls. -func (k *Findings) Use(w FindingWriter) { - k.mu.Lock() - k.Writer = w - k.mu.Unlock() -} - -// writer is the writer set, nil before Use. -func (k *Findings) writer() FindingWriter { - k.mu.Lock() - defer k.mu.Unlock() - return k.Writer } // Say raises (raised) or clears the finding of a kind about a subject. Its id is the seat's and the subject's, each escaped @@ -53,13 +36,8 @@ func (k *Findings) writer() FindingWriter { func (k *Findings) Say(kind, subject, words string, raised bool) { id := keyparts.EscapeName(Self) + "." + keyparts.EscapeName(subject) key := views.FindingKey("seat", id, kind) - w := k.writer() - if w == nil { - k.Logf("the finding %s is not said: the writer is not made yet", key) - return - } if !raised { - if err := w.Clear(context.Background(), "seat", id, kind, "it no longer holds"); err != nil { + if err := k.Writer.Clear(context.Background(), "seat", id, kind, "it no longer holds"); err != nil { k.Logf("the finding %s could not be cleared: %v", key, err) } return @@ -71,7 +49,7 @@ func (k *Findings) Say(kind, subject, words string, raised bool) { f := meshconditions.Finding{Scope: "seat", ID: id, Kind: kind, Subject: meshconditions.Subject{Scope: "seat", ID: id}, Severity: meshconditions.FindingSeverityWarning, Summary: words, Headline: words, Explanation: words, Source: kind, Observer: Self, At: at.UTC()} - if err := w.Write(context.Background(), f); err != nil { + if err := k.Writer.Write(context.Background(), f); err != nil { k.Logf("the finding %s could not be written: %v", key, err) } } diff --git a/modules/gitea/cmd/package-registry/findings.go b/modules/gitea/cmd/package-registry/findings.go index 330f545c5..ebbce5955 100644 --- a/modules/gitea/cmd/package-registry/findings.go +++ b/modules/gitea/cmd/package-registry/findings.go @@ -3,7 +3,6 @@ package main import ( "context" "strings" - "sync" "time" meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" @@ -26,25 +25,9 @@ type findingWriter interface { // Findings keeps a bundle's open findings and says them through the module's writer (design 47 G §689, A-14): its `Say` is // the Finding callback of the Driver and the Holder; the writer is the held writer (views.HeldWriter), which holds what is open (A-29, A-32). type Findings struct { - Writer findingWriter // set by Use once the runtime has its channel (the held writer reads its state at its start) + Writer findingWriter Logf func(string, ...any) Now func() time.Time - - mu sync.Mutex -} - -// Use sets the writer, once the runtime answers a bundle's state calls. -func (k *Findings) Use(w findingWriter) { - k.mu.Lock() - k.Writer = w - k.mu.Unlock() -} - -// writer is the writer set, nil before Use. -func (k *Findings) writer() findingWriter { - k.mu.Lock() - defer k.mu.Unlock() - return k.Writer } // Say raises (raised) or clears the finding of a kind about a subject. Its id is the seat's and the subject's, each escaped @@ -52,13 +35,8 @@ func (k *Findings) writer() findingWriter { func (k *Findings) Say(kind, subject, words string, raised bool) { id := keyparts.EscapeName(packageseats.Self) + "." + keyparts.EscapeName(subject) key := views.FindingKey("seat", id, kind) - w := k.writer() - if w == nil { - k.Logf("the finding %s is not said: the writer is not made yet", key) - return - } if !raised { - if err := w.Clear(context.Background(), "seat", id, kind, "it no longer holds"); err != nil { + if err := k.Writer.Clear(context.Background(), "seat", id, kind, "it no longer holds"); err != nil { k.Logf("the finding %s could not be cleared: %v", key, err) } return @@ -70,7 +48,7 @@ func (k *Findings) Say(kind, subject, words string, raised bool) { f := meshconditions.Finding{Scope: "seat", ID: id, Kind: kind, Subject: meshconditions.Subject{Scope: "seat", ID: id}, Severity: meshconditions.FindingSeverityWarning, Summary: words, Headline: words, Explanation: words, Source: kind, Observer: packageseats.Self, At: at.UTC()} - if err := w.Write(context.Background(), f); err != nil { + if err := k.Writer.Write(context.Background(), f); err != nil { k.Logf("the finding %s could not be written: %v", key, err) } } diff --git a/modules/gitea/cmd/package-registry/main.go b/modules/gitea/cmd/package-registry/main.go index 0314439d5..02de1384c 100644 --- a/modules/gitea/cmd/package-registry/main.go +++ b/modules/gitea/cmd/package-registry/main.go @@ -29,21 +29,22 @@ var ToolNames = []string{"go_packages", "go_retention", "go_incoming", "npm_pack var findings = &Findings{Logf: func(f string, a ...any) { fmt.Fprintf(os.Stderr, f+"\n", a...) }} func main() { - // The bundle's findings go through the module's held writer (design 47 G A-16, A-29, A-32). The runtime answers the writer's - // state and subscription only once Serve has its channel, so it is made then. + // The bundle's findings go through the module's held writer (design 47 G A-16, A-29, A-32). + w, err := views.NewStdioHeldWriter(views.WriterConfig[meshconditions.Finding, meshconditions.FindingCleared, meshconditions.FindingsStated, meshconditions.FindingsAskedEvent]{ + Asked: meshconditions.SubjectFindingsAsked, Module: packageseats.Self, State: stdio.State("findings"), Kinds: findingKinds}) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + findings.Writer = w + // the runtime answers the writer's state and subscription only once Serve has its channel go func() { <-stdio.Served() // the keys of the older form end in no kind the writer owns, so it does not clear them (A-31) if err := DeleteOldFindings(stdio.State("findings"), packageseats.Self, findingKinds); err != nil { fmt.Fprintln(os.Stderr, "the old findings are not deleted:", err) } - w, err := views.NewStdioHeldWriter(views.WriterConfig[meshconditions.Finding, meshconditions.FindingCleared, meshconditions.FindingsStated, meshconditions.FindingsAskedEvent]{ - Asked: meshconditions.SubjectFindingsAsked, Module: packageseats.Self, State: stdio.State("findings"), Kinds: findingKinds}) - if err == nil { - findings.Use(w) - err = w.Start(context.Background()) - } - if err != nil { + if err := w.Start(context.Background()); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) }