api: Add support for DeleteCAS
This commit is contained in:
parent
f3baa0a113
commit
18ebb1a8e9
33
api/kv.go
33
api/kv.go
|
@ -193,27 +193,44 @@ func (k *KV) put(key string, params map[string]string, body []byte, q *WriteOpti
|
||||||
|
|
||||||
// Delete is used to delete a single key
|
// Delete is used to delete a single key
|
||||||
func (k *KV) Delete(key string, w *WriteOptions) (*WriteMeta, error) {
|
func (k *KV) Delete(key string, w *WriteOptions) (*WriteMeta, error) {
|
||||||
return k.deleteInternal(key, nil, w)
|
_, qm, err := k.deleteInternal(key, nil, w)
|
||||||
|
return qm, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCAS is used for a Delete Check-And-Set operation. The Key
|
||||||
|
// and ModifyIndex are respected. Returns true on success or false on failures.
|
||||||
|
func (k *KV) DeleteCAS(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) {
|
||||||
|
params := map[string]string{
|
||||||
|
"cas": strconv.FormatUint(p.ModifyIndex, 10),
|
||||||
|
}
|
||||||
|
return k.deleteInternal(p.Key, params, q)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteTree is used to delete all keys under a prefix
|
// DeleteTree is used to delete all keys under a prefix
|
||||||
func (k *KV) DeleteTree(prefix string, w *WriteOptions) (*WriteMeta, error) {
|
func (k *KV) DeleteTree(prefix string, w *WriteOptions) (*WriteMeta, error) {
|
||||||
return k.deleteInternal(prefix, []string{"recurse"}, w)
|
_, qm, err := k.deleteInternal(prefix, map[string]string{"recurse": ""}, w)
|
||||||
|
return qm, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KV) deleteInternal(key string, params []string, q *WriteOptions) (*WriteMeta, error) {
|
func (k *KV) deleteInternal(key string, params map[string]string, q *WriteOptions) (bool, *WriteMeta, error) {
|
||||||
r := k.c.newRequest("DELETE", "/v1/kv/"+key)
|
r := k.c.newRequest("DELETE", "/v1/kv/"+key)
|
||||||
r.setWriteOptions(q)
|
r.setWriteOptions(q)
|
||||||
for _, param := range params {
|
for param, val := range params {
|
||||||
r.params.Set(param, "")
|
r.params.Set(param, val)
|
||||||
}
|
}
|
||||||
rtt, resp, err := requireOK(k.c.doRequest(r))
|
rtt, resp, err := requireOK(k.c.doRequest(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
qm := &WriteMeta{}
|
qm := &WriteMeta{}
|
||||||
qm.RequestTime = rtt
|
qm.RequestTime = rtt
|
||||||
return qm, nil
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if _, err := io.Copy(&buf, resp.Body); err != nil {
|
||||||
|
return false, nil, fmt.Errorf("Failed to read response: %v", err)
|
||||||
|
}
|
||||||
|
res := strings.Contains(string(buf.Bytes()), "true")
|
||||||
|
return res, qm, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,51 @@ func TestClient_List_DeleteRecurse(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClient_DeleteCAS(t *testing.T) {
|
||||||
|
c, s := makeClient(t)
|
||||||
|
defer s.stop()
|
||||||
|
|
||||||
|
kv := c.KV()
|
||||||
|
|
||||||
|
// Put the key
|
||||||
|
key := testKey()
|
||||||
|
value := []byte("test")
|
||||||
|
p := &KVPair{Key: key, Value: value}
|
||||||
|
if work, _, err := kv.CAS(p, nil); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
} else if !work {
|
||||||
|
t.Fatalf("CAS failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get should work
|
||||||
|
pair, meta, err := kv.Get(key, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
if pair == nil {
|
||||||
|
t.Fatalf("expected value: %#v", pair)
|
||||||
|
}
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
t.Fatalf("unexpected value: %#v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAS update with bad index
|
||||||
|
p.ModifyIndex = 1
|
||||||
|
if work, _, err := kv.DeleteCAS(p, nil); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
} else if work {
|
||||||
|
t.Fatalf("unexpected CAS")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CAS update with valid index
|
||||||
|
p.ModifyIndex = meta.LastIndex
|
||||||
|
if work, _, err := kv.DeleteCAS(p, nil); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
} else if !work {
|
||||||
|
t.Fatalf("unexpected CAS failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestClient_CAS(t *testing.T) {
|
func TestClient_CAS(t *testing.T) {
|
||||||
c, s := makeClient(t)
|
c, s := makeClient(t)
|
||||||
defer s.stop()
|
defer s.stop()
|
||||||
|
|
Loading…
Reference in New Issue