*: keep tombstone if revision == compactAtRev
Before this patch, the tombstone can be deleted if its revision is equal compacted revision. It causes that the watch subscriber won't get this DELETE event. Based on Compact API[1], we should keep tombstone revision if it's not less than the compaction revision. > CompactionRequest compacts the key-value store up to a given revision. > All superseded keys with a revision less than the compaction revision > will be removed. [1]: https://etcd.io/docs/latest/dev-guide/api_reference_v3/ Signed-off-by: Wei Fu <fuweid89@gmail.com>
This commit is contained in:
@ -18,6 +18,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zaptest"
|
||||
)
|
||||
@ -308,12 +309,15 @@ func TestKeyIndexCompactAndKeep(t *testing.T) {
|
||||
key: []byte("foo"),
|
||||
modified: Revision{Main: 16},
|
||||
generations: []generation{
|
||||
{created: Revision{Main: 2}, ver: 3, revs: []Revision{Revision{Main: 6}}},
|
||||
{created: Revision{Main: 8}, ver: 3, revs: []Revision{Revision{Main: 8}, Revision{Main: 10}, Revision{Main: 12}}},
|
||||
{created: Revision{Main: 14}, ver: 3, revs: []Revision{Revision{Main: 14}, Revision{Main: 15, Sub: 1}, Revision{Main: 16}}},
|
||||
{},
|
||||
},
|
||||
},
|
||||
map[Revision]struct{}{},
|
||||
map[Revision]struct{}{
|
||||
Revision{Main: 6}: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
7,
|
||||
@ -394,11 +398,14 @@ func TestKeyIndexCompactAndKeep(t *testing.T) {
|
||||
key: []byte("foo"),
|
||||
modified: Revision{Main: 16},
|
||||
generations: []generation{
|
||||
{created: Revision{Main: 8}, ver: 3, revs: []Revision{Revision{Main: 12}}},
|
||||
{created: Revision{Main: 14}, ver: 3, revs: []Revision{Revision{Main: 14}, Revision{Main: 15, Sub: 1}, Revision{Main: 16}}},
|
||||
{},
|
||||
},
|
||||
},
|
||||
map[Revision]struct{}{},
|
||||
map[Revision]struct{}{
|
||||
Revision{Main: 12}: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
13,
|
||||
@ -442,6 +449,20 @@ func TestKeyIndexCompactAndKeep(t *testing.T) {
|
||||
},
|
||||
{
|
||||
16,
|
||||
&keyIndex{
|
||||
key: []byte("foo"),
|
||||
modified: Revision{Main: 16},
|
||||
generations: []generation{
|
||||
{created: Revision{Main: 14}, ver: 3, revs: []Revision{Revision{Main: 16}}},
|
||||
{},
|
||||
},
|
||||
},
|
||||
map[Revision]struct{}{
|
||||
Revision{Main: 16}: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
17,
|
||||
&keyIndex{
|
||||
key: []byte("foo"),
|
||||
modified: Revision{Main: 16},
|
||||
@ -453,18 +474,36 @@ func TestKeyIndexCompactAndKeep(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
isTombstoneRevFn := func(ki *keyIndex, rev int64) bool {
|
||||
for i := 0; i < len(ki.generations)-1; i++ {
|
||||
g := ki.generations[i]
|
||||
|
||||
if l := len(g.revs); l > 0 && g.revs[l-1].Main == rev {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Continuous Compaction and finding Keep
|
||||
ki := newTestKeyIndex(zaptest.NewLogger(t))
|
||||
for i, tt := range tests {
|
||||
isTombstone := isTombstoneRevFn(ki, tt.compact)
|
||||
|
||||
am := make(map[Revision]struct{})
|
||||
kiclone := cloneKeyIndex(ki)
|
||||
ki.keep(tt.compact, am)
|
||||
if !reflect.DeepEqual(ki, kiclone) {
|
||||
t.Errorf("#%d: ki = %+v, want %+v", i, ki, kiclone)
|
||||
}
|
||||
if !reflect.DeepEqual(am, tt.wam) {
|
||||
t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam)
|
||||
|
||||
if isTombstone {
|
||||
assert.Equal(t, 0, len(am), "#%d: ki = %d, keep result wants empty because tombstone", i, ki)
|
||||
} else {
|
||||
assert.Equal(t, tt.wam, am,
|
||||
"#%d: ki = %d, compact keep should be equal to keep keep if it's not tombstone", i, ki)
|
||||
}
|
||||
|
||||
am = make(map[Revision]struct{})
|
||||
ki.compact(zaptest.NewLogger(t), tt.compact, am)
|
||||
if !reflect.DeepEqual(ki, tt.wki) {
|
||||
@ -478,7 +517,7 @@ func TestKeyIndexCompactAndKeep(t *testing.T) {
|
||||
// Jump Compaction and finding Keep
|
||||
ki = newTestKeyIndex(zaptest.NewLogger(t))
|
||||
for i, tt := range tests {
|
||||
if (i%2 == 0 && i < 6) || (i%2 == 1 && i > 6) {
|
||||
if !isTombstoneRevFn(ki, tt.compact) {
|
||||
am := make(map[Revision]struct{})
|
||||
kiclone := cloneKeyIndex(ki)
|
||||
ki.keep(tt.compact, am)
|
||||
@ -508,9 +547,14 @@ func TestKeyIndexCompactAndKeep(t *testing.T) {
|
||||
if !reflect.DeepEqual(ki, kiClone) {
|
||||
t.Errorf("#%d: ki = %+v, want %+v", i, ki, kiClone)
|
||||
}
|
||||
if !reflect.DeepEqual(am, tt.wam) {
|
||||
t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam)
|
||||
|
||||
if isTombstoneRevFn(ki, tt.compact) {
|
||||
assert.Equal(t, 0, len(am), "#%d: ki = %d, keep result wants empty because tombstone", i, ki)
|
||||
} else {
|
||||
assert.Equal(t, tt.wam, am,
|
||||
"#%d: ki = %d, compact keep should be equal to keep keep if it's not tombstone", i, ki)
|
||||
}
|
||||
|
||||
am = make(map[Revision]struct{})
|
||||
ki.compact(zaptest.NewLogger(t), tt.compact, am)
|
||||
if !reflect.DeepEqual(ki, tt.wki) {
|
||||
|
Reference in New Issue
Block a user