Two consumers may share a name; they must not share a delivery subject
novox/hq 04-ISSUES/146. A push consumer delivers onto an ordinary subject and everything subscribed to it gets a copy. The controller holds a consumer called 'controller' on CONTROL and another called 'controller' on EVENTS, and both were given _DELIVER.controller — so the one process, holding both subscriptions, acted on every message twice. Measured: one enrolment published, one message in the stream, one delivery, no redelivery, and the controller enrolled the machine twice — the second minting a credential that replaced the one the machine had just been handed, which is why it then reconnected for ever as a user whose password the mesh had rotated. Every report and every followed event doubled the same way, silently. The stream goes in the subject because the pair is what identifies a consumer. A subscriber's permission gains the same shape, keeping the bare name so an existing consumer keeps working until the next assertion moves it.
This commit is contained in:
@@ -184,7 +184,20 @@ func (j *JetStream) EnsureConsumer(c Consumer) error {
|
||||
// without the other is refused by the server with a message that does not say which half is
|
||||
// missing.
|
||||
if c.Queue != "" || c.Push {
|
||||
want.DeliverSubject = "_DELIVER." + c.Name
|
||||
// **Per consumer, which means per stream as well as per name** (novox/hq 04-ISSUES/146).
|
||||
// A push consumer delivers onto an ordinary subject, and everything subscribed to that
|
||||
// subject gets a copy. The controller holds a consumer called `controller` on CONTROL and
|
||||
// another called `controller` on EVENTS, and both were given `_DELIVER.controller` — so the
|
||||
// one process, holding both subscriptions, acted on every message twice. It enrolled a
|
||||
// joining machine twice from one request, minting a second credential that replaced the one
|
||||
// the machine had just been given; the same doubling applied to every report and every
|
||||
// event the controller follows.
|
||||
//
|
||||
// The stream is in the name because the pair is what identifies a consumer — the server
|
||||
// scopes a durable's name to its stream, and this subject is the only place that scoping
|
||||
// was dropped. Already within what the controller may subscribe (`_DELIVER.controller.>`),
|
||||
// so no permission moves.
|
||||
want.DeliverSubject = DeliverSubjectFor(c)
|
||||
}
|
||||
|
||||
switch _, err := j.js.ConsumerInfo(c.Stream, c.Name); {
|
||||
|
||||
Reference in New Issue
Block a user