ORMap and friends have deltas (#22350)
This commit is contained in:
parent
40b883cda7
commit
1f2ef60174
15 changed files with 4371 additions and 140 deletions
|
|
@ -77,6 +77,12 @@ class ORMultiMapSpec extends WordSpec with Matchers {
|
|||
|
||||
val merged2 = m2 merge m1
|
||||
merged2.entries should be(expectedMerged)
|
||||
|
||||
val merged3 = m1 mergeDelta m2.delta.get
|
||||
merged3.entries should be(expectedMerged)
|
||||
|
||||
val merged4 = m2 mergeDelta m1.delta.get
|
||||
merged4.entries should be(expectedMerged)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +113,74 @@ class ORMultiMapSpec extends WordSpec with Matchers {
|
|||
m2.entries should be(Map("b" → Set("B1")))
|
||||
}
|
||||
|
||||
"not have usual anomalies for remove+addBinding scenario and delta-deltas" in {
|
||||
val m1 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
|
||||
val m2 = ORMultiMap.emptyWithValueDeltas[String, String].put(node2, "c", Set("C"))
|
||||
|
||||
val merged1 = m1 merge m2
|
||||
|
||||
val m3 = merged1.resetDelta.remove(node1, "b")
|
||||
val m4 = merged1.resetDelta.addBinding(node1, "b", "B2")
|
||||
|
||||
val merged2 = m3 merge m4
|
||||
|
||||
merged2.entries("a") should be(Set("A"))
|
||||
merged2.entries("b") should be(Set("B2"))
|
||||
merged2.entries("c") should be(Set("C"))
|
||||
|
||||
val merged3 = m3 mergeDelta m4.delta.get
|
||||
|
||||
merged3.entries("a") should be(Set("A"))
|
||||
merged3.entries("b") should be(Set("B2"))
|
||||
merged3.entries("c") should be(Set("C"))
|
||||
}
|
||||
|
||||
"not have usual anomalies for remove+addBinding scenario and delta-deltas 2" in {
|
||||
// the new delta-delta ORMultiMap is free from this anomaly
|
||||
val m1 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
|
||||
val m2 = ORMultiMap.emptyWithValueDeltas[String, String].put(node2, "c", Set("C"))
|
||||
|
||||
// m1 - node1 gets the update from m2
|
||||
val merged1 = m1 merge m2
|
||||
// m2 - node2 gets the update from m1
|
||||
val merged2 = m2 merge m1
|
||||
|
||||
// no race condition
|
||||
val m3 = merged1.resetDelta.remove(node1, "b")
|
||||
// let's imagine that m3 (node1) update gets propagated here (full state or delta - doesn't matter)
|
||||
// and is in flight, but in the meantime, an element is being added somewhere else (m4 - node2)
|
||||
// and the update is propagated before the update from node1 is merged
|
||||
val m4 = merged2.resetDelta.addBinding(node2, "b", "B2")
|
||||
// and later merged on node1
|
||||
val merged3 = m3 merge m4
|
||||
// and the other way round...
|
||||
val merged4 = m4 merge m3
|
||||
|
||||
// result - the element "B" is kept on both sides...
|
||||
merged3.entries("a") should be(Set("A"))
|
||||
merged3.entries("b") should be(Set("B2"))
|
||||
merged3.entries("c") should be(Set("C"))
|
||||
|
||||
merged4.entries("a") should be(Set("A"))
|
||||
merged4.entries("b") should be(Set("B2"))
|
||||
merged4.entries("c") should be(Set("C"))
|
||||
|
||||
// but if the timing was slightly different, so that the update from node1
|
||||
// would get merged just before update on node2:
|
||||
val merged5 = (m2 merge m3).resetDelta.addBinding(node2, "b", "B2")
|
||||
// the update propagated ... and merged on node1:
|
||||
val merged6 = m3 merge merged5
|
||||
|
||||
// then the outcome would be the same...
|
||||
merged5.entries("a") should be(Set("A"))
|
||||
merged5.entries("b") should be(Set("B2"))
|
||||
merged5.entries("c") should be(Set("C"))
|
||||
|
||||
merged6.entries("a") should be(Set("A"))
|
||||
merged6.entries("b") should be(Set("B2"))
|
||||
merged6.entries("c") should be(Set("C"))
|
||||
}
|
||||
|
||||
"have unapply extractor" in {
|
||||
val m1 = ORMultiMap.empty.put(node1, "a", Set(1L, 2L)).put(node2, "b", Set(3L))
|
||||
val m2: ORMultiMap[String, Long] = m1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue