clientv3: add 'WithIgnoreValue' option

release-3.2
Gyu-Ho Lee 2016-12-05 12:35:31 -08:00
parent a66f133209
commit d94d22122b
3 changed files with 47 additions and 2 deletions

View File

@ -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) {
defer testutil.AfterTest(t)

View File

@ -148,7 +148,7 @@ func (kv *kv) do(ctx context.Context, op Op) (OpResponse, error) {
}
case tPut:
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)
if err == nil {
return OpResponse{put: (*PutResponse)(resp)}, nil

View File

@ -52,6 +52,9 @@ type Op struct {
// for watch, put, delete
prevKV bool
// for put
ignoreValue bool
// progressNotify is for progress updates.
progressNotify bool
// createdNotify is for created event
@ -94,7 +97,7 @@ func (op Op) toRequestOp() *pb.RequestOp {
case tRange:
return &pb.RequestOp{Request: &pb.RequestOp_RequestRange{RequestRange: op.toRangeRequest()}}
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}}
case tDeleteRange:
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.
type LeaseOp struct {
id LeaseID