diff --git a/modules/mesh-delivery-view/cmd/mesh-delivery-view/findingwriter.go b/modules/mesh-delivery-view/cmd/mesh-delivery-view/findingwriter.go new file mode 100644 index 00000000..e2bc27e8 --- /dev/null +++ b/modules/mesh-delivery-view/cmd/mesh-delivery-view/findingwriter.go @@ -0,0 +1,33 @@ +package main + +import ( + "context" + + "github.com/nats-io/nats.go" + "github.com/nats-io/nats.go/jetstream" + + condseat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" + "git.novox.be/novox/mesh-sdk/go/process" + "git.novox.be/novox/mesh-sdk/go/views" +) + +// findingWriter is the view's mesh-sdk finding writer (design 47 G §461, §689): the view observes only what its views +// reader finds, so its own observe states none and the writer's statement covers the reader's open findings. The writer +// forms its subjects itself (design 47 G §383, A-13). +func findingWriter(ctx context.Context, cred process.Account, conn *nats.Conn, js jetstream.JetStream, state process.State, logf func(string, ...any)) (*views.Writer[condseat.Finding, condseat.FindingCleared, condseat.FindingsStated, condseat.FindingsAskedEvent], error) { + w, err := views.NewWriter(views.WriterConfig[condseat.Finding, condseat.FindingCleared, condseat.FindingsStated, condseat.FindingsAskedEvent]{ + Module: cred.Module, State: state, Node: cred.Node, JS: js, Conn: conn, Logf: logf, + Observe: func(context.Context) (views.Observed[condseat.Finding], error) { + return views.Observed[condseat.Finding]{}, nil + }, + }) + if err != nil { + return nil, err + } + // A writer that cannot start (the stream of its asks is not there yet) is said; its findings are then kept in the + // state alone and said by the next start (as the node-engine's is). + if err := w.Start(ctx); err != nil { + logf("the finding writer cannot start, its findings are kept in the state alone: %v", err) + } + return w, nil +} diff --git a/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go b/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go index 267f1463..b0181359 100644 --- a/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go +++ b/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go @@ -22,7 +22,6 @@ import ( "syscall" "time" - sdkfindings "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient/findings" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate" "git.novox.be/novox/mesh-delivery/sdk/trunk" @@ -125,8 +124,12 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro } defer calls.Close() reader := &views.ProcessReader{Module: viewstate.ViewModule, Call: calls.Call, Logf: logger.Printf} - findings := process.AwaitBucket(ctx, js, conn, findingsBucket, "a first view unanswered past its bound is said in the log alone", logger.Printf) - reader.Findings = func() views.FindingWriter { return sdkfindings.Writer(ctx, findings.KV) } + writer, err := findingWriter(ctx, cred, conn, js, calls.State("findings"), logger.Printf) + if err != nil { + return fmt.Errorf("the view's finding writer: %w", err) + } + defer writer.Close() + reader.Findings = func() views.FindingWriter { return views.WriterFindings{Writer: writer} } for _, o := range ownersFollowed { if _, err := reader.Follow(o.owner, o.state, o.tool); err != nil { return err @@ -196,12 +199,8 @@ type ReachedEvent struct { Reach json.RawMessage `json:"reach"` } -// The view's own states of its first views (views.StatusState) and of its findings, where the condition keeper raises a -// first view unanswered past its bound (ADR 0615 §6). -var ( - firstViewsBucket = viewstate.ViewModule + "_" + views.StatusState - findingsBucket = viewstate.ViewModule + "_findings" -) +// The view's own state of its first views (views.StatusState). +var firstViewsBucket = viewstate.ViewModule + "_" + views.StatusState // ownersFollowed are the indexer's and the assigner's states the view's process follows by their first views, each by its // owner's read tool (as the view's invokes names it) and views family (its events on the shared events stream); the