Skip to content

Commit d06eb95

Browse files
dndxagentzh
authored andcommitted
feature: added new method expire() that can change the TTL of the lock being held.
Signed-off-by: Yichun Zhang (agentzh) <agentzh@gmail.com>
1 parent 20cd49f commit d06eb95

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

README.markdown

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Table of Contents
1414
* [new](#new)
1515
* [lock](#lock)
1616
* [unlock](#unlock)
17+
* [expire](#expire)
1718
* [For Multiple Lua Light Threads](#for-multiple-lua-light-threads)
1819
* [For Cache Locks](#for-cache-locks)
1920
* [Prerequisites](#prerequisites)
@@ -162,6 +163,22 @@ Returns `1` on success. Returns `nil` and a string describing the error otherwis
162163

163164
If you call `unlock` when no lock is currently held, the error "unlocked" will be returned.
164165

166+
expire
167+
------
168+
`syntax: ok, err = obj:expire(timeout)`
169+
170+
Sets the TTL of the lock held by the current `resty.lock` object instance. This will reset the
171+
timeout of the lock to `timeout` seconds if it is given, otherwise the `timeout` provided while
172+
calling [new](#new) will be used.
173+
174+
Note that the `timeout` supplied inside this function is independent from the `timeout` provided while
175+
calling [new](#new). Calling `expire()` will not change the `timeout` value specified inside [new](#new)
176+
and subsequent `expire(nil)` call will still use the `timeout` number from [new](#new).
177+
178+
Returns `true` on success. Returns `nil` and a string describing the error otherwise.
179+
180+
If you call `expire` when no lock is currently held, the error "unlocked" will be returned.
181+
165182
[Back to TOC](#table-of-contents)
166183

167184
For Multiple Lua Light Threads

lib/resty/lock.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ function _M.lock(self, key)
135135
local ok, err = dict:add(key, true, exptime)
136136
if ok then
137137
cdata.key_id = ref_obj(key)
138+
self.key = key
138139
return 0
139140
end
140141
if err ~= "exists" then
@@ -154,6 +155,7 @@ function _M.lock(self, key)
154155
local ok, err = dict:add(key, true, exptime)
155156
if ok then
156157
cdata.key_id = ref_obj(key)
158+
self.key = key
157159
return elapsed
158160
end
159161

@@ -193,4 +195,25 @@ function _M.unlock(self)
193195
end
194196

195197

198+
function _M.expire(self, time)
199+
local dict = self.dict
200+
local cdata = self.cdata
201+
local key_id = tonumber(cdata.key_id)
202+
if key_id <= 0 then
203+
return nil, "unlocked"
204+
end
205+
206+
if not time then
207+
time = self.exptime
208+
end
209+
210+
local ok, err = dict:replace(self.key, true, time)
211+
if not ok then
212+
return nil, err
213+
end
214+
215+
return true
216+
end
217+
218+
196219
return _M

t/sanity.t

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,76 @@ lock 2: unlock: nil, unlocked
468468
--- no_error_log
469469
[error]
470470

471+
472+
473+
=== TEST 13: expire()
474+
--- http_config eval: $::HttpConfig
475+
--- config
476+
location = /t {
477+
content_by_lua_block {
478+
local lock = require "resty.lock"
479+
for i = 1, 2 do
480+
local lock1 = lock:new("cache_locks", { timeout = 0, exptime = 0.1 })
481+
local lock2 = lock:new("cache_locks", { timeout = 0, exptime = 0.1 })
482+
483+
local exp, err = lock1:expire()
484+
ngx.say("lock 1: expire: ", exp, ", ", err)
485+
486+
local elapsed, err = lock1:lock("foo")
487+
ngx.say("lock 1: lock: ", elapsed, ", ", err)
488+
489+
ngx.sleep(0.06)
490+
491+
local exp, err = lock1:expire()
492+
ngx.say("lock 1: expire: ", exp, ", ", err)
493+
494+
ngx.sleep(0.06)
495+
496+
local elapsed, err = lock2:lock("foo")
497+
ngx.say("lock 2: lock: ", elapsed, ", ", err)
498+
499+
local exp, err = lock1:expire(0.2)
500+
ngx.say("lock 1: expire: ", exp, ", ", err)
501+
502+
ngx.sleep(0.15)
503+
504+
local elapsed, err = lock2:lock("foo")
505+
ngx.say("lock 2: lock: ", elapsed, ", ", err)
506+
507+
ngx.sleep(0.1)
508+
509+
local elapsed, err = lock2:lock("foo")
510+
ngx.say("lock 2: lock: ", elapsed, ", ", err)
511+
512+
local ok, err = lock2:unlock()
513+
ngx.say("lock 2: unlock: ", ok, ", ", err)
514+
515+
local exp, err = lock2:expire(0.2)
516+
ngx.say("lock 2: expire: ", exp, ", ", err)
517+
end
518+
}
519+
}
520+
--- request
521+
GET /t
522+
--- response_body
523+
lock 1: expire: nil, unlocked
524+
lock 1: lock: 0, nil
525+
lock 1: expire: true, nil
526+
lock 2: lock: nil, timeout
527+
lock 1: expire: true, nil
528+
lock 2: lock: nil, timeout
529+
lock 2: lock: 0, nil
530+
lock 2: unlock: 1, nil
531+
lock 2: expire: nil, unlocked
532+
lock 1: expire: nil, unlocked
533+
lock 1: lock: 0, nil
534+
lock 1: expire: true, nil
535+
lock 2: lock: nil, timeout
536+
lock 1: expire: true, nil
537+
lock 2: lock: nil, timeout
538+
lock 2: lock: 0, nil
539+
lock 2: unlock: 1, nil
540+
lock 2: expire: nil, unlocked
541+
542+
--- no_error_log
543+
[error]

0 commit comments

Comments
 (0)