Review round 1: a carried module's queue consumer survives PruneHeard, a work-queue stream's restricted metadata is proven on the server config (issue 1178)
ConsumersOf's carried-module path (a module the tool runner carries, no account of its own — mesh-mail's real shape) was not passing Queues through, so its work-queue consumer was missing from the composed list and PruneHeard would have removed what issueProcess made for it. Fixed, with a test through Users -> ConsumersOf. Extracted EnsureStream's config building into StreamConfigFor, a pure function, so the dead-letters test can assert the restricted metadata EnsureStream would actually send for a work-queue stream instead of setting the dead letter's header by hand, which passed whether or not modstreams.go's out.Restricted = true was there at all.
This commit is contained in:
@@ -154,16 +154,10 @@ func Borrow(j *JetStream) *JetStream {
|
||||
return &lent
|
||||
}
|
||||
|
||||
// EnsureStream creates the stream if it is absent and brings it to match if it is present.
|
||||
//
|
||||
// **Idempotent, because the controller asserts on every start** rather than creating once at
|
||||
// genesis: a stream somebody deleted, or a mesh raised from a restored backup, has to converge
|
||||
// rather than run without the guarantee its messages assume.
|
||||
//
|
||||
// An update, not a delete and recreate. Recreating would discard every message the stream holds
|
||||
// and every consumer's position in it — which for CONTROL means the pushes being held through a
|
||||
// store restart, exactly the guarantee the stream exists for.
|
||||
func (j *JetStream) EnsureStream(s Stream) error {
|
||||
// StreamConfigFor is the server's own config for one of the mesh's streams, pure so the shape it builds —
|
||||
// not least the restricted metadata a work-queue or a grant-restricted stream's dead letters age and hide
|
||||
// by (novox/hq ADR 0436 §6, ADR 0376 §3) — is testable without a server.
|
||||
func StreamConfigFor(s Stream) *nats.StreamConfig {
|
||||
want := &nats.StreamConfig{
|
||||
Name: s.Name,
|
||||
Subjects: s.Subjects,
|
||||
@@ -193,6 +187,20 @@ func (j *JetStream) EnsureStream(s Stream) error {
|
||||
want.MaxMsgsPerSubject = 1
|
||||
want.MaxAge = 0
|
||||
}
|
||||
return want
|
||||
}
|
||||
|
||||
// EnsureStream creates the stream if it is absent and brings it to match if it is present.
|
||||
//
|
||||
// **Idempotent, because the controller asserts on every start** rather than creating once at
|
||||
// genesis: a stream somebody deleted, or a mesh raised from a restored backup, has to converge
|
||||
// rather than run without the guarantee its messages assume.
|
||||
//
|
||||
// An update, not a delete and recreate. Recreating would discard every message the stream holds
|
||||
// and every consumer's position in it — which for CONTROL means the pushes being held through a
|
||||
// store restart, exactly the guarantee the stream exists for.
|
||||
func (j *JetStream) EnsureStream(s Stream) error {
|
||||
want := StreamConfigFor(s)
|
||||
|
||||
switch _, err := j.js.StreamInfo(s.Name); {
|
||||
case err == nil:
|
||||
|
||||
Reference in New Issue
Block a user