Skip to content

Commit 16dc8de

Browse files
committed
Add e2e test to reproduce issue #19406
Signed-off-by: Miancheng Lin <[email protected]>
1 parent 5122d43 commit 16dc8de

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

server/storage/mvcc/kvstore_compaction.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func (s *store) scheduleCompaction(compactMainRev, prevCompactRev int64) (KeyVal
4949

5050
tx := s.b.BatchTx()
5151
tx.LockOutsideApply()
52+
// gofail: var compactAfterAcquiredBatchTxLock struct{}
5253
keys, values := tx.UnsafeRange(schema.Key, last, end, int64(batchNum))
5354
for i := range keys {
5455
rev = BytesToRev(keys[i])

tests/e2e/reproduce_19406_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package e2e
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/stretchr/testify/require"
7+
clientv3 "go.etcd.io/etcd/client/v3"
8+
"go.etcd.io/etcd/pkg/v3/stringutil"
9+
"sync"
10+
"testing"
11+
"time"
12+
13+
"go.etcd.io/etcd/tests/v3/framework/e2e"
14+
)
15+
16+
// TestReproduce19406 reproduces the issue: https://github.com/etcd-io/etcd/issues/19406
17+
func TestReproduce19406(t *testing.T) {
18+
e2e.BeforeTest(t)
19+
20+
compactionBatchLimit := 1
21+
22+
ctx := context.TODO()
23+
CompactionSleepInterval := 100 * time.Millisecond
24+
25+
clus, cerr := e2e.NewEtcdProcessCluster(ctx, t,
26+
e2e.WithClusterSize(1),
27+
e2e.WithGoFailEnabled(true),
28+
e2e.WithCompactionBatchLimit(compactionBatchLimit),
29+
e2e.WithCompactionSleepInterval(CompactionSleepInterval),
30+
)
31+
32+
require.NoError(t, cerr)
33+
t.Cleanup(func() { require.NoError(t, clus.Stop()) })
34+
35+
// produce some data
36+
cli := newClient(t, clus.EndpointsGRPC(), e2e.ClientConfig{})
37+
valueSize := 10
38+
var latestRevision int64
39+
for i := 0; i <= 100; i++ {
40+
resp, err := cli.Put(ctx, fmt.Sprintf("%d", i), stringutil.RandString(uint(valueSize)))
41+
require.NoError(t, err)
42+
latestRevision = resp.Header.Revision
43+
}
44+
45+
// sleep for CompactionSleepInterval
46+
require.NoError(t, clus.Procs[0].Failpoints().SetupHTTP(ctx, "compactAfterAcquiredBatchTxLock",
47+
fmt.Sprintf(`sleep("%s")`, CompactionSleepInterval)))
48+
49+
// start compaction
50+
compactionFinished := make(chan struct{}) // Channel to signal completion of compaction
51+
var wg sync.WaitGroup
52+
wg.Add(1)
53+
go func() {
54+
defer wg.Done() // Decrement counter when done
55+
defer close(compactionFinished)
56+
t.Log("start compaction...")
57+
_, err := cli.Compact(context.Background(), latestRevision, clientv3.WithCompactPhysical())
58+
require.NoError(t, err)
59+
t.Log("finished compaction...")
60+
}()
61+
62+
// Compaction runs in batches. During each batch, it acquires a lock, releases it at the end,
63+
// and then waits for a CompactionSleepInterval before starting the next batch. This pause
64+
// allows PUT requests to be processed.
65+
//
66+
// Therefore, the expected PUT request latency should fall between
67+
// [each batch execution time, each batch execution time + CompactionSleepInterval],
68+
// which in this case is [CompactionSleepInterval, CompactionSleepInterval × 2].
69+
numGoroutines := 10
70+
for i := 1; i <= numGoroutines; i++ {
71+
wg.Add(1) // Increment WaitGroup counter
72+
73+
go func(gid int) {
74+
defer wg.Done() // Decrement counter when done
75+
verifyPutLatencyDuringCompaction(ctx, t, cli, compactionFinished, CompactionSleepInterval*2)
76+
}(i)
77+
}
78+
wg.Wait()
79+
}
80+
81+
func verifyPutLatencyDuringCompaction(ctx context.Context, t *testing.T, cli *clientv3.Client, compactionFinished <-chan struct{}, putLatencyLimit time.Duration) {
82+
for {
83+
select {
84+
case <-compactionFinished: // compaction finished
85+
return
86+
default:
87+
start := time.Now()
88+
_, err := cli.Put(ctx, fmt.Sprintf("foo"), "far")
89+
require.NoError(t, err)
90+
91+
if time.Since(start) > putLatencyLimit {
92+
t.Fatalf("Test failed: put latency is larger than %s", putLatencyLimit)
93+
}
94+
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)