The consume side on NATS, and the window held by the server
The other implementation behind the seam, so the store-window guarantee now has both: one loop, one message at a time, the same window deciding. What differs is where a held message lives, and that is the whole point of the move — the AMQP side keeps an unacknowledged delivery in this process, bounded by the prefetch and lost if the controller stops; this keeps eight bytes saying when the window opened, and the message stays the server's. Checked against a running server, seven claims that reasoning cannot answer: a report is heard and leaves the work queue; one the store cannot take is naked with a delay, stays in the stream, and is recorded when the store returns; one about a superseded declaration is settled without being acted on; one the store never takes is let go once the bound passes; a heartbeat is heard and nothing is persisted; and the enrolment answer reaches the address the request carried in its payload — the test design 25 §2 asks for, so the reason for that field cannot quietly become folklore. Three things the wiring forced into the open: **The controller could not have consumed a module event.** Its permissions granted no event subject to subscribe and no ack subject on the events stream, so every announcement would have been redelivered for ever, refused by the list it already had. Both narrow: each followed subject named, not `mesh.mod.*.>`. **The controller's consumers are not derived.** It files no manifest, so its authority cannot come from a declaration that does not exist; they sit beside the mesh's own streams and are asserted the same way. No max-deliver on CONTROL — the window's bound is the controller's, and a server that dead-lettered first would discard the push the stream exists to protect. **Channels, not callbacks.** The library would run a handler on its own goroutine, and the window's bookkeeping is unlocked because the AMQP loop never had two.
This commit is contained in:
@@ -80,6 +80,20 @@ type EnrolRequest struct {
|
||||
// it. Nil from a node that found none, which is every converged one.
|
||||
Tunnel *Tunnel `json:"tunnel,omitempty"`
|
||||
|
||||
// ReplyTo is where the answer goes, as a field of the request rather than the transport's own
|
||||
// reply address.
|
||||
//
|
||||
// **Because a stream eats the transport's field** (design 25 §2, verified against a running
|
||||
// server): a message a JetStream consumer delivers has had its reply field claimed for that
|
||||
// consumer's own ack address, so by the time the controller sees an enrolment, the field names
|
||||
// where the *controller* must acknowledge, not where the node is waiting. An enrolment is the
|
||||
// case that matters — a caller waiting on an ephemeral inbox, over a subject the store window
|
||||
// may legitimately delay by several nak cycles.
|
||||
//
|
||||
// Empty on the bus the mesh runs on today, where the delivery carries the reply queue and the
|
||||
// field means what it has always meant.
|
||||
ReplyTo string `json:"reply_to,omitempty"`
|
||||
|
||||
// Redelivered is set by the control plane, never sent: the broker handed this request over a
|
||||
// second time. Such a request does not finish an enrolment already spent — the first time may
|
||||
// have answered, and the node holds what it was told.
|
||||
|
||||
Reference in New Issue
Block a user