[FIXED] LeafNode: possible duplicate messages in complex setup

This is specific to setup described [here](https://github.com/nats-io/nats-server/issues/3191#issuecomment-1296974382)
and does not require JetStream to be reproduced. The added test
reproduces the above setup but without JetStream enabled in
the accounts.

Each cluster has a leafnode for a given account to the other
cluster. The accounts import/export a subject. When a consumer
is connected to cluster "B" and the producer is on cluster "A"
there was a duplicate message. Due to shadow subscription caused
by the import/export rules, an additional subscription was
sent across the leafnode.

Resolves #3191

Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
This commit is contained in:
Ivan Kozlovic
2022-11-03 12:34:01 -06:00
parent 0f8aa11422
commit 91c84c03c2
2 changed files with 263 additions and 35 deletions

View File

@@ -816,6 +816,7 @@ func (s *Server) removeLeafNodeURL(urlStr string) bool {
// Server lock is held on entry
func (s *Server) generateLeafNodeInfoJSON() {
s.leafNodeInfo.Cluster = s.cachedClusterName()
s.leafNodeInfo.LeafNodeURLs = s.leafURLsMap.getAsStringSlice()
s.leafNodeInfo.WSConnectURLs = s.websocket.connectURLsMap.getAsStringSlice()
b, _ := json.Marshal(s.leafNodeInfo)
@@ -1767,6 +1768,11 @@ func (s *Server) updateLeafNodes(acc *Account, sub *subscription, delta int32) {
// Check to make sure this sub does not have an origin cluster than matches the leafnode.
ln.mu.Lock()
skip := (sub.origin != nil && string(sub.origin) == ln.remoteCluster()) || !ln.canSubscribe(string(sub.subject))
// If skipped, make sure that we still let go the "$LDS." subscription that allows
// the detection of a loop.
if skip && bytes.HasPrefix(sub.subject, []byte(leafNodeLoopDetectionSubjectPrefix)) {
skip = false
}
ln.mu.Unlock()
if skip {
continue