Skip to content

Commit 05eb12b

Browse files
authored
feature: implemented lease-related api (#66)
* implement lease related func and test files * add lease documentation * fix naming typo of txn test file * remove extra layer and fix formatting * multiversion adaptation * improved test file * same with #12 * add demo in doc
1 parent 427a799 commit 05eb12b

File tree

6 files changed

+451
-6
lines changed

6 files changed

+451
-6
lines changed

api_v3.md

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ API V3
1515
* [rmdir](#rmdir)
1616
* [txn](#txn)
1717
* [version](#version)
18+
* [grant](#grant)
19+
* [revoke](#revoke)
20+
* [keepalive](#keepalive)
21+
* [timetolive](#timetolive)
22+
* [leases](#leases)
1823

1924
Method
2025
======
@@ -58,7 +63,7 @@ Please refer the **etcd API documentaion** at - https://github.com/coreos/etcd f
5863
Gets the value for key.
5964

6065
```lua
61-
local res, err = cli:get('/path_/to/_key')
66+
local res, err = cli:get('/path/to/key')
6267
```
6368

6469
[Back to TOP](#api-v3)
@@ -261,3 +266,71 @@ local res, err = cli:txn(compare, success, nil)
261266
Gets the etcd version info.
262267

263268
[Back to TOP](#api-v3)
269+
270+
### grant
271+
272+
`syntax: res, err = cli:grant(TTL:int [, ID:int])`
273+
274+
- `TTL`: advisory time-to-live in seconds.
275+
- `ID`: the requested ID for the lease. If ID is set to 0, the lessor chooses an ID.
276+
277+
Creates a lease which expires if the server does not receive a keepalive within a given time to live period. All keys attached to the lease will be expired and deleted if the lease expires. Each expired key generates a delete event in the event history.
278+
279+
```lua
280+
-- grant a lease with 5 second TTL
281+
local res, err = cli:grant(5)
282+
283+
-- attach key to lease, whose ID would be contained in res
284+
local data, err = etcd:set('/path/to/key', 'val', {lease = res.body.ID})
285+
```
286+
287+
[Back to TOP](#api-v3)
288+
289+
### revoke
290+
291+
`syntax: res, err = cli:revoke(ID:int)`
292+
293+
- `ID`: the lease ID to revoke. When the ID is revoked, all associated keys will be deleted.
294+
295+
Revokes a lease. All keys attached to the lease will expire and be deleted.
296+
297+
```lua
298+
local res, err = cli:grant(5)
299+
local data, err = etcd:set('/path/to/key', 'val', {lease = res.body.ID})
300+
301+
local data, err = etcd:revoke(res.body.ID)
302+
local data, err = cli:get('/path/to/key')
303+
-- responce would contains no kvs
304+
```
305+
306+
[Back to TOP](#api-v3)
307+
308+
### keepalive
309+
310+
`syntax: res, err = cli:keepalive(ID:int)`
311+
312+
- `ID`: the lease ID for the lease to keep alive.
313+
314+
Keeps the lease alive by streaming keep alive requests from the client to the server and streaming keep alive responses from the server to the client.
315+
316+
[Back to TOP](#api-v3)
317+
318+
### timetolive
319+
320+
`syntax: res, err = cli:timetolive(ID:int [, keys: bool])`
321+
322+
- `ID`: the lease ID for the lease.
323+
- `keys`: if true, query all the keys attached to this lease.
324+
325+
Retrieves lease information.
326+
327+
[Back to TOP](#api-v3)
328+
329+
### leases
330+
331+
`syntax: res, err = cli:leases()`
332+
333+
Lists all existing leases.
334+
335+
[Back to TOP](#api-v3)
336+

lib/resty/etcd/v3.lua

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@ local function get(self, key, attr)
383383
choose_endpoint(self).full_prefix .. "/kv/range",
384384
opts, attr and attr.timeout or self.timeout)
385385

386-
if res and res.status==200 then
387-
if res.body.kvs and tab_nkeys(res.body.kvs)>0 then
386+
if res and res.status == 200 then
387+
if res.body.kvs and tab_nkeys(res.body.kvs) > 0 then
388388
for _, kv in ipairs(res.body.kvs) do
389389
kv.key = decode_base64(kv.key)
390390
kv.value = decode_base64(kv.value)
@@ -429,7 +429,7 @@ local function txn(self, opts_arg, compare, success, failure)
429429
return nil, "compare couldn't be empty"
430430
end
431431

432-
if (success==nil or #success < 1) and (failure==nil or #failure<1) then
432+
if (success == nil or #success < 1) and (failure == nil or #failure < 1) then
433433
return nil, "success and failure couldn't be empty at the same time"
434434
end
435435

@@ -634,7 +634,6 @@ local function watch(self, key, attr)
634634
return callback_fun
635635
end
636636

637-
638637
do
639638
local attr = {}
640639
function _M.get(self, key, opts)
@@ -825,6 +824,89 @@ function _M.txn(self, compare, success, failure, opts)
825824
return txn(self, opts, compare, success, failure)
826825
end
827826

827+
function _M.grant(self, ttl, id)
828+
if ttl == nil then
829+
return nil, "lease grant command needs TTL argument"
830+
end
831+
832+
if not typeof.int(ttl) then
833+
return nil, 'ttl must be integer'
834+
end
835+
836+
id = id or 0
837+
local opts = {
838+
body = {
839+
TTL = ttl,
840+
ID = id
841+
},
842+
}
843+
844+
return _request_uri(self, "POST",
845+
choose_endpoint(self).full_prefix .. "/lease/grant", opts)
846+
end
847+
848+
function _M.revoke(self, id)
849+
if id == nil then
850+
return nil, "lease revoke command needs ID argument"
851+
end
852+
853+
local opts = {
854+
body = {
855+
ID = id
856+
},
857+
}
858+
859+
return _request_uri(self, "POST",
860+
choose_endpoint(self).full_prefix .. "/kv/lease/revoke", opts)
861+
end
862+
863+
function _M.keepalive(self, id)
864+
if id == nil then
865+
return nil, "lease keepalive command needs ID argument"
866+
end
867+
868+
local opts = {
869+
body = {
870+
ID = id
871+
},
872+
}
873+
874+
return _request_uri(self, "POST",
875+
choose_endpoint(self).full_prefix .. "/lease/keepalive", opts)
876+
end
877+
878+
function _M.timetolive(self, id, keys)
879+
if id == nil then
880+
return nil, "lease timetolive command needs ID argument"
881+
end
882+
883+
keys = keys or false
884+
local opts = {
885+
body = {
886+
ID = id,
887+
keys = keys
888+
},
889+
}
890+
891+
local res, err = _request_uri(self, "POST",
892+
choose_endpoint(self).full_prefix .. "/kv/lease/timetolive", opts)
893+
894+
if res and res.status == 200 then
895+
if res.body.keys and tab_nkeys(res.body.keys) > 0 then
896+
for i, key in ipairs(res.body.keys) do
897+
res.body.keys[i] = decode_base64(key)
898+
end
899+
end
900+
end
901+
902+
return res, err
903+
end
904+
905+
function _M.leases(self)
906+
return _request_uri(self, "POST",
907+
choose_endpoint(self).full_prefix .. "/lease/leases")
908+
end
909+
828910

829911
-- /version
830912
function _M.version(self)

t/v2/dir.t

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ checked val as expect: b
218218
end)
219219

220220
cur_time = ngx.now()
221-
res, err = etcd:waitdir("/dir", res.body.node.modifiedIndex + 1, 5)
221+
res, err = etcd:waitdir("/dir", res.body.node.modifiedIndex + 1, 3)
222222

223223
check_res(res, err, "a")
224224
ngx.say("wait more than 1sec: ", ngx.now() - cur_time > 1)
@@ -233,6 +233,7 @@ checked [/dir] is dir.
233233
err: timeout, more than 1sec: true
234234
checked val as expect: a
235235
wait more than 1sec: true
236+
--- timeout: 5
236237
237238
238239

0 commit comments

Comments
 (0)