diff --git a/client/v3/ordering/util.go b/client/v3/ordering/util.go index 701cc7096165..cd8333cba722 100644 --- a/client/v3/ordering/util.go +++ b/client/v3/ordering/util.go @@ -29,7 +29,7 @@ func NewOrderViolationSwitchEndpointClosure(c *clientv3.Client) OrderViolationFu violationCount := int32(0) return func(_ clientv3.Op, _ clientv3.OpResponse, _ int64) error { // Each request is assigned by round-robin load-balancer's picker to a different - // endpoints. If we cycled them 5 times (even with some level of concurrency), + // endpoint. If we cycled them 5 times (even with some level of concurrency), // with high probability no endpoint points on a member with fresh data. // TODO: Ideally we should track members (resp.opp.Header) that returned // stale result and explicitly temporarily disable them in 'picker'. diff --git a/tests/integration/clientv3/ordering_util_test.go b/tests/integration/clientv3/ordering_util_test.go index 56e347620894..9e5ae1eaf406 100644 --- a/tests/integration/clientv3/ordering_util_test.go +++ b/tests/integration/clientv3/ordering_util_test.go @@ -24,6 +24,9 @@ import ( integration2 "go.etcd.io/etcd/tests/v3/framework/integration" ) +// TestEndpointSwitchResolvesViolation ensures +// - ErrNoGreaterRev error is returned from partitioned member when it has stale revision +// - no more error after partition recovers func TestEndpointSwitchResolvesViolation(t *testing.T) { integration2.BeforeTest(t) clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3}) @@ -78,8 +81,16 @@ func TestEndpointSwitchResolvesViolation(t *testing.T) { if err != ordering.ErrNoGreaterRev { t.Fatal("While speaking to partitioned leader, we should get ErrNoGreaterRev error") } + + clus.Members[2].RecoverPartition(t, clus.Members[:2]...) + time.Sleep(1 * time.Second) // give enough time for the operation + _, err = orderingKv.Get(ctx, "foo", clientv3.WithSerializable()) + if err != nil { + t.Fatal("After partition recovered, third member should recover and return no error") + } } +// TestUnresolvableOrderViolation ensures ErrNoGreaterRev error is returned when available members only have stale revisions func TestUnresolvableOrderViolation(t *testing.T) { integration2.BeforeTest(t) clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 5, UseBridge: true})