RR-2: the reader reads an accepted kind's stream
mesh/delivery merged: source.main moved to novox/mesh-sdk@83772f2908a1
mesh/check checking 0036455e6380 on 45e143fba672
mesh/delivery merged: source.main moved to novox/mesh-sdk@83772f2908a1
mesh/check checking 0036455e6380 on 45e143fba672
check or delivery; the same kind name may ride both. Builds: design 47 G §409, §415 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
+17
-2
@@ -223,6 +223,12 @@ type Verb struct {
|
|||||||
NeedsApproval bool `json:"needs-approval,omitempty"`
|
NeedsApproval bool `json:"needs-approval,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The streams an accepted kind may ride (design 47 G §415).
|
||||||
|
const (
|
||||||
|
StreamCheck = "check"
|
||||||
|
StreamDelivery = "delivery"
|
||||||
|
)
|
||||||
|
|
||||||
// Message is one accepted message or one event of the seat, its body a JSON Schema.
|
// Message is one accepted message or one event of the seat, its body a JSON Schema.
|
||||||
type Message struct {
|
type Message struct {
|
||||||
// Name is the message's name; an event's may be lower-case words joined by dots (pull.updated), as a module's
|
// Name is the message's name; an event's may be lower-case words joined by dots (pull.updated), as a module's
|
||||||
@@ -245,6 +251,9 @@ type Message struct {
|
|||||||
Keep *Keep `json:"keep,omitempty"`
|
Keep *Keep `json:"keep,omitempty"`
|
||||||
// Callers says who may send an accepted kind, as a verb's (design 47 G §338).
|
// Callers says who may send an accepted kind, as a verb's (design 47 G §338).
|
||||||
Callers *Callers `json:"callers,omitempty"`
|
Callers *Callers `json:"callers,omitempty"`
|
||||||
|
// Stream is the stream an accepted kind rides, StreamCheck or StreamDelivery; its subject is `<stream>.<kind>`, and
|
||||||
|
// the same kind name may ride more than one stream (design 47 G §415).
|
||||||
|
Stream string `json:"stream,omitempty"`
|
||||||
// MaxAgeDays and MaxMiB bound an event kept KeepStream: how long a message is kept and how much the stream holds
|
// MaxAgeDays and MaxMiB bound an event kept KeepStream: how long a message is kept and how much the stream holds
|
||||||
// (design 47 *What the gate owes the forge*: the stream `owed`, 7 days and at most 64 MiB). Given with KeepStream
|
// (design 47 *What the gate owes the forge*: the stream `owed`, 7 days and at most 64 MiB). Given with KeepStream
|
||||||
// alone.
|
// alone.
|
||||||
@@ -814,10 +823,16 @@ func checkMessages(field string, ms []Message, whole bool) Problems {
|
|||||||
}
|
}
|
||||||
if !named.MatchString(m.Name) {
|
if !named.MatchString(m.Name) {
|
||||||
ps = append(ps, Problem{where + ".name", "missing, or not a lower-case name"})
|
ps = append(ps, Problem{where + ".name", "missing, or not a lower-case name"})
|
||||||
} else if seen[m.Name] {
|
} else if key := m.Stream + "/" + m.Name; seen[key] {
|
||||||
ps = append(ps, Problem{where + ".name", fmt.Sprintf("%q twice", m.Name)})
|
ps = append(ps, Problem{where + ".name", fmt.Sprintf("%q twice", m.Name)})
|
||||||
}
|
}
|
||||||
seen[m.Name] = true
|
seen[m.Stream+"/"+m.Name] = true
|
||||||
|
switch {
|
||||||
|
case m.Stream != "" && field != "accepts":
|
||||||
|
ps = append(ps, Problem{where + ".stream", "only an accepted kind rides a stream"})
|
||||||
|
case m.Stream != "" && m.Stream != StreamCheck && m.Stream != StreamDelivery:
|
||||||
|
ps = append(ps, Problem{where + ".stream", fmt.Sprintf("%q is not %s or %s", m.Stream, StreamCheck, StreamDelivery)})
|
||||||
|
}
|
||||||
mode := m.legacyMode()
|
mode := m.legacyMode()
|
||||||
switch {
|
switch {
|
||||||
case m.Keep != nil && field != "events":
|
case m.Keep != nil && field != "events":
|
||||||
|
|||||||
@@ -143,6 +143,13 @@ func TestADefinitionIsReadStrictlyNamingWhatIsWrong(t *testing.T) {
|
|||||||
{"a verb marked for approval", strings.Replace(whole, `"name":"list",`, `"name":"list","needs-approval":true,`, 1), ""},
|
{"a verb marked for approval", strings.Replace(whole, `"name":"list",`, `"name":"list","needs-approval":true,`, 1), ""},
|
||||||
{"a verb marked with a word that is no boolean", strings.Replace(whole, `"name":"list",`, `"name":"list","needs-approval":"yes",`, 1), "not a seat definition's JSON"},
|
{"a verb marked with a word that is no boolean", strings.Replace(whole, `"name":"list",`, `"name":"list","needs-approval":"yes",`, 1), "not a seat definition's JSON"},
|
||||||
{"a bodies section", strings.Replace(whole, `"family":`, `"bodies":{"Finding":{"type":"object"}},"family":`, 1), ""},
|
{"a bodies section", strings.Replace(whole, `"family":`, `"bodies":{"Finding":{"type":"object"}},"family":`, 1), ""},
|
||||||
|
{"one kind on two streams", strings.Replace(whole, `"events":`,
|
||||||
|
`"accepts":[{"name":"step","body":{},"stream":"check"},{"name":"step","body":{},"stream":"delivery"}],"events":`, 1), ""},
|
||||||
|
{"one kind twice on a stream", strings.Replace(whole, `"events":`,
|
||||||
|
`"accepts":[{"name":"step","body":{},"stream":"check"},{"name":"step","body":{},"stream":"check"}],"events":`, 1), `"step" twice`},
|
||||||
|
{"a stream that is none", strings.Replace(whole, `"events":`, `"accepts":[{"name":"step","body":{},"stream":"mail"}],"events":`, 1),
|
||||||
|
`accepts[0].stream: "mail" is not check or delivery`},
|
||||||
|
{"an event on a stream", strings.Replace(whole, `"name":"created"`, `"name":"created","stream":"check"`, 1), "only an accepted kind rides a stream"},
|
||||||
{"over 256 KiB", listGrain[:len(listGrain)-1] + `,"description":"` + strings.Repeat("x", MaxSize) + `"}`,
|
{"over 256 KiB", listGrain[:len(listGrain)-1] + `,"description":"` + strings.Repeat("x", MaxSize) + `"}`,
|
||||||
ErrTooLarge.Error()},
|
ErrTooLarge.Error()},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user