nats_stream_messages shows a body only for the stream EVENTS (issue 1966, review 1)
mesh/delivery merged: source.main moved to novox/mesh-catalog@fd9147087ef6
mesh/check checking a3d141e79351 on fd9147087ef6
mesh/delivery merged: source.main moved to novox/mesh-catalog@fd9147087ef6
mesh/check checking a3d141e79351 on fd9147087ef6
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -110,10 +109,10 @@ const (
|
||||
maxAsks = 3000
|
||||
)
|
||||
|
||||
// eventStream is a stream that keeps events: the shared EVENTS and a seat's kept events SEAT_<SEAT>_EVENTS. Only these show
|
||||
// a body; every other stream holds calls and replies, asks, mail, dead letters, records or logs, whose bodies carry what
|
||||
// is not an event's to show. It fails closed: a stream not named here shows sequence, subject, time and size only.
|
||||
var eventStream = regexp.MustCompile(`^(EVENTS|SEAT_[A-Z0-9]+(_[A-Z0-9]+)*_EVENTS)$`)
|
||||
// bodyStream is the one stream that shows a body: the shared EVENTS, which holds every event, the seats' kept event streams
|
||||
// (SEAT_<seat>_<event>) being sourced from it. Every other stream holds calls and replies, asks, mail, dead letters, records
|
||||
// or logs, whose bodies are not an event's to show: it answers sequence, subject, time and size only.
|
||||
const bodyStream = "EVENTS"
|
||||
|
||||
// MessageRow is one message of the answer.
|
||||
type MessageRow struct {
|
||||
@@ -272,7 +271,7 @@ func readTools(jsz func() ([]byte, error), open MsgOpen) []stdio.Tool {
|
||||
return Consumer(doc, arg(a, "stream"), arg(a, "consumer"))
|
||||
}},
|
||||
{Name: "nats_stream_messages",
|
||||
Description: "The messages a stream keeps for one subject (a filter with * or > is allowed), newest first: sequence, subject, time and size of each, and the body only when asked for, no larger than 4 KiB, and only on an event stream (EVENTS or a seat's kept events); on every other stream (asks, calls and replies, mail, dead letters, records, logs) only sequence, subject, time and size. Bounded by count (default 20, at most 200) and bytes (default 1 MiB); says when it stopped before the oldest the stream keeps. Read on the bus module's own credential. Refuses the streams of a module's kept state (KV_*, OBJ_*): their values are read through their owners' tools; this tool is for lost events.",
|
||||
Description: "The messages a stream keeps for one subject (a filter with * or > is allowed), newest first: sequence, subject, time and size of each, and the body only when asked for, no larger than 4 KiB, and only on the stream EVENTS (every kept event is there); on every other stream (kept events, asks, calls and replies, mail, dead letters, records, logs) only sequence, subject, time and size. Bounded by count (default 20, at most 200) and bytes (default 1 MiB); says when it stopped before the oldest the stream keeps. Read on the bus module's own credential. Refuses the streams of a module's kept state (KV_*, OBJ_*): their values are read through their owners' tools; this tool is for lost events.",
|
||||
Input: map[string]any{"stream": str("the stream, e.g. EVENTS"), "subject": str("a subject or filter, e.g. mesh.mod.mesh-delivery-indexer.event.view-changed"),
|
||||
"count": num("at most this many (default 20, at most 200)"), "bytes": num("at most this many bytes of messages (default 1048576)"),
|
||||
"body": map[string]any{"type": "boolean", "description": "carry the body of each message of at most 4 KiB"}},
|
||||
@@ -296,8 +295,8 @@ func readTools(jsz func() ([]byte, error), open MsgOpen) []stdio.Tool {
|
||||
bytes, _ := a["bytes"].(float64)
|
||||
body, _ := a["body"].(bool)
|
||||
bodyHidden := ""
|
||||
if body && !eventStream.MatchString(stream) {
|
||||
body, bodyHidden = false, stream+" is not an event stream (EVENTS or a seat's kept events): its bodies are not shown, only sequence, subject, time and size"
|
||||
if body && stream != bodyStream {
|
||||
body, bodyHidden = false, stream+" is not the stream EVENTS: its bodies are not shown, only sequence, subject, time and size"
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -147,14 +147,17 @@ func TestTheReadToolsAreServedAndRefuseBadArguments(t *testing.T) {
|
||||
if rows := ev.(map[string]any)["messages"].([]MessageRow); len(rows) != 1 || rows[0].Body != "body-50" {
|
||||
t.Fatalf("an event stream showed no body: %v", ev)
|
||||
}
|
||||
for _, s := range []string{"EVENTS", "SEAT_NODE_BUILD_GO_EVENTS"} {
|
||||
if !eventStream.MatchString(s) {
|
||||
t.Fatalf("%s is an event stream", s)
|
||||
seat := strings.Replace(consumerJsz, `"name":"EVENTS"`, `"name":"SEAT_node-engine_running"`, 1)
|
||||
for _, tl := range readTools(func() ([]byte, error) { return []byte(seat), nil },
|
||||
func(context.Context) (MsgGet, func(), error) {
|
||||
return fake(map[uint64]string{50: "a.b"}, nil), func() {}, nil
|
||||
}) {
|
||||
if tl.Name != "nats_stream_messages" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
for _, s := range []string{"SEAT_CHANNEL", "ASKS", "MAIL", "DEAD_LETTERS", "LOG_X", "SEAT_X_worker"} {
|
||||
if eventStream.MatchString(s) {
|
||||
t.Fatalf("%s is not an event stream", s)
|
||||
o, err := tl.Run(map[string]any{"stream": "SEAT_node-engine_running", "subject": "a.b", "body": true})
|
||||
if err != nil || o.(map[string]any)["messages"].([]MessageRow)[0].Body != "" {
|
||||
t.Fatalf("a kept event stream showed a body: %v %v", o, err)
|
||||
}
|
||||
}
|
||||
if _, err := by["nats_stream_messages"](map[string]any{"stream": "EVENTS"}); err == nil {
|
||||
|
||||
Reference in New Issue
Block a user