Skip to content

Commit

Permalink
clientv3: remove v3.WithFirstKey() in Barrier.Wait()
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
kensou97 committed Jul 6, 2023
1 parent f3f3729 commit 6be3ad3
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
2 changes: 1 addition & 1 deletion client/v3/experimental/recipes/barrier.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
39 changes: 39 additions & 0 deletions tests/integration/clientv3/experimental/recipes/v3_barrier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,42 @@ func testBarrier(t *testing.T, waiters int, chooseClient func() *clientv3.Client
}
}
}

func TestBarrierWaitNonexistentKey(t *testing.T) {
integration.BeforeTest(t)
clus := integration.NewClusterV3(t, &integration.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:
}
}
}

0 comments on commit 6be3ad3

Please sign in to comment.