diff --git a/Documentation/api.md b/Documentation/api.md index 1ecaf0a9f..95a8e2c6b 100644 --- a/Documentation/api.md +++ b/Documentation/api.md @@ -202,6 +202,32 @@ If the TTL has expired, the key will have been deleted, and you will be returned } ``` +The TTL could be unset to avoid expiration through update operation: + +```sh +curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -d ttl= -d prevExist=true +``` + +```json +{ + "action": "update", + "node": { + "createdIndex": 5, + "key": "/foo", + "modifiedIndex": 6, + "value": "bar" + } + "prevNode": { + "createdIndex": 5, + "expiration": "2013-12-04T12:01:21.874888581-08:00", + "key": "/foo", + "modifiedIndex": 5, + "ttl": 3, + "value": "bar" + } +} +``` + ### Waiting for a change diff --git a/server/v2/tests/put_handler_test.go b/server/v2/tests/put_handler_test.go index ec7267847..d6416b2a2 100644 --- a/server/v2/tests/put_handler_test.go +++ b/server/v2/tests/put_handler_test.go @@ -194,6 +194,42 @@ func TestV2UpdateKeyFailOnMissingDirectory(t *testing.T) { }) } +// Ensures that a key could update TTL. +// +// $ curl -X PUT localhost:4001/v2/keys/foo -d value=XXX +// $ curl -X PUT localhost:4001/v2/keys/foo -d value=XXX -d ttl=1000 -d prevExist=true +// $ curl -X PUT localhost:4001/v2/keys/foo -d value=XXX -d ttl= -d prevExist=true +// +func TestV2UpdateKeySuccessWithTTL(t *testing.T) { + tests.RunServer(func(s *server.Server) { + v := url.Values{} + v.Set("value", "XXX") + resp, _ := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo"), v) + assert.Equal(t, resp.StatusCode, http.StatusCreated) + node := (tests.ReadBodyJSON(resp)["node"]).(map[string]interface{}) + createdIndex := node["createdIndex"] + + v.Set("ttl", "1000") + v.Set("prevExist", "true") + resp, _ = tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo"), v) + assert.Equal(t, resp.StatusCode, http.StatusOK) + node = (tests.ReadBodyJSON(resp)["node"]).(map[string]interface{}) + assert.Equal(t, node["value"], "XXX", "") + assert.Equal(t, node["ttl"], 1000, "") + assert.NotEqual(t, node["expiration"], "", "") + assert.Equal(t, node["createdIndex"], createdIndex, "") + + v.Del("ttl") + resp, _ = tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo"), v) + assert.Equal(t, resp.StatusCode, http.StatusOK) + node = (tests.ReadBodyJSON(resp)["node"]).(map[string]interface{}) + assert.Equal(t, node["value"], "XXX", "") + assert.Equal(t, node["ttl"], nil, "") + assert.Equal(t, node["expiration"], nil, "") + assert.Equal(t, node["createdIndex"], createdIndex, "") + }) +} + // Ensures that a key is set only if the previous index matches. // // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX diff --git a/store/node.go b/store/node.go index 95d5d067d..f11619a60 100644 --- a/store/node.go +++ b/store/node.go @@ -310,6 +310,7 @@ func (n *node) UpdateTTL(expireTime time.Time) { if !n.IsPermanent() { if expireTime.IsZero() { // from ttl to permanent + n.ExpireTime = expireTime // remove from ttl heap n.store.ttlKeyHeap.remove(n) } else {