Squashed 'src/deps/src/lua-resty-mlcache/' changes from ab418e423..b4d0aed5a

b4d0aed5a release: 2.7.0
0e5eb9c3a docs(changelog) add 2.7.0 changes
821d5ed4b feat(mlcache) 'peek()' only returns 0 when key has indefinite ttl
fdf9008ab feat(mlcache) new 'get()' option: resty_lock_opts
21b85abf8 tests(mlcache) remove 'l1_serializer' usage from 02-get.t

git-subtree-dir: src/deps/src/lua-resty-mlcache
git-subtree-split: b4d0aed5adf74b118238efdcd971224278ec7d26
This commit is contained in:
Théophile Diot 2024-02-15 11:11:42 +01:00
parent 5dcf04a15d
commit c617d20398
6 changed files with 158 additions and 38 deletions

View file

@ -1,5 +1,6 @@
# Table of Contents
- [2.7.0](#270)
- [2.6.1](#261)
- [2.6.0](#260)
- [2.5.0](#250)
@ -15,6 +16,26 @@
- [1.0.1](#101)
- [1.0.0](#100)
## [2.7.0]
> Released on: 2024/02/09
#### Changed
- Update `peek()` to only return `0` when TTL (or neg-TTL) was "indefinite"
(i.e. `0`). Any non-zero TTL now guarantees a non-zero return value for
`peek()`. A stale value still in cache may still return a negative return
value.
[#124](https://github.com/thibaultcha/lua-resty-mlcache/pull/124)
#### Added
- New `get()` option `resty_lock_opts` allows overriding lua-resty-lock option
for individual calls.
[#125](https://github.com/thibaultcha/lua-resty-mlcache/pull/125)
[Back to TOC](#table-of-contents)
## [2.6.1]
> Released on: 2024/01/30
@ -268,6 +289,7 @@ Initial release.
[Back to TOC](#table-of-contents)
[2.7.0]: https://github.com/thibaultcha/lua-resty-mlcache/compare/2.6.1...2.7.0
[2.6.1]: https://github.com/thibaultcha/lua-resty-mlcache/compare/2.6.0...2.6.1
[2.6.0]: https://github.com/thibaultcha/lua-resty-mlcache/compare/2.5.0...2.6.0
[2.5.0]: https://github.com/thibaultcha/lua-resty-mlcache/compare/2.4.1...2.5.0

View file

@ -410,6 +410,9 @@ options:
having to repeat such transformations on every request, such as creating
tables, cdata objects, loading new Lua code, etc...
**Default:** inherited from the instance.
- `resty_lock_opts`: _optional_ table. If specified, override the instance
`resty_lock_opts` for the current `get()` lookup.
**Default:** inherited from the instance.
The third argument `callback` is optional. If provided, it must be a function
whose signature and return values are documented in the following example:
@ -745,8 +748,12 @@ If there is no value for the queried `key`, it returns `nil` and no error.
If there is a value for the queried `key`, it returns a number indicating the
remaining TTL of the cached value (in seconds) and no error. If the value for
`key` has expired but is still in the L2 cache, returned TTL value will be
negative. Finally, the third returned value in that case will be the cached
value itself, for convenience.
negative. The remaining TTL return value will only be `0` if the queried `key`
has an indefinite ttl (`ttl=0`). Otherwise, this return value may be positive
(`key` still valid), or negative (`key` is stale).
The third returned value will be the cached value as stored in the L2 cache, if
still available.
This method is useful when you want to determine if a value is cached. A value
stored in the L2 cache is considered cached regardless of whether or not it is

View file

@ -174,7 +174,7 @@ end
local _M = {
_VERSION = "2.6.1",
_VERSION = "2.7.0",
_AUTHOR = "Thibault Charbonnier",
_LICENSE = "MIT",
_URL = "https://github.com/thibaultcha/lua-resty-mlcache",
@ -616,6 +616,7 @@ local function check_opts(self, opts)
local resurrect_ttl
local l1_serializer
local shm_set_tries
local resty_lock_opts
if opts ~= nil then
if type(opts) ~= "table" then
@ -670,6 +671,13 @@ local function check_opts(self, opts)
error("opts.shm_set_tries must be >= 1", 3)
end
end
resty_lock_opts = opts.resty_lock_opts
if resty_lock_opts ~= nil then
if type(resty_lock_opts) ~= "table" then
error("opts.resty_lock_opts must be a table", 3)
end
end
end
if not ttl then
@ -692,7 +700,12 @@ local function check_opts(self, opts)
shm_set_tries = self.shm_set_tries
end
return ttl, neg_ttl, resurrect_ttl, l1_serializer, shm_set_tries
if not resty_lock_opts then
resty_lock_opts = self.resty_lock_opts
end
return ttl, neg_ttl, resurrect_ttl, l1_serializer, shm_set_tries,
resty_lock_opts
end
@ -707,9 +720,9 @@ end
local function run_callback(self, key, shm_key, data, ttl, neg_ttl,
went_stale, l1_serializer, resurrect_ttl, shm_set_tries, cb, ...)
went_stale, l1_serializer, resurrect_ttl, shm_set_tries, rlock_opts, cb, ...)
local lock, err = resty_lock:new(self.shm_locks, self.resty_lock_opts)
local lock, err = resty_lock:new(self.shm_locks, rlock_opts)
if not lock then
return nil, "could not create lock: " .. err
end
@ -877,8 +890,8 @@ function _M:get(key, opts, cb, ...)
-- opts validation
local ttl, neg_ttl, resurrect_ttl, l1_serializer, shm_set_tries =
check_opts(self, opts)
local ttl, neg_ttl, resurrect_ttl, l1_serializer, shm_set_tries,
rlock_opts = check_opts(self, opts)
local err, went_stale, is_stale
data, err, went_stale, is_stale = get_shm_set_lru(self, key, namespaced_key,
@ -906,7 +919,7 @@ function _M:get(key, opts, cb, ...)
return run_callback(self, key, namespaced_key, data, ttl, neg_ttl,
went_stale, l1_serializer, resurrect_ttl,
shm_set_tries, cb, ...)
shm_set_tries, rlock_opts, cb, ...)
end
@ -922,6 +935,7 @@ local function run_thread(self, ops, from, to)
ctx.l1_serializer,
ctx.resurrect_ttl,
ctx.shm_set_tries,
ctx.rlock_opts,
ctx.cb, ctx.arg)
end
end
@ -1042,8 +1056,8 @@ function _M:get_bulk(bulk, opts)
res[res_idx + 2] = 1
else
local pok, ttl, neg_ttl, resurrect_ttl, l1_serializer, shm_set_tries
= pcall(check_opts, self, b_opts)
local pok, ttl, neg_ttl, resurrect_ttl, l1_serializer,
shm_set_tries, rlock_opts = pcall(check_opts, self, b_opts)
if not pok then
-- strip the stacktrace
local err = ttl:match("mlcache%.lua:%d+:%s(.*)")
@ -1096,6 +1110,7 @@ function _M:get_bulk(bulk, opts)
ctx.l1_serializer = l1_serializer
ctx.resurrect_ttl = resurrect_ttl
ctx.shm_set_tries = shm_set_tries
ctx.rlock_opts = rlock_opts
ctx.data = data
ctx.err = nil
ctx.hit_lvl = nil
@ -1262,7 +1277,16 @@ function _M:peek(key, stale)
"retrieval: " .. err
end
local remaining_ttl = ttl - (now() - at)
local remaining_ttl = 0
if ttl > 0 then
remaining_ttl = ttl - (now() - at)
if remaining_ttl == 0 then
-- guarantee a non-zero remaining_ttl if ttl is set
remaining_ttl = 0.001
end
end
return remaining_ttl, nil, value, went_stale
end

View file

@ -1,8 +1,8 @@
package = "lua-resty-mlcache"
version = "2.6.1-1"
version = "2.7.0-1"
source = {
url = "git+https://github.com/thibaultcha/lua-resty-mlcache",
tag = "2.6.1"
tag = "2.7.0"
}
description = {
summary = "Layered caching library for OpenResty",

View file

@ -701,9 +701,6 @@ qr/\[error\] .*?mlcache\.lua:\d+: cannot cache value of type userdata/
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
ttl = 0.3,
l1_serializer = function(s)
return "override"
end
}))
local function cb()
@ -712,17 +709,17 @@ qr/\[error\] .*?mlcache\.lua:\d+: cannot cache value of type userdata/
end
local data = assert(cache:get("key", nil, cb))
assert(data == "override")
assert(data == 123)
ngx.sleep(0.2)
data = assert(cache:get("key", nil, cb))
assert(data == "override")
assert(data == 123)
ngx.sleep(0.2)
local data, err, lvl = assert(cache:get("key", nil, cb))
assert(data == "override")
assert(data == 123)
}
}
--- response_body
@ -1769,7 +1766,35 @@ in positive callback
=== TEST 42: get() passes 'resty_lock_opts' for L3 calls
=== TEST 42: get() errors on invalid opts.resty_lock_opts
--- config
location /t {
content_by_lua_block {
local mlcache = require "resty.mlcache"
local cache, err = mlcache.new("my_mlcache", "cache_shm")
if not cache then
ngx.log(ngx.ERR, err)
return
end
local ok, err = pcall(cache.get, cache, "key", {
resty_lock_opts = "true"
})
if not ok then
ngx.say(err)
end
}
}
--- response_body
opts.resty_lock_opts must be a table
--- no_error_log
[error]
[crit]
=== TEST 43: get() passes 'resty_lock_opts' for L3 calls
--- config
location /t {
content_by_lua_block {
@ -1810,7 +1835,51 @@ was given 'opts.resty_lock_opts': true
=== TEST 43: get() errors on lock timeout
=== TEST 44: get() uses 'opts.resty_lock_opts' if specified
--- config
location /t {
content_by_lua_block {
local resty_lock = require "resty.lock"
local mlcache = require "resty.mlcache"
local opts = { timeout = 1 }
local resty_lock_opts = { timeout = 5 }
do
local orig_resty_lock_new = resty_lock.new
resty_lock.new = function(_, dict_name, opts, ...)
ngx.say("was given 'opts.resty_lock_opts': ", opts == resty_lock_opts)
return orig_resty_lock_new(_, dict_name, opts, ...)
end
end
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
resty_lock_opts = opts,
})
if not cache then
ngx.log(ngx.ERR, err)
return
end
local data, err = cache:get("key", {
resty_lock_opts = resty_lock_opts,
}, function() return nil end)
if err then
ngx.log(ngx.ERR, err)
return
end
}
}
--- response_body
was given 'opts.resty_lock_opts': true
--- no_error_log
[error]
[crit]
=== TEST 45: get() errors on lock timeout
--- config
location /t {
access_by_lua_block {
@ -1888,7 +1957,7 @@ hit_lvl: 1
=== TEST 44: get() returns data even if failed to set in shm
=== TEST 46: get() returns data even if failed to set in shm
--- config
location /t {
content_by_lua_block {
@ -1937,7 +2006,7 @@ qr/\[warn\] .*? could not write to lua_shared_dict 'cache_shm' after 3 tries \(n
=== TEST 45: get() errors on invalid opts.shm_set_tries
=== TEST 47: get() errors on invalid opts.shm_set_tries
--- config
location /t {
content_by_lua_block {
@ -1975,7 +2044,7 @@ opts.shm_set_tries must be >= 1
=== TEST 46: get() with default shm_set_tries to LRU evict items when a large value is being cached
=== TEST 48: get() with default shm_set_tries to LRU evict items when a large value is being cached
--- config
location /t {
content_by_lua_block {
@ -2043,7 +2112,7 @@ callback was called: 1 times
=== TEST 47: get() respects instance opts.shm_set_tries to LRU evict items when a large value is being cached
=== TEST 49: get() respects instance opts.shm_set_tries to LRU evict items when a large value is being cached
--- config
location /t {
content_by_lua_block {
@ -2113,7 +2182,7 @@ callback was called: 1 times
=== TEST 48: get() accepts opts.shm_set_tries to LRU evict items when a large value is being cached
=== TEST 50: get() accepts opts.shm_set_tries to LRU evict items when a large value is being cached
--- config
location /t {
content_by_lua_block {
@ -2183,7 +2252,7 @@ callback was called: 1 times
=== TEST 49: get() caches data in L1 LRU even if failed to set in shm
=== TEST 51: get() caches data in L1 LRU even if failed to set in shm
--- config
location /t {
content_by_lua_block {
@ -2245,7 +2314,7 @@ is stale: true
=== TEST 50: get() does not cache value in LRU indefinitely when retrieved from shm on last ms (see GH PR #58)
=== TEST 52: get() does not cache value in LRU indefinitely when retrieved from shm on last ms (see GH PR #58)
--- config
location /t {
content_by_lua_block {
@ -2308,7 +2377,7 @@ is stale: true
=== TEST 51: get() bypass cache for negative callback TTL
=== TEST 53: get() bypass cache for negative callback TTL
--- config
location /t {
content_by_lua_block {
@ -2373,7 +2442,7 @@ in negative callback
=== TEST 52: get() nil callback returns positive cached items from L1/L2
=== TEST 54: get() nil callback returns positive cached items from L1/L2
--- config
location /t {
content_by_lua_block {
@ -2455,7 +2524,7 @@ hit_lvl: 1
=== TEST 53: get() nil callback returns negative cached items from L1/L2
=== TEST 55: get() nil callback returns negative cached items from L1/L2
--- config
location /t {
content_by_lua_block {
@ -2537,7 +2606,7 @@ hit_lvl: 1
=== TEST 54: get() JITs on misses without a callback
=== TEST 56: get() JITs on misses without a callback
--- config
location /t {
content_by_lua_block {

View file

@ -120,9 +120,7 @@ ttl: 18
=== TEST 4: peek() returns a negative ttl when a key expired
--- main_config
timer_resolution 10ms;
=== TEST 4: peek() returns a 0 remaining_ttl if the ttl was 0
--- config
location /t {
content_by_lua_block {
@ -152,8 +150,8 @@ ttl: 18
}
}
--- response_body
ttl: -1
ttl: -2
ttl: 0
ttl: 0
--- no_error_log
[error]
[crit]