clientv3: remove v3.WithFirstKey() in Barrier.Wait()

fix the unexpected blocking when using Barrier.Wait(), e.g.
NewBarrier(client, "a").Wait() will block if key "a" is not existed but "a0" is existed, but it should return immediately.

Signed-off-by: zhangwenkang <zwenkang@vmware.com>
This commit is contained in:
zhangwenkang 2023-07-04 22:01:54 +08:00
parent 833aabe4cd
commit 3d3e91c6e3
2 changed files with 40 additions and 1 deletions

View File

@ -49,7 +49,7 @@ func (b *Barrier) Release() error {
// Wait blocks on the barrier key until it is deleted. If there is no key, Wait
// assumes Release has already been called and returns immediately.
func (b *Barrier) Wait() error {
resp, err := b.client.Get(b.ctx, b.key, v3.WithFirstKey()...)
resp, err := b.client.Get(b.ctx, b.key)
if err != nil {
return err
}

View File

@ -83,3 +83,42 @@ func testBarrier(t *testing.T, waiters int, chooseClient func() *clientv3.Client
}
}
}
func TestBarrierWaitNonexistentKey(t *testing.T) {
integration2.BeforeTest(t)
clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1})
defer clus.Terminate(t)
cli := clus.Client(0)
if _, err := cli.Put(cli.Ctx(), "test-barrier-0", ""); err != nil {
t.Errorf("could not put test-barrier0, err:%v", err)
}
donec := make(chan struct{})
stopc := make(chan struct{})
defer close(stopc)
waiters := 5
for i := 0; i < waiters; i++ {
go func() {
br := recipe.NewBarrier(cli, "test-barrier")
if err := br.Wait(); err != nil {
t.Errorf("could not wait on barrier (%v)", err)
}
select {
case donec <- struct{}{}:
case <-stopc:
}
}()
}
// all waiters should return immediately if waiting on a nonexistent key "test-barrier" even if key "test-barrier-0" exists
timerC := time.After(time.Duration(waiters*100) * time.Millisecond)
for i := 0; i < waiters; i++ {
select {
case <-timerC:
t.Fatal("barrier timed out")
case <-donec:
}
}
}