NGINX Timer Resolution

Using ngx.time or ngx.now is encouraged over using Lua’s built in functions because they use the cached time rather than performing a syscall, but how often is the cache updated?

After a bit of a dig, it turns out there’s no absolute answer, because the cache is actually updated when a kernel event fires:

It can be set manually using nginx’s timer_resolution
http://nginx.org/en/docs/ngx_core_module.html#timer_resolution
but this is not recommended because it either causes too many syscalls if set too low, or necessary time lag if set too high.

https://groups.google.com/d/msg/openresty-en/OdNzfh8rlzk/EQHF-hlhlQ0J

Openresty Redis ZUNIONSTORE gotcha

Problem

ZUNIONSTORE merges multiple sorted sets into one, and stores the result under the key specified. Since the number of keys can vary and there are more parameters after the keys, it require the numkeys parameter to be specified before the keys.

If using the default aggregate function (SUM) this is fine, as you can simply store the sorted set names to be merged in a table, use the size of the table as numkeys, and unpack() the table to pass all of the keys names to redis.

The problem occurs when you want to change the aggregate function, adding more parameters after unpack(), which changes its behaviour:

http://www.lua.org/pil/5.1.html
‘Lua always adjusts the number of results from a function to the circumstances of the call. When we call a function as a statement, Lua discards all of its results. When we use a call as an expression, Lua keeps only the first result. We get all results only when the call is the last (or the only) expression in a list of expressions.’

So unpack will only pass the first sorted set key name.

Solution

The workaround is to add the aggregate command to the list of sorted set key names, and deduct the number of keys passed:

table.insert(setNames, ‘AGGREGATE’)
table.insert(setNames, ‘MAX’)
local ok, err = red:zunionstore(‘destinationKey’,#setNames-2,unpack(setNames))