Pull Consumer Updates#2776
Conversation
Signed-off-by: Derek Collison <derek@nats.io>
Cleaned up code, made more consistent, utilize loopAndGather. Allow pull consumers to have AckAll as well as AckExplicit. Signed-off-by: Derek Collison <derek@nats.io>
… size and expiration. Signed-off-by: Derek Collison <derek@nats.io>
Signed-off-by: Derek Collison <derek@nats.io>
matthiashanel
left a comment
There was a problem hiding this comment.
LGTM
Change looks ok. But not super familiar, and a second set of eyes would be good
|
|
||
| // If we are a pull mode consumer, report on number of waiting requests. | ||
| if o.isPullMode() { | ||
| o.expireWaiting() |
There was a problem hiding this comment.
Does this mean that doing sub.ConsumerInfo() will expire the pending requests?
There was a problem hiding this comment.
Yes it will reclaim old requests here, and when we move to a wait state in the loop and gather, and we check them when we pop to deliver a message.
There was a problem hiding this comment.
Not sure I understand how this all work, but when the user will try to subscribe, the library does a ConsumerInfo() (assuming a consumer name is provided by the user). So expiring existing pending requests just because an app wants to consume seem strange, but again, I may not understand well how pull consumers work in the server...
There was a problem hiding this comment.
I think this is good approach, it was needed some way to trigger the expiration of accumulated pending requests that have just timed out without a client issuing a 'get next' request. Now when the state is confirmed by using nats consumer info for example, the expired requests would no longer be accounted in the NumWaiting field.
There was a problem hiding this comment.
We used to expire pending requests sporadically and not on a regular time interval. I did not opt for a time interval per se but added a bunch of spots to where we do collect now.
- Namely when we pop a request we now check inline, so no delivering to a request that we invalidate.
- When the consumer's loopAndGather goes into a waiting state we check the pending list then as well.
- When someone asks for consumer info on a pull consumer.
| // If not durable determine the inactive threshold. | ||
| if !o.isDurable() { | ||
| if o.cfg.InactiveThreshold != 0 { | ||
| o.dthresh = o.cfg.InactiveThreshold |
There was a problem hiding this comment.
Would it make sense to constrain minimum inactive threshold around max ack time? They should expire some time after the last ack is expected, important for WQs etc
There was a problem hiding this comment.
If this ack can be extended, that activity should also extend the inactivity timer(?)
There was a problem hiding this comment.
Pull consumer logic is different, if we have seen a request in that window we are good, if not attempt to expire all invalid requests and if empty, then we consider inactive.
There was a problem hiding this comment.
But if there are outstanding messages waiting on acks the consumer is essentially still valid - even with no interest or waiting pulls recently, it still has to wait for acks until the past the latest possible ack.
There was a problem hiding this comment.
We do not follow that philosophy with ephemerals today. E.g. push consumers if the delivery subject loses interest for some period of time (5s default IIRC) we reclaim the consumer, regardless of pending acks.
This stays consistent but we could consider adding this, but I feel pretty strong we would not want to do that.
One app sends ack that gets lost and then disconnects, we will never clean up an ephemeral pull consumer if the logic requires the acks.
There was a problem hiding this comment.
Not “never” just up to max ack waiting time.
There was a problem hiding this comment.
Possibly but that would be inconsistent with how we do that today for push. So prefer to keep them the same for now and add in that logic if needed to a later date.
Also, if I am thinking about this correctly, if we only wait an additional max wait but take no other action, this feels like just reclaiming the consumer since we don't wait for non acked messages. IMO..
There was a problem hiding this comment.
Yeah - my thinking is if you are processing messages from a WQ removing the consumer too early while there are still messages in flight could result in processed messages not being removed from tbe stream.
Agree it’s something we can park for a later time but seems important.
There was a problem hiding this comment.
Good point but if its WQ and the consumer goes away that releases all of the messages anyway that were being held for that consumer.
| } | ||
| // They are also required to be durable since otherwise we will not know when to | ||
| // clean them up. | ||
| if config.Durable == _EMPTY_ { |
There was a problem hiding this comment.
Just a note, this is making the nats.go client test suite fail because we were checking there that a durable name was required. Client tests will need some adjustment.
|
|
||
| // If we are a pull mode consumer, report on number of waiting requests. | ||
| if o.isPullMode() { | ||
| o.expireWaiting() |
There was a problem hiding this comment.
Not sure I understand how this all work, but when the user will try to subscribe, the library does a ConsumerInfo() (assuming a consumer name is provided by the user). So expiring existing pending requests just because an app wants to consume seem strange, but again, I may not understand well how pull consumers work in the server...
Signed-off-by: Derek Collison <derek@nats.io>
6796265 to
32c3c9e
Compare
…fnode. When we want to track service import response interest across a leafnode we need to send sub and unsub for all response _R_ subjects versus using a wildcard. Signed-off-by: Derek Collison <derek@nats.io>
ddcc3b1 to
43eff40
Compare
Under load we could have a message committed to the underlying store when a consumer was being created and then it increase num pending again when the stream signals the consumers. This fix just remembers the last seq of the state when we calculate sgap and test before adding in the stream code. Signed-off-by: Derek Collison <derek@nats.io>
Signed-off-by: Derek Collison <derek@nats.io>
This change cleans up alot of the inner workings of pull consumers to be more resilient, better at waiting request management, and the ability to determine and watch interest cross account.
We also introduce new consumer config items to limit next msg requests' batch size and maximum wait times as well as indicate inactive thresholds.
We also now allow pull consumers that are ephemeral (they will auto-cleanup) and can have ack-all, not just ack explicit.
Signed-off-by: Derek Collison derek@nats.io
/cc @nats-io/core