clientv3: add 'WithIgnoreValue' option
parent
a66f133209
commit
d94d22122b
|
@ -113,6 +113,39 @@ func TestKVPut(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestKVPutWithIgnoreValue ensures that Put with WithIgnoreValue does not clobber the old value.
|
||||||
|
func TestKVPutWithIgnoreValue(t *testing.T) {
|
||||||
|
defer testutil.AfterTest(t)
|
||||||
|
|
||||||
|
clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1})
|
||||||
|
defer clus.Terminate(t)
|
||||||
|
|
||||||
|
kv := clientv3.NewKV(clus.RandClient())
|
||||||
|
|
||||||
|
_, err := kv.Put(context.TODO(), "foo", "", clientv3.WithIgnoreValue())
|
||||||
|
if err != rpctypes.ErrKeyNotFound {
|
||||||
|
t.Fatalf("err expected %v, got %v", rpctypes.ErrKeyNotFound, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := kv.Put(context.TODO(), "foo", "bar"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := kv.Put(context.TODO(), "foo", "", clientv3.WithIgnoreValue()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
rr, rerr := kv.Get(context.TODO(), "foo")
|
||||||
|
if rerr != nil {
|
||||||
|
t.Fatal(rerr)
|
||||||
|
}
|
||||||
|
if len(rr.Kvs) != 1 {
|
||||||
|
t.Fatalf("len(rr.Kvs) expected 1, got %d", len(rr.Kvs))
|
||||||
|
}
|
||||||
|
if !bytes.Equal(rr.Kvs[0].Value, []byte("bar")) {
|
||||||
|
t.Fatalf("value expected 'bar', got %q", rr.Kvs[0].Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestKVPutWithRequireLeader(t *testing.T) {
|
func TestKVPutWithRequireLeader(t *testing.T) {
|
||||||
defer testutil.AfterTest(t)
|
defer testutil.AfterTest(t)
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ func (kv *kv) do(ctx context.Context, op Op) (OpResponse, error) {
|
||||||
}
|
}
|
||||||
case tPut:
|
case tPut:
|
||||||
var resp *pb.PutResponse
|
var resp *pb.PutResponse
|
||||||
r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV}
|
r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue}
|
||||||
resp, err = kv.remote.Put(ctx, r)
|
resp, err = kv.remote.Put(ctx, r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return OpResponse{put: (*PutResponse)(resp)}, nil
|
return OpResponse{put: (*PutResponse)(resp)}, nil
|
||||||
|
|
|
@ -52,6 +52,9 @@ type Op struct {
|
||||||
// for watch, put, delete
|
// for watch, put, delete
|
||||||
prevKV bool
|
prevKV bool
|
||||||
|
|
||||||
|
// for put
|
||||||
|
ignoreValue bool
|
||||||
|
|
||||||
// progressNotify is for progress updates.
|
// progressNotify is for progress updates.
|
||||||
progressNotify bool
|
progressNotify bool
|
||||||
// createdNotify is for created event
|
// createdNotify is for created event
|
||||||
|
@ -94,7 +97,7 @@ func (op Op) toRequestOp() *pb.RequestOp {
|
||||||
case tRange:
|
case tRange:
|
||||||
return &pb.RequestOp{Request: &pb.RequestOp_RequestRange{RequestRange: op.toRangeRequest()}}
|
return &pb.RequestOp{Request: &pb.RequestOp_RequestRange{RequestRange: op.toRangeRequest()}}
|
||||||
case tPut:
|
case tPut:
|
||||||
r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV}
|
r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue}
|
||||||
return &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: r}}
|
return &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: r}}
|
||||||
case tDeleteRange:
|
case tDeleteRange:
|
||||||
r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
|
r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
|
||||||
|
@ -360,6 +363,15 @@ func WithPrevKV() OpOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithIgnoreValue updates the key using its current value.
|
||||||
|
// Empty value should be passed when ignore_value is set.
|
||||||
|
// Returns an error if the key does not exist.
|
||||||
|
func WithIgnoreValue() OpOption {
|
||||||
|
return func(op *Op) {
|
||||||
|
op.ignoreValue = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LeaseOp represents an Operation that lease can execute.
|
// LeaseOp represents an Operation that lease can execute.
|
||||||
type LeaseOp struct {
|
type LeaseOp struct {
|
||||||
id LeaseID
|
id LeaseID
|
||||||
|
|
Loading…
Reference in New Issue