stdio: TopicMatches understands the bus's > so an adopted follower hears every event
Builds: design 47 G A-101, §532, §521
This commit is contained in:
+5
-1
@@ -582,7 +582,8 @@ func Ask(key string, body any) (json.RawMessage, error) {
|
||||
}
|
||||
|
||||
// TopicMatches says whether an event's type matches a pattern: `*` is one dot-separated segment, `#`
|
||||
// (or `**`) any number, as the TypeScript SDK matches.
|
||||
// (or `**`) any number, as the TypeScript SDK matches; the bus's own `>` as the last token matches one or more
|
||||
// further tokens (design 47 G A-101), so an adopted follower's `<seat>.<event>.>` hears every event on the seat's event.
|
||||
func TopicMatches(pattern, key string) bool {
|
||||
return matchFrom(strings.Split(pattern, "."), 0, strings.Split(key, "."), 0)
|
||||
}
|
||||
@@ -591,6 +592,9 @@ func matchFrom(p []string, pi int, k []string, ki int) bool {
|
||||
if pi == len(p) {
|
||||
return ki == len(k)
|
||||
}
|
||||
if p[pi] == ">" && pi == len(p)-1 {
|
||||
return ki < len(k)
|
||||
}
|
||||
if p[pi] == "#" || p[pi] == "**" {
|
||||
for skip := ki; skip <= len(k); skip++ {
|
||||
if matchFrom(p, pi+1, k, skip) {
|
||||
|
||||
@@ -153,6 +153,18 @@ func TestABundleSubscribesAndAsksThroughTheRuntime(t *testing.T) {
|
||||
if !TopicMatches("a.#", "a.b.c") || TopicMatches("a.*", "a.b.c") || !TopicMatches("#", "x") {
|
||||
t.Error("topic matching differs from the TypeScript SDK's")
|
||||
}
|
||||
// Design 47 G A-101: the bus's `>` is one or more tokens at the end, and only there.
|
||||
for pattern, want := range map[string]map[string]bool{
|
||||
"s.rev.>": {"s.rev.a": true, "s.rev.a.b": true, "s.rev": false, "s.other.a": false},
|
||||
"s.>.x": {"s.a.x": false},
|
||||
">": {"a": true, "a.b": true},
|
||||
} {
|
||||
for key, ok := range want {
|
||||
if TopicMatches(pattern, key) != ok {
|
||||
t.Errorf("TopicMatches(%q, %q) = %v, want %v", pattern, key, !ok, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Issue 774 notes 84-87: a malformed key is refused before the runtime is asked.
|
||||
for _, key := range []string{"seat:node-service-manager.stop@novox@g14", "seat:a.*", "postgres.list@", "postgres.list@a.b"} {
|
||||
if _, err := Ask(key, nil); err == nil || strings.Contains(err.Error(), "Serve") {
|
||||
|
||||
@@ -719,6 +719,10 @@ func subViews(t *testing.T) {
|
||||
if r.adopted["s.revisions"].local() != "s.revision-said.>" || len(heard) != 1 {
|
||||
t.Errorf("the seat event %v reached the client %v", r.adopted, heard)
|
||||
}
|
||||
// A later revision, said with a further part (`<seat>.<event>.<part>`), reaches the follower by the runtime's own matching.
|
||||
if pat := r.adopted["s.revisions"].local(); !stdio.TopicMatches(pat, "s.revision-said.catalog-revision-9") || !stdio.TopicMatches(pat, "s.revision-said.a.b") {
|
||||
t.Errorf("the pattern %q does not hear a later catalog revision", pat)
|
||||
}
|
||||
f.WaitFor(context.Background(), "3")
|
||||
ended <- true
|
||||
if fd := fs.next(t); fd.Kind != ViewWaitsKind || fd.ID != "reader.s.revisions" {
|
||||
|
||||
Reference in New Issue
Block a user