Skip to content

Commit

Permalink
feat(peek) [breaking] use shm:ttl() in recent OpenResty versions
Browse files Browse the repository at this point in the history
Use the new `shm:ttl()` API which was contributed in order to support
mlcache's `peek()` method. The existing `peek()` implementation was a
temporary solution until then. It is slightly unfortunate that we chose
to return the value along with the remaining TTL, as this behavior now
must break.

Pros/cons
---------
+ As a result, `peek()` is ligher and thus, faster
+ It does not touch the shm LRU queue
- It is a breaking change

Fix #39
  • Loading branch information
thibaultcha committed Jun 5, 2018
1 parent e6980c2 commit 23e5401
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 26 deletions.
77 changes: 54 additions & 23 deletions lib/resty/mlcache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ local ngx_log = ngx.log
local WARN = ngx.WARN


local has_shm_ttl
if ngx.config.ngx_lua_version >= 10011 then
has_shm_ttl = true
end


local CACHE_MISS_SENTINEL_LRU = {}
local SHM_SET_DEFAULT_TRIES = 3
local LOCK_KEY_PREFIX = "lua-resty-mlcache:lock:"
Expand Down Expand Up @@ -713,40 +719,65 @@ function _M:get(key, opts, cb, ...)
end


function _M:peek(key)
if type(key) ~= "string" then
error("key must be a string", 2)
end
if has_shm_ttl then
function _M:peek(key)
if type(key) ~= "string" then
error("key must be a string", 2)
end

-- restrict this key to the current namespace, so we isolate this
-- mlcache instance from potential other instances using the same
-- shm
local namespaced_key = self.name .. key
local namespaced_key = self.name .. key

local v, err = self.dict:get(namespaced_key)
if err then
return nil, "could not read from lua_shared_dict: " .. err
local ttl, err = self.dict:ttl(namespaced_key)
if not ttl and err ~= "not found" then
return nil, "could not read from lua_shared_dict: " .. err
end

if self.dict_miss and ttl == nil then
ttl, err = self.dict_miss:ttl(namespaced_key)
if not ttl and err ~= "not found" then
return nil, "could not read from lua_shared_dict: " .. err
end
end

return ttl
end

-- if we specified shm_miss, it might be a negative hit cached
-- there
if self.dict_miss and v == nil then
v, err = self.dict_miss:get(namespaced_key)
else
function _M:peek(key)
if type(key) ~= "string" then
error("key must be a string", 2)
end

-- restrict this key to the current namespace, so we isolate this
-- mlcache instance from potential other instances using the same
-- shm
local namespaced_key = self.name .. key

local v, err = self.dict:get(namespaced_key)
if err then
return nil, "could not read from lua_shared_dict: " .. err
end
end

if v ~= nil then
local value, err, at, ttl = unmarshall_from_shm(v)
if err then
return nil, "could not deserialize value after lua_shared_dict " ..
"retrieval: " .. err
-- if we specified shm_miss, it might be a negative hit cached
-- there
if self.dict_miss and v == nil then
v, err = self.dict_miss:get(namespaced_key)
if err then
return nil, "could not read from lua_shared_dict: " .. err
end
end

local remaining_ttl = ttl - (now() - at)
if v ~= nil then
local value, err, at, ttl = unmarshall_from_shm(v)
if err then
return nil, "could not deserialize value after " ..
"lua_shared_dict retrieval: " .. err
end

local remaining_ttl = ttl - (now() - at)

return remaining_ttl, nil, value
return remaining_ttl, nil, value
end
end
end

Expand Down
52 changes: 49 additions & 3 deletions t/03-peek.t
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

use Test::Nginx::Socket::Lua;
use Cwd qw(cwd);
use lib '.';
use t::Util;

workers(2);

Expand Down Expand Up @@ -202,6 +204,7 @@ ttl: 18


=== TEST 5: peek() returns the value if a key has been fetched before
--- skip_eval: 3: t::Util::skip_openresty('>=', '1.13.6.1')
--- http_config eval: $::HttpConfig
--- config
location = /t {
Expand Down Expand Up @@ -261,7 +264,50 @@ ttl: \d* nil_val: nil



=== TEST 6: peek() returns the value if shm_miss is specified
=== TEST 6: peek() returns no value for recent OpenResty versions
--- skip_eval: 3: t::Util::skip_openresty('<', '1.13.6.1')
--- http_config eval: $::HttpConfig
--- 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 function cb_number()
return 123
end
local val, err = cache:get("my_key", nil, cb_number)
if err then
ngx.log(ngx.ERR, err)
return
end
local ttl, err, val = cache:peek("my_key")
if err then
ngx.log(ngx.ERR, err)
return
end
ngx.say("ttl: ", math.ceil(ttl), " val: ", val)
}
}
--- request
GET /t
--- response_body_like
ttl: \d* val: nil
--- no_error_log
[error]



=== TEST 7: peek() returns the value if shm_miss is specified
--- skip_eval: 3: t::Util::skip_openresty('>=', '1.13.6.1')
--- http_config eval: $::HttpConfig
--- config
location = /t {
Expand Down Expand Up @@ -300,7 +346,7 @@ ttl: \d* nil_val: nil



=== TEST 7: peek() JITs on hit
=== TEST 8: peek() JITs on hit
--- http_config eval: $::HttpConfig
--- config
location = /t {
Expand Down Expand Up @@ -332,7 +378,7 @@ qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):13 loop\]/



=== TEST 8: peek() JITs on miss
=== TEST 9: peek() JITs on miss
--- http_config eval: $::HttpConfig
--- config
location = /t {
Expand Down

0 comments on commit 23e5401

Please sign in to comment.