fix move cancel issue where tags and peers diverge (#3354)

This can happen if the move was initiated by the user.
A subsequent cancel resets the initial peer list.
The original peer list was picked on the old set of tags.
A cancel would then keep the new list of tags but reset
to the old peers. Thus tags and peers diverge.

The problem is that at the time of cancel, the old
placement tags can't be found anymore.

This fix causes cancel to remove the placement tags, if
the old peers do not satisfy the new placement tags.

Signed-off-by: Matthias Hanel <mh@synadia.com>
This commit is contained in:
Matthias Hanel
2022-08-10 18:48:18 +02:00
committed by GitHub
parent 2cf2868406
commit 7015e46dd9
2 changed files with 88 additions and 0 deletions

View File

@@ -2465,6 +2465,34 @@ func (s *Server) jsLeaderServerStreamCancelMoveRequest(sub *subscription, c *cli
peers := currPeers[:cfg.Replicas]
// Remove placement in case tags don't match
// This can happen if the move was initiated by modifying the tags.
// This is an account operation.
// This can NOT happen when the move was initiated by the system account.
// There move honors the original tag list.
if cfg.Placement != nil && len(cfg.Placement.Tags) != 0 {
FOR_TAGCHECK:
for _, peer := range peers {
si, ok := s.nodeToInfo.Load(peer)
if !ok {
// can't verify tags, do the safe thing and error
resp.Error = NewJSStreamGeneralError(
fmt.Errorf("peer %s not present for tag validation", peer))
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
return
}
nodeTags := si.(nodeInfo).tags
for _, tag := range cfg.Placement.Tags {
if !nodeTags.Contains(tag) {
// clear placement as tags don't match
cfg.Placement = nil
break FOR_TAGCHECK
}
}
}
}
s.Noticef("Requested cancel of move: R=%d '%s > %s' to peer set %+v and restore previous peer set %+v",
cfg.Replicas, streamName, accName, s.peerSetToNames(currPeers), s.peerSetToNames(peers))