go.etcd.io/etcd@v3.3.27+incompatible/clientv3/kv.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package clientv3 16 17 import ( 18 "context" 19 20 pb "github.com/coreos/etcd/etcdserver/etcdserverpb" 21 22 "google.golang.org/grpc" 23 ) 24 25 type ( 26 CompactResponse pb.CompactionResponse 27 PutResponse pb.PutResponse 28 GetResponse pb.RangeResponse 29 DeleteResponse pb.DeleteRangeResponse 30 TxnResponse pb.TxnResponse 31 ) 32 33 type KV interface { 34 // Put puts a key-value pair into etcd. 35 // Note that key,value can be plain bytes array and string is 36 // an immutable representation of that bytes array. 37 // To get a string of bytes, do string([]byte{0x10, 0x20}). 38 Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) 39 40 // Get retrieves keys. 41 // By default, Get will return the value for "key", if any. 42 // When passed WithRange(end), Get will return the keys in the range [key, end). 43 // When passed WithFromKey(), Get returns keys greater than or equal to key. 44 // When passed WithRev(rev) with rev > 0, Get retrieves keys at the given revision; 45 // if the required revision is compacted, the request will fail with ErrCompacted . 46 // When passed WithLimit(limit), the number of returned keys is bounded by limit. 47 // When passed WithSort(), the keys will be sorted. 48 Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error) 49 50 // Delete deletes a key, or optionally using WithRange(end), [key, end). 51 Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error) 52 53 // Compact compacts etcd KV history before the given rev. 54 Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) 55 56 // Do applies a single Op on KV without a transaction. 57 // Do is useful when creating arbitrary operations to be issued at a 58 // later time; the user can range over the operations, calling Do to 59 // execute them. Get/Put/Delete, on the other hand, are best suited 60 // for when the operation should be issued at the time of declaration. 61 Do(ctx context.Context, op Op) (OpResponse, error) 62 63 // Txn creates a transaction. 64 Txn(ctx context.Context) Txn 65 } 66 67 type OpResponse struct { 68 put *PutResponse 69 get *GetResponse 70 del *DeleteResponse 71 txn *TxnResponse 72 } 73 74 func (op OpResponse) Put() *PutResponse { return op.put } 75 func (op OpResponse) Get() *GetResponse { return op.get } 76 func (op OpResponse) Del() *DeleteResponse { return op.del } 77 func (op OpResponse) Txn() *TxnResponse { return op.txn } 78 79 func (resp *PutResponse) OpResponse() OpResponse { 80 return OpResponse{put: resp} 81 } 82 func (resp *GetResponse) OpResponse() OpResponse { 83 return OpResponse{get: resp} 84 } 85 func (resp *DeleteResponse) OpResponse() OpResponse { 86 return OpResponse{del: resp} 87 } 88 func (resp *TxnResponse) OpResponse() OpResponse { 89 return OpResponse{txn: resp} 90 } 91 92 type kv struct { 93 remote pb.KVClient 94 callOpts []grpc.CallOption 95 } 96 97 func NewKV(c *Client) KV { 98 api := &kv{remote: RetryKVClient(c)} 99 if c != nil { 100 api.callOpts = c.callOpts 101 } 102 return api 103 } 104 105 func NewKVFromKVClient(remote pb.KVClient, c *Client) KV { 106 api := &kv{remote: remote} 107 if c != nil { 108 api.callOpts = c.callOpts 109 } 110 return api 111 } 112 113 func (kv *kv) Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) { 114 r, err := kv.Do(ctx, OpPut(key, val, opts...)) 115 return r.put, toErr(ctx, err) 116 } 117 118 func (kv *kv) Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error) { 119 r, err := kv.Do(ctx, OpGet(key, opts...)) 120 return r.get, toErr(ctx, err) 121 } 122 123 func (kv *kv) Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error) { 124 r, err := kv.Do(ctx, OpDelete(key, opts...)) 125 return r.del, toErr(ctx, err) 126 } 127 128 func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) { 129 resp, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest(), kv.callOpts...) 130 if err != nil { 131 return nil, toErr(ctx, err) 132 } 133 return (*CompactResponse)(resp), err 134 } 135 136 func (kv *kv) Txn(ctx context.Context) Txn { 137 return &txn{ 138 kv: kv, 139 ctx: ctx, 140 callOpts: kv.callOpts, 141 } 142 } 143 144 func (kv *kv) Do(ctx context.Context, op Op) (OpResponse, error) { 145 var err error 146 switch op.t { 147 case tRange: 148 var resp *pb.RangeResponse 149 resp, err = kv.remote.Range(ctx, op.toRangeRequest(), kv.callOpts...) 150 if err == nil { 151 return OpResponse{get: (*GetResponse)(resp)}, nil 152 } 153 case tPut: 154 var resp *pb.PutResponse 155 r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue, IgnoreLease: op.ignoreLease} 156 resp, err = kv.remote.Put(ctx, r, kv.callOpts...) 157 if err == nil { 158 return OpResponse{put: (*PutResponse)(resp)}, nil 159 } 160 case tDeleteRange: 161 var resp *pb.DeleteRangeResponse 162 r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV} 163 resp, err = kv.remote.DeleteRange(ctx, r, kv.callOpts...) 164 if err == nil { 165 return OpResponse{del: (*DeleteResponse)(resp)}, nil 166 } 167 case tTxn: 168 var resp *pb.TxnResponse 169 resp, err = kv.remote.Txn(ctx, op.toTxnRequest(), kv.callOpts...) 170 if err == nil { 171 return OpResponse{txn: (*TxnResponse)(resp)}, nil 172 } 173 default: 174 panic("Unknown op") 175 } 176 return OpResponse{}, toErr(ctx, err) 177 }