Kong singletons cache logic in custom plugin QQ

I have been trying to implement a bit of a /logout functionality for cached entities with the mlcache lib that will clean out a cached entry from all workers of a node (or multiple clustered nodes if possible), I modified my code like so adding an update so the delete gets propagated against all workers on a single node. I am thinking Kong maybe handles this so I don’t need to?

First looked at this readme:

Then I went back and started looking over here:

local singletons = require "kong.singletons"
   if conf.user_info_cache_enabled then
      local ok, err = singletons.cache:delete(encrypted_token)
      if not ok then
         ngx.log(ngx.ERR, "Failed to find cache entry: ", err)
	 return responses.HTTP_NOT_FOUND()
      end
end

Maybe that delete should actually be:

cache:invalidate(key) or cache:invalidate_local(key) ??? This cached value could technically reside on one of the nodes in memory(not in the db itself as a value, but that may be a road-map feature to store the token to db and propagate across multiple nodes like oauth2) or multiple nodes in memory only. Not sure if this is a problem for Kong so figured I would ask here, would prefer to use :invalidate it if its safe to do so even if it does not exist on the other nodes(or does :stuck_out_tongue: ).

The other snippet of my code was updated to this:

local function getKongKey(eoauth_token, access_token, callback_url, conf)

 -- make sure L1 cache is evicted of stale values before calling get()
  local ok, err1 = singletons.cache:update()
  if not ok then
     ngx.log(ngx.ERR, "failed to poll eviction events: ", err1)
  end

  local userInfo, err = singletons.cache:get(eoauth_token, { ttl = 28800 }, getUserInfo, access_token, callback_url, conf)
	
  if err then
    ngx.log(ngx.ERR, "Could not retrieve UserInfo: ", err)
    return
  end
	
  return userInfo
end

The :update is throwing a nil currently as well so I am assuming this may not be needed(and does not even exist) in the Kong mlcache singleton?

EDIT:
So just studying the code it seems that yes I can do a :invalidate() and that will create a record in the db that helps it propagate to other nodes within the cluster(should not hurt if no entry in other cluster nodes). And then update is not needed in the next part since Kong will handle that during its broadcast and worker_events execution?

Feeling closer here, but behavior is strange. invalidate reports nil not found when I know based on my requests its present in all my cluster nodes local singleton cache at that point:

2018/05/25 19:51:52 [error] 55#0: *11689 [lua] access.lua:93: run(): Failed to find cache entry: nil, client: 10.0.0.1, server: kong, request: "GET /oidc/test/logout HTTP/1.1", host: "gateway-dev-core.company.com"
   if conf.user_info_cache_enabled then
      local ok, err = singletons.cache:invalidate(encrypted_token)
      if not ok then
         ngx.log(ngx.ERR, "Failed to find cache entry: ", err)
	 return responses.send_HTTP_NOT_FOUND()
      end
end
local function getKongKey(eoauth_token, access_token, callback_url, conf)
  -- This will add a 28800 second (8 hour) expiring TTL on this cached value
  -- https://github.com/thibaultcha/lua-resty-mlcache/blob/master/README.md
  local userInfo, err = singletons.cache:get(eoauth_token, { ttl = 28800 }, getUserInfo, access_token, callback_url, conf)
	
  if err then
    ngx.log(ngx.ERR, "Could not retrieve UserInfo: ", err)
    return
  end
	
  return userInfo
end

EIDT: OR wait… in sample code with Kong I see invalidate does not have return values. So we just assume it sort of worked lol?

invalidate() has no return value since logging potential errors is already done within the function itself, and in the case of the core/bundled plugins (the “official” users of this module), there isn’t much more they can do or care to do when such errors occur. Do you have a need for handling the error explicitly and take some action?

1 Like

Can’t say its a real concern. In my specific case I was imagining throwing a 404 not found if someone attempts to call the /logout and I attempt to invalidate but there is no cached value to invalidate, but honestly I can just #fingersCrossed assume it works if it is present and return a 200 Ok regardless if cached entity is present or not.

Does invalidate() work like I assumed? Safe to run even if other nodes does not have it present and it temporarily creates an entry in db for other nodes to look into? Also the update gets handled internally on the Kong singleton mlcache so future gets will not be stale?

Thanks!

Yes, it works as you understood it and is meant to be used like so. Arguably, retuning 200 OK could be acceptable in both cases, since logging out a user who wasn’t logged in in the first place produces the same result: the user is successfully logged out. We follow the same conventions (sort of idempotent) in our new Admin API implementation to handle DELETE operations on non-existing entities. The end state is that the user isn’t logged in. I would still advise for monitoring invalidation errors of course, but never saw any in the field personally.

1 Like