mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
[IMPROVED] Optimize locking for consumer info API (#4615)
Signed-off-by: Derek Collison <derek@nats.io>
This commit is contained in:
@@ -4164,9 +4164,20 @@ func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account,
|
|||||||
js.mu.RLock()
|
js.mu.RLock()
|
||||||
isLeader, sa, ca := cc.isLeader(), js.streamAssignment(acc.Name, streamName), js.consumerAssignment(acc.Name, streamName, consumerName)
|
isLeader, sa, ca := cc.isLeader(), js.streamAssignment(acc.Name, streamName), js.consumerAssignment(acc.Name, streamName, consumerName)
|
||||||
ourID := cc.meta.ID()
|
ourID := cc.meta.ID()
|
||||||
var offline bool
|
var rg *raftGroup
|
||||||
|
var offline, isMember bool
|
||||||
if ca != nil {
|
if ca != nil {
|
||||||
offline = s.allPeersOffline(ca.Group)
|
if rg = ca.Group; rg != nil {
|
||||||
|
offline = s.allPeersOffline(rg)
|
||||||
|
isMember = rg.isMember(ourID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Capture consumer leader here.
|
||||||
|
isConsumerLeader := cc.isConsumerLeader(acc.Name, streamName, consumerName)
|
||||||
|
// Also capture if we think there is no meta leader.
|
||||||
|
var isLeaderLess bool
|
||||||
|
if !isLeader {
|
||||||
|
isLeaderLess = cc.meta.GroupLeader() == _EMPTY_ && time.Since(cc.meta.Created()) > lostQuorumIntervalDefault
|
||||||
}
|
}
|
||||||
js.mu.RUnlock()
|
js.mu.RUnlock()
|
||||||
|
|
||||||
@@ -4189,7 +4200,7 @@ func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account,
|
|||||||
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
|
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
|
||||||
return
|
return
|
||||||
} else if ca == nil {
|
} else if ca == nil {
|
||||||
if js.isLeaderless() {
|
if isLeaderLess {
|
||||||
resp.Error = NewJSClusterNotAvailError()
|
resp.Error = NewJSClusterNotAvailError()
|
||||||
// Delaying an error response gives the leader a chance to respond before us
|
// Delaying an error response gives the leader a chance to respond before us
|
||||||
s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
|
s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil)
|
||||||
@@ -4202,38 +4213,35 @@ func (s *Server) jsConsumerInfoRequest(sub *subscription, c *client, _ *Account,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if we are a member of the group and if the group has no leader.
|
// Check to see if we are a member of the group and if the group has no leader.
|
||||||
if js.isGroupLeaderless(ca.Group) {
|
if isMember && js.isGroupLeaderless(ca.Group) {
|
||||||
resp.Error = NewJSClusterNotAvailError()
|
resp.Error = NewJSClusterNotAvailError()
|
||||||
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
|
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have the consumer assigned and a leader, so only the consumer leader should answer.
|
// We have the consumer assigned and a leader, so only the consumer leader should answer.
|
||||||
if !acc.JetStreamIsConsumerLeader(streamName, consumerName) {
|
if !isConsumerLeader {
|
||||||
if js.isLeaderless() {
|
if isLeaderLess {
|
||||||
resp.Error = NewJSClusterNotAvailError()
|
resp.Error = NewJSClusterNotAvailError()
|
||||||
// Delaying an error response gives the leader a chance to respond before us
|
// Delaying an error response gives the leader a chance to respond before us
|
||||||
s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), ca.Group)
|
s.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), ca.Group)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var node RaftNode
|
||||||
|
var leaderNotPartOfGroup bool
|
||||||
|
|
||||||
// We have a consumer assignment.
|
// We have a consumer assignment.
|
||||||
js.mu.RLock()
|
if isMember {
|
||||||
var (
|
js.mu.RLock()
|
||||||
node RaftNode
|
|
||||||
leaderNotPartOfGroup bool
|
|
||||||
isMember bool
|
|
||||||
)
|
|
||||||
rg := ca.Group
|
|
||||||
if rg != nil && rg.isMember(ourID) {
|
|
||||||
isMember = true
|
|
||||||
if rg.node != nil {
|
if rg.node != nil {
|
||||||
node = rg.node
|
node = rg.node
|
||||||
if gl := node.GroupLeader(); gl != _EMPTY_ && !rg.isMember(gl) {
|
if gl := node.GroupLeader(); gl != _EMPTY_ && !rg.isMember(gl) {
|
||||||
leaderNotPartOfGroup = true
|
leaderNotPartOfGroup = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
js.mu.RUnlock()
|
||||||
}
|
}
|
||||||
js.mu.RUnlock()
|
|
||||||
|
|
||||||
// Check if we should ignore all together.
|
// Check if we should ignore all together.
|
||||||
if node == nil {
|
if node == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user