Snapshot initial consumer info when needed.

Signed-off-by: Derek Collison <derek@nats.io>
This commit is contained in:
Derek Collison
2022-02-09 13:48:37 -08:00
parent 3dcf0246c6
commit da9046b2e6
3 changed files with 39 additions and 2 deletions

View File

@@ -239,6 +239,7 @@ type consumer struct {
maxdc uint64
waiting *waitQueue
cfg ConsumerConfig
ici *ConsumerInfo
store ConsumerStore
active bool
replay bool
@@ -849,6 +850,9 @@ func (o *consumer) setLeader(isLeader bool) {
}
o.mu.Unlock()
// Snapshot initial info.
o.infoWithSnap(true)
// Now start up Go routine to deliver msgs.
go o.loopAndGatherMsgs(qch)
@@ -1830,8 +1834,33 @@ func (o *consumer) writeStoreStateUnlocked() error {
return o.store.Update(&state)
}
// Returns an initial info. Only applicable for non-clustered consumers.
// We will clear after we return it, so one shot.
func (o *consumer) initialInfo() *ConsumerInfo {
o.mu.Lock()
ici := o.ici
o.ici = nil // gc friendly
o.mu.Unlock()
if ici == nil {
ici = o.info()
}
return ici
}
// Clears our initial info.
// Used when we have a leader change in cluster mode but do not send a response.
func (o *consumer) clearInitialInfo() {
o.mu.Lock()
o.ici = nil // gc friendly
o.mu.Unlock()
}
// Info returns our current consumer state.
func (o *consumer) info() *ConsumerInfo {
return o.infoWithSnap(false)
}
func (o *consumer) infoWithSnap(snap bool) *ConsumerInfo {
o.mu.RLock()
mset := o.mset
if mset == nil || mset.srv == nil {
@@ -1885,6 +1914,11 @@ func (o *consumer) info() *ConsumerInfo {
o.expireWaiting()
info.NumWaiting = o.waiting.len()
}
// If we were asked to snapshot do so here.
if snap {
o.ici = info
}
return info
}

View File

@@ -3244,7 +3244,7 @@ func (s *Server) jsConsumerCreate(sub *subscription, c *client, a *Account, subj
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
return
}
resp.ConsumerInfo = o.info()
resp.ConsumerInfo = o.initialInfo()
s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(resp))
}

View File

@@ -3292,6 +3292,9 @@ func (js *jetStream) processConsumerLeaderChange(o *consumer, isLeader bool) {
}
if !isLeader || hasResponded {
if isLeader {
o.clearInitialInfo()
}
return
}
@@ -3300,7 +3303,7 @@ func (js *jetStream) processConsumerLeaderChange(o *consumer, isLeader bool) {
resp.Error = NewJSConsumerCreateError(err, Unless(err))
s.sendAPIErrResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp))
} else {
resp.ConsumerInfo = o.info()
resp.ConsumerInfo = o.initialInfo()
s.sendAPIResponse(client, acc, subject, reply, _EMPTY_, s.jsonResponse(&resp))
if node := o.raftNode(); node != nil {
o.sendCreateAdvisory()