Prune version clocks based on merged tombstones when merging #23318
This commit is contained in:
parent
a15e459922
commit
be5a0207bb
2 changed files with 43 additions and 6 deletions
|
|
@ -154,10 +154,9 @@ private[cluster] final case class Gossip(
|
|||
|
||||
// 1. merge sets of tombstones
|
||||
val mergedTombstones = tombstones ++ that.tombstones
|
||||
val newTombstonedNodes = mergedTombstones.keySet diff that.tombstones.keySet
|
||||
|
||||
// 2. merge vector clocks (but remove entries for tombstoned nodes)
|
||||
val mergedVClock = newTombstonedNodes.foldLeft(this.version merge that.version) { (vclock, node) ⇒
|
||||
val mergedVClock = mergedTombstones.keys.foldLeft(this.version merge that.version) { (vclock, node) ⇒
|
||||
vclock.prune(VectorClock.Node(Gossip.vclockName(node)))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -339,16 +339,25 @@ class GossipSpec extends WordSpec with Matchers {
|
|||
// TODO test coverage for when leaderOf returns None - I have not been able to figure it out
|
||||
|
||||
"clear out a bunch of stuff when removing a node" in {
|
||||
val g = Gossip(members = SortedSet(dc1a1, dc1b1, dc2d2))
|
||||
val g = Gossip(
|
||||
members = SortedSet(dc1a1, dc1b1, dc2d2),
|
||||
overview = GossipOverview(reachability =
|
||||
Reachability.empty
|
||||
.unreachable(dc1b1.uniqueAddress, dc2d2.uniqueAddress)
|
||||
.unreachable(dc2d2.uniqueAddress, dc1b1.uniqueAddress)
|
||||
))
|
||||
.:+(VectorClock.Node(Gossip.vclockName(dc1b1.uniqueAddress)))
|
||||
.:+(VectorClock.Node(Gossip.vclockName(dc2d2.uniqueAddress)))
|
||||
.remove(dc1b1.uniqueAddress, System.currentTimeMillis())
|
||||
|
||||
g.seenBy should not contain (dc1b1.uniqueAddress)
|
||||
g.overview.reachability.records.exists(_.observer == dc1b1.uniqueAddress) should be(false)
|
||||
g.overview.reachability.records.exists(_.subject == dc1b1.uniqueAddress) should be(false)
|
||||
g.version.versions should have size (0)
|
||||
g.overview.reachability.records.map(_.observer) should not contain (dc1b1.uniqueAddress)
|
||||
g.overview.reachability.records.map(_.subject) should not contain (dc1b1.uniqueAddress)
|
||||
|
||||
// sort order should be kept
|
||||
g.members.toList should ===(List(dc1a1, dc2d2))
|
||||
g.version.versions.keySet should not contain (VectorClock.Node(Gossip.vclockName(dc1b1.uniqueAddress)))
|
||||
g.version.versions.keySet should contain(VectorClock.Node(Gossip.vclockName(dc2d2.uniqueAddress)))
|
||||
}
|
||||
|
||||
"not reintroduce members from out-of data center gossip when merging" in {
|
||||
|
|
@ -379,6 +388,35 @@ class GossipSpec extends WordSpec with Matchers {
|
|||
merged1.version.versions.keys should not contain (VectorClock.Node(vclockName(dc2d1.uniqueAddress)))
|
||||
}
|
||||
|
||||
"correctly prune vector clocks based on tombstones when merging" in {
|
||||
val gdc1 = Gossip(members = SortedSet(dc1a1, dc1b1, dc2c1, dc2d1))
|
||||
.:+(VectorClock.Node(vclockName(dc1a1.uniqueAddress)))
|
||||
.:+(VectorClock.Node(vclockName(dc1b1.uniqueAddress)))
|
||||
.:+(VectorClock.Node(vclockName(dc2c1.uniqueAddress)))
|
||||
.:+(VectorClock.Node(vclockName(dc2d1.uniqueAddress)))
|
||||
.remove(dc1b1.uniqueAddress, System.currentTimeMillis())
|
||||
|
||||
gdc1.version.versions.keySet should not contain (VectorClock.Node(vclockName(dc1b1.uniqueAddress)))
|
||||
|
||||
val gdc2 = Gossip(members = SortedSet(dc1a1, dc1b1, dc2c1, dc2d1))
|
||||
.seen(dc1a1.uniqueAddress)
|
||||
.:+(VectorClock.Node(vclockName(dc1a1.uniqueAddress)))
|
||||
.:+(VectorClock.Node(vclockName(dc1b1.uniqueAddress)))
|
||||
.:+(VectorClock.Node(vclockName(dc2c1.uniqueAddress)))
|
||||
.:+(VectorClock.Node(vclockName(dc2d1.uniqueAddress)))
|
||||
.remove(dc2c1.uniqueAddress, System.currentTimeMillis())
|
||||
|
||||
gdc2.version.versions.keySet should not contain (VectorClock.Node(vclockName(dc2c1.uniqueAddress)))
|
||||
|
||||
// when we merge the two, the nodes should not be reintroduced
|
||||
val merged1 = gdc2 merge gdc1
|
||||
merged1.members should ===(SortedSet(dc1a1, dc2d1))
|
||||
|
||||
merged1.version.versions.keySet should ===(Set(
|
||||
VectorClock.Node(vclockName(dc1a1.uniqueAddress)),
|
||||
VectorClock.Node(vclockName(dc2d1.uniqueAddress))))
|
||||
}
|
||||
|
||||
"prune old tombstones" in {
|
||||
val timestamp = 352684800
|
||||
val g = Gossip(members = SortedSet(dc1a1, dc1b1))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue