Merge pull request #4483 from heyitsanthony/clientv3-op-opts

clientv3: optionize put and delete
This commit is contained in:
Anthony Romano 2016-02-10 15:37:35 -08:00
commit fcf94f3a59
7 changed files with 62 additions and 61 deletions

View File

@ -55,7 +55,7 @@ func TestKVPut(t *testing.T) {
}
for i, tt := range tests {
if _, err := kv.Put(ctx, tt.key, tt.val, tt.leaseID); err != nil {
if _, err := kv.Put(ctx, tt.key, tt.val, clientv3.WithLease(tt.leaseID)); err != nil {
t.Fatalf("#%d: couldn't put %q (%v)", i, tt.key, err)
}
resp, err := kv.Get(ctx, tt.key)
@ -85,7 +85,7 @@ func TestKVRange(t *testing.T) {
keySet := []string{"a", "b", "c", "c", "c", "foo", "foo/abc", "fop"}
for i, key := range keySet {
if _, err := kv.Put(ctx, key, "", lease.NoLease); err != nil {
if _, err := kv.Put(ctx, key, ""); err != nil {
t.Fatalf("#%d: couldn't put %q (%v)", i, key, err)
}
}
@ -199,7 +199,7 @@ func TestKVDeleteRange(t *testing.T) {
keySet := []string{"a", "b", "c", "c", "c", "d", "e", "f"}
for i, key := range keySet {
if _, err := kv.Put(ctx, key, "", lease.NoLease); err != nil {
if _, err := kv.Put(ctx, key, ""); err != nil {
t.Fatalf("#%d: couldn't put %q (%v)", i, key, err)
}
}
@ -213,7 +213,7 @@ func TestKVDeleteRange(t *testing.T) {
}
for i, tt := range tests {
dresp, err := kv.DeleteRange(ctx, tt.key, tt.end)
dresp, err := kv.Delete(ctx, tt.key, clientv3.WithRange(tt.end))
if err != nil {
t.Fatalf("#%d: couldn't delete range (%v)", i, err)
}
@ -239,7 +239,7 @@ func TestKVDelete(t *testing.T) {
kv := clientv3.NewKV(clus.RandClient())
ctx := context.TODO()
presp, err := kv.Put(ctx, "foo", "", lease.NoLease)
presp, err := kv.Put(ctx, "foo", "")
if err != nil {
t.Fatalf("couldn't put 'foo' (%v)", err)
}
@ -272,7 +272,7 @@ func TestKVCompact(t *testing.T) {
ctx := context.TODO()
for i := 0; i < 10; i++ {
if _, err := kv.Put(ctx, "foo", "bar", lease.NoLease); err != nil {
if _, err := kv.Put(ctx, "foo", "bar"); err != nil {
t.Fatalf("couldn't put 'foo' (%v)", err)
}
}
@ -311,7 +311,7 @@ func TestKVGetRetry(t *testing.T) {
kv := clientv3.NewKV(clus.Client(0))
ctx := context.TODO()
if _, err := kv.Put(ctx, "foo", "bar", 0); err != nil {
if _, err := kv.Put(ctx, "foo", "bar"); err != nil {
t.Fatal(err)
}
@ -363,7 +363,7 @@ func TestKVPutFailGetRetry(t *testing.T) {
clus.Members[0].Stop(t)
<-clus.Members[0].StopNotify()
_, err := kv.Put(ctx, "foo", "bar", 0)
_, err := kv.Put(ctx, "foo", "bar")
if err == nil {
t.Fatalf("got success on disconnected put, wanted error")
}

View File

@ -42,7 +42,7 @@ func TestLeaseCreate(t *testing.T) {
t.Errorf("failed to create lease %v", err)
}
_, err = kv.Put(context.TODO(), "foo", "bar", lease.LeaseID(resp.ID))
_, err = kv.Put(context.TODO(), "foo", "bar", clientv3.WithLease(lease.LeaseID(resp.ID)))
if err != nil {
t.Fatalf("failed to create key with lease %v", err)
}
@ -69,7 +69,7 @@ func TestLeaseRevoke(t *testing.T) {
t.Errorf("failed to revoke lease %v", err)
}
_, err = kv.Put(context.TODO(), "foo", "bar", lease.LeaseID(resp.ID))
_, err = kv.Put(context.TODO(), "foo", "bar", clientv3.WithLease(lease.LeaseID(resp.ID)))
if err != v3rpc.ErrLeaseNotFound {
t.Fatalf("err = %v, want %v", err, v3rpc.ErrLeaseNotFound)
}

View File

@ -38,7 +38,7 @@ func TestTxnWriteFail(t *testing.T) {
donec := make(chan struct{})
go func() {
resp, err := kv.Txn(ctx).Then(clientv3.OpPut("foo", "bar", 0)).Commit()
resp, err := kv.Txn(ctx).Then(clientv3.OpPut("foo", "bar")).Commit()
if err == nil {
t.Fatalf("expected error, got response %v", resp)
}
@ -123,7 +123,7 @@ func TestTxnSuccess(t *testing.T) {
kv := clientv3.NewKV(clus.Client(0))
ctx := context.TODO()
_, err := kv.Txn(ctx).Then(clientv3.OpPut("foo", "bar", 0)).Commit()
_, err := kv.Txn(ctx).Then(clientv3.OpPut("foo", "bar")).Commit()
if err != nil {
t.Fatal(err)
}

View File

@ -146,7 +146,7 @@ func testWatchMultiWatcher(t *testing.T, wctx *watchctx) {
for i := 0; i < numKeyUpdates; i++ {
for _, k := range keys {
v := fmt.Sprintf("%s-%d", k, i)
if _, err := wctx.kv.Put(ctx, k, v, 0); err != nil {
if _, err := wctx.kv.Put(ctx, k, v); err != nil {
t.Fatal(err)
}
}
@ -221,7 +221,7 @@ func testWatchCancelRunning(t *testing.T, wctx *watchctx) {
if wctx.ch = wctx.w.Watch(ctx, "a", 0); wctx.ch == nil {
t.Fatalf("expected non-nil watcher channel")
}
if _, err := wctx.kv.Put(ctx, "a", "a", 0); err != nil {
if _, err := wctx.kv.Put(ctx, "a", "a"); err != nil {
t.Fatal(err)
}
cancel()
@ -246,7 +246,7 @@ func testWatchCancelRunning(t *testing.T, wctx *watchctx) {
}
func putAndWatch(t *testing.T, wctx *watchctx, key, val string) {
if _, err := wctx.kv.Put(context.TODO(), key, val, 0); err != nil {
if _, err := wctx.kv.Put(context.TODO(), key, val); err != nil {
t.Fatal(err)
}
select {

View File

@ -20,15 +20,13 @@ import (
"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
"github.com/coreos/etcd/Godeps/_workspace/src/google.golang.org/grpc"
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
"github.com/coreos/etcd/lease"
)
type (
PutResponse pb.PutResponse
GetResponse pb.RangeResponse
DeleteRangeResponse pb.DeleteRangeResponse
DeleteResponse pb.DeleteRangeResponse
TxnResponse pb.TxnResponse
PutResponse pb.PutResponse
GetResponse pb.RangeResponse
DeleteResponse pb.DeleteRangeResponse
TxnResponse pb.TxnResponse
)
type KV interface {
@ -36,7 +34,7 @@ type KV interface {
// Note that key,value can be plain bytes array and string is
// an immutable representation of that bytes array.
// To get a string of bytes, do string([]byte(0x10, 0x20)).
Put(ctx context.Context, key, val string, leaseID lease.LeaseID) (*PutResponse, error)
Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)
// Get retrieves keys.
// By default, Get will return the value for "key", if any.
@ -47,11 +45,8 @@ type KV interface {
// When passed WithSort(), the keys will be sorted.
Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error)
// DeleteRange deletes the given range [key, end).
DeleteRange(ctx context.Context, key, end string) (*DeleteRangeResponse, error)
// Delete is like DeleteRange. A shortcut for deleting single key like [key, key+1).
Delete(ctx context.Context, key string) (*DeleteResponse, error)
// Delete deletes a key, or optionallly using WithRange(end), [key, end).
Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error)
// Compact compacts etcd KV history before the given rev.
Compact(ctx context.Context, rev int64) error
@ -80,8 +75,8 @@ func NewKV(c *Client) KV {
}
}
func (kv *kv) Put(ctx context.Context, key, val string, leaseID lease.LeaseID) (*PutResponse, error) {
r, err := kv.do(ctx, OpPut(key, val, leaseID))
func (kv *kv) Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) {
r, err := kv.do(ctx, OpPut(key, val, opts...))
if err != nil {
return nil, err
}
@ -96,16 +91,8 @@ func (kv *kv) Get(ctx context.Context, key string, opts ...OpOption) (*GetRespon
return (*GetResponse)(r.GetResponseRange()), nil
}
func (kv *kv) DeleteRange(ctx context.Context, key, end string) (*DeleteRangeResponse, error) {
r, err := kv.do(ctx, OpDeleteRange(key, end))
if err != nil {
return nil, err
}
return (*DeleteRangeResponse)(r.GetResponseDeleteRange()), nil
}
func (kv *kv) Delete(ctx context.Context, key string) (*DeleteResponse, error) {
r, err := kv.do(ctx, OpDelete(key))
func (kv *kv) Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error) {
r, err := kv.do(ctx, OpDelete(key, opts...))
if err != nil {
return nil, err
}

View File

@ -70,39 +70,53 @@ func (op Op) isWrite() bool {
func OpGet(key string, opts ...OpOption) Op {
ret := Op{t: tRange, key: []byte(key)}
for _, opt := range opts {
opt(&ret)
ret.applyOpts(opts)
return ret
}
func OpDelete(key string, opts ...OpOption) Op {
ret := Op{t: tDeleteRange, key: []byte(key)}
ret.applyOpts(opts)
switch {
case ret.leaseID != 0:
panic("unexpected lease in delete")
case ret.limit != 0:
panic("unexpected limit in delete")
case ret.rev != 0:
panic("unexpected revision in delete")
case ret.sort != nil:
panic("unexpected sort in delete")
}
return ret
}
func OpDeleteRange(key, end string) Op {
return Op{
t: tDeleteRange,
key: []byte(key),
end: []byte(end),
func OpPut(key, val string, opts ...OpOption) Op {
ret := Op{t: tPut, key: []byte(key), val: []byte(val)}
ret.applyOpts(opts)
switch {
case ret.end != nil:
panic("unexpected range in put")
case ret.limit != 0:
panic("unexpected limit in put")
case ret.rev != 0:
panic("unexpected revision in put")
case ret.sort != nil:
panic("unexpected sort in put")
}
return ret
}
func OpDelete(key string) Op {
return Op{
t: tDeleteRange,
key: []byte(key),
}
}
func OpPut(key, val string, leaseID lease.LeaseID) Op {
return Op{
t: tPut,
key: []byte(key),
val: []byte(val),
leaseID: leaseID,
func (op *Op) applyOpts(opts []OpOption) {
for _, opt := range opts {
opt(op)
}
}
type OpOption func(*Op)
func WithLease(leaseID lease.LeaseID) OpOption {
return func(op *Op) { op.leaseID = leaseID }
}
func WithLimit(n int64) OpOption { return func(op *Op) { op.limit = n } }
func WithRev(rev int64) OpOption { return func(op *Op) { op.rev = rev } }
func WithSort(tgt SortTarget, order SortOrder) OpOption {

View File

@ -34,7 +34,7 @@ func TestTxnPanics(t *testing.T) {
}
cmp := Compare(CreatedRevision("foo"), "=", 0)
op := OpPut("foo", "bar", 0)
op := OpPut("foo", "bar")
tests := []struct {
f func()