Skip to content

Commit

Permalink
Closes #264
Browse files Browse the repository at this point in the history
  • Loading branch information
subnetmarco committed Jul 8, 2016
1 parent e26a80f commit 569ba9c
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 5 deletions.
1 change: 1 addition & 0 deletions kong/templates/nginx_kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ lua_shared_dict cache ${{MEM_CACHE_SIZE}};
lua_shared_dict reports_locks 100k;
lua_shared_dict cluster_locks 100k;
lua_shared_dict cluster_autojoin_locks 100k;
lua_shared_dict cache_locks 100k;
lua_shared_dict cassandra 1m;
lua_shared_dict cassandra_prepared 5m;
lua_socket_log_errors off;
Expand Down
Empty file added kong/tools/07-cache
Empty file.
32 changes: 27 additions & 5 deletions kong/tools/database_cache.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local resty_lock = require "resty.lock"
local cjson = require "cjson"
local cache = ngx.shared.cache

Expand Down Expand Up @@ -120,21 +121,42 @@ function _M.all_apis_by_dict_key()
end

function _M.get_or_set(key, cb)
local lock = resty_lock:new("cache_locks", {
exptime = 10,
timeout = 10
})

local value, err
-- Try to get

-- Try to get the value from the cache
value = _M.get(key)
if value then return value end

-- The value is missing, aquire a lock
local elapsed, err = lock:lock(key)
if not elapsed then
ngx.log(ngx.ERR, "failed to acquire cache lock: "..err)
end

-- Lock acquired. Since in the meanwhile another worker may have
-- populated the value we have to check again
value = _M.get(key)
if not value then
-- Get from closure
value, err = cb()
if err then
return nil, err
elseif value then
if value then
local ok, err = _M.set(key, value)
if not ok then
if err then
ngx.log(ngx.ERR, err)
end
end
end

local ok, err = lock:unlock()
if not ok then
ngx.log(ngx.ERR, "failed to unlock: "..err)
end

return value
end

Expand Down
File renamed without changes.
84 changes: 84 additions & 0 deletions spec/02-integration/07-cache/database_cache_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
local helpers = require "spec.helpers"
local cjson = require "cjson"
local meta = require "kong.meta"

describe("Resolver", function()
local client
setup(function()
helpers.kill_all()

assert(helpers.dao.apis:insert {
request_host = "mockbin.com",
upstream_url = "http://mockbin.com"
})

assert(helpers.start_kong({
["custom_plugins"] = "database-cache",
lua_package_path = "?/init.lua;./kong/?.lua;./spec/fixtures/?.lua"
}))

-- Add the plugin
local admin_client = helpers.admin_client()
local res = assert(admin_client:send {
method = "POST",
path = "/apis/mockbin.com/plugins/",
body = {
name = "database-cache"
},
headers = {
["Content-Type"] = "application/json"
}
})
assert.res_status(201, res)
admin_client:close()
end)

teardown(function()
helpers.stop_kong()
end)

it("avoids dog-pile effect", function()
local function make_request(premature, sleep_time)
local client = helpers.proxy_client()
local res = assert(client:send {
method = "GET",
path = "/status/200?sleep="..sleep_time,
headers = {
["Host"] = "mockbin.com"
}
})
res:read_body()
client:close()
end

local ok, err = ngx.timer.at(0, make_request, 2)
assert.truthy(ok)

local ok, err = ngx.timer.at(0, make_request, 5)
assert.truthy(ok)

local ok, err = ngx.timer.at(0, make_request, 1)
assert.truthy(ok)

helpers.wait_until(function()
local admin_client = helpers.admin_client()
local res = assert(admin_client:send {
method = "GET",
path = "/cache/invocations"
})
local body = res:read_body()
admin_client:close()
return cjson.decode(body).message == 3
end, 10)

-- Invocation are 3, but lookups should be 1
local admin_client = helpers.admin_client()
local res = assert(admin_client:send {
method = "GET",
path = "/cache/lookups"
})
local body = res:read_body()
admin_client:close()
assert.equal(1, cjson.decode(body).message)
end)
end)
35 changes: 35 additions & 0 deletions spec/fixtures/kong/plugins/database-cache/handler.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
local BasePlugin = require "kong.plugins.base_plugin"
local cache = require "kong.tools.database_cache"

local INVOCATIONS = "invocations"
local LOOKUPS = "lookups"

local DatabaseCacheHandler = BasePlugin:extend()

DatabaseCacheHandler.PRIORITY = 1000

function DatabaseCacheHandler:new()
DatabaseCacheHandler.super.new(self, "database-cache")
end

function DatabaseCacheHandler:init_worker()
DatabaseCacheHandler.super.init_worker(self)

cache.rawset(INVOCATIONS, 0)
cache.rawset(LOOKUPS, 0)
end

function DatabaseCacheHandler:access(conf)
DatabaseCacheHandler.super.access(self)

cache.get_or_set("pile_effect", function()
cache.incr(LOOKUPS, 1)
-- Adds some delay
ngx.sleep(tonumber(ngx.req.get_uri_args().sleep))
return true
end)

cache.incr(INVOCATIONS, 1)
end

return DatabaseCacheHandler
3 changes: 3 additions & 0 deletions spec/fixtures/kong/plugins/database-cache/schema.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
return {
fields = {}
}

0 comments on commit 569ba9c

Please sign in to comment.