G A-37: views.NewStdioHeldWriter, and the held writer holds the findings a reader writes through it
A stdio module's held writer fills Publish and Listen as NewStdioWriter does; HeldWriter.WriteWire holds the finding as Write does, so a views reader's first-view findings are in the held set and in findings-stated. Builds: design 47 G A-37, A-29, A-16
This commit is contained in:
@@ -88,3 +88,13 @@ func (h *HeldWriter[F, C, S, A]) Clear(ctx context.Context, scope, id, kind, why
|
||||
h.mu.Unlock()
|
||||
return h.Writer.Clear(ctx, scope, id, kind, why)
|
||||
}
|
||||
|
||||
// WriteWire is Write of a finding in its wire form, held as Write holds it (design 47 G A-37): a views reader writing through
|
||||
// the held writer has its findings in the held set, so in the statement.
|
||||
func (h *HeldWriter[F, C, S, A]) WriteWire(ctx context.Context, finding map[string]any) error {
|
||||
var f F
|
||||
if err := fillFrom(&f, finding); err != nil {
|
||||
return err
|
||||
}
|
||||
return h.Write(ctx, f)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,18 @@ func NewStdioWriter[F, C, S, A any](cfg WriterConfig[F, C, S, A]) (*Writer[F, C,
|
||||
func newStdioWriter[F, C, S, A any](cfg WriterConfig[F, C, S, A],
|
||||
emit func(string, any, ...stdio.EmitOptions) error,
|
||||
subscribe func(string, func(stdio.Envelope) error) error) (*Writer[F, C, S, A], error) {
|
||||
return NewWriter(withStdioPlumbing(cfg, emit, subscribe))
|
||||
}
|
||||
|
||||
// NewStdioHeldWriter is NewHeldWriter for a stdio module: it fills `Publish` and `Listen` as NewStdioWriter does (design 47
|
||||
// G A-37, after A-16).
|
||||
func NewStdioHeldWriter[F, C, S, A any](cfg WriterConfig[F, C, S, A]) (*HeldWriter[F, C, S, A], error) {
|
||||
return NewHeldWriter(withStdioPlumbing(cfg, stdio.Emit, stdio.SubscribeNew))
|
||||
}
|
||||
|
||||
func withStdioPlumbing[F, C, S, A any](cfg WriterConfig[F, C, S, A],
|
||||
emit func(string, any, ...stdio.EmitOptions) error,
|
||||
subscribe func(string, func(stdio.Envelope) error) error) WriterConfig[F, C, S, A] {
|
||||
if cfg.Publish == nil {
|
||||
cfg.Publish = func(_ context.Context, subject string, data []byte, id string) error {
|
||||
event, err := eventOfSubject(subject)
|
||||
@@ -50,7 +62,7 @@ func newStdioWriter[F, C, S, A any](cfg WriterConfig[F, C, S, A],
|
||||
return func() { stopped.Store(true) }, nil
|
||||
}
|
||||
}
|
||||
return NewWriter(cfg)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// eventOfSubject is the event of a subject of FindingSubjects: `mesh.stream.<module>.event.<event>.<node>`.
|
||||
|
||||
@@ -97,6 +97,29 @@ func subStdioWriterPublishesAndListensThroughTheModulesOwnPlumbing(t *testing.T)
|
||||
if err := w.cfg.Publish(context.Background(), "obs.event", nil, ""); err == nil {
|
||||
t.Fatal("a subject of no event form is refused")
|
||||
}
|
||||
// the held form fills the same plumbing and states what it holds (design 47 G A-37)
|
||||
out = nil
|
||||
h, err := NewHeldWriter(withStdioPlumbing(WriterConfig[swFinding, swCleared, swStated, swAsked]{
|
||||
Module: "m", Node: "n1", State: noState{}, Asked: "mesh.seat.s.event.findings-asked",
|
||||
}, func(event string, body any, o ...stdio.EmitOptions) error {
|
||||
raw, _ := json.Marshal(body)
|
||||
out = append(out, said{event, string(raw), o[0]})
|
||||
return nil
|
||||
}, func(string, func(stdio.Envelope) error) error { return nil }))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := h.Write(context.Background(), swFinding{Kind: "k", Scope: "module", ID: "x", Observer: "m", Subject: struct {
|
||||
Scope string `json:"scope"`
|
||||
}{"module"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := h.State(context.Background(), "a"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(out) == 0 || out[len(out)-1].event != "findings-stated" || !strings.Contains(out[len(out)-1].body, `"id":"x"`) {
|
||||
t.Fatalf("a stdio held writer states its findings: %+v", out)
|
||||
}
|
||||
}
|
||||
|
||||
type noState struct{}
|
||||
|
||||
+13
-1
@@ -495,6 +495,13 @@ func subHeldWriterStatesWhatItHoldsFromItsOwnState(t *testing.T) {
|
||||
if err := h.Write(ctx, testFinding{Kind: "k", ID: "no-scope"}); err == nil {
|
||||
t.Fatal("a finding that breaks a rule was held")
|
||||
}
|
||||
// a views reader writes its findings in the wire form: they are held as well (design 47 G A-37)
|
||||
var wire map[string]any
|
||||
rawWire, _ := json.Marshal(finding("wired", "from a reader"))
|
||||
_ = json.Unmarshal(rawWire, &wire)
|
||||
if err := h.WriteWire(ctx, wire); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := h.Clear(ctx, "module", "seeded", "k", "no longer"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -504,9 +511,14 @@ func subHeldWriterStatesWhatItHoldsFromItsOwnState(t *testing.T) {
|
||||
}
|
||||
var stated testStated
|
||||
if len(sent) != 1 || sent[0].subject != subjects.Stated || json.Unmarshal(sent[0].data, &stated) != nil ||
|
||||
len(stated.Findings) != 1 || stated.Findings[0].ID != "raised" || stated.Asked != "a1" {
|
||||
len(stated.Findings) != 2 || stated.Asked != "a1" {
|
||||
t.Fatalf("the statement says %+v after %d events", stated, len(sent))
|
||||
}
|
||||
ids := []string{stated.Findings[0].ID, stated.Findings[1].ID}
|
||||
slices.Sort(ids)
|
||||
if ids[0] != "raised" || ids[1] != "wired" {
|
||||
t.Fatalf("the statement says %v", ids)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFindingSubjectsAreTheEventsStreamForm runs the tests of this package that were merged to keep the module within its test budget (design 47 G §419), each as a subtest.
|
||||
|
||||
Reference in New Issue
Block a user