lua-counter example

Annotation For counter.lua
anonymous

Annotation For counter.lua

Origin for each line in counter.lua from check-in 38ec946cba:

38ec946cba 2014-07-03    1: -- module counter - counts some junk
38ec946cba 2014-07-03    2: 
38ec946cba 2014-07-03    3: local today = os.date('*t')
38ec946cba 2014-07-03    4: local timestamp = os.time{year = today['year'], month = today['month'], day = today['day']}
38ec946cba 2014-07-03    5: local referer = '-';
38ec946cba 2014-07-03    6: 
38ec946cba 2014-07-03    7: if ngx.var.http_referer ~= nil then
38ec946cba 2014-07-03    8: 	_, _, referer = string.find(ngx.var.http_referer, '^https?://([%w%.]+)')
38ec946cba 2014-07-03    9: end
38ec946cba 2014-07-03   10: 
38ec946cba 2014-07-03   11: local key = 'stat_counter_' .. timestamp .. '_' .. referer
38ec946cba 2014-07-03   12: 
38ec946cba 2014-07-03   13: -- connect to redis
38ec946cba 2014-07-03   14: local redis = require 'resty.redis'
38ec946cba 2014-07-03   15: local red = redis:new()
38ec946cba 2014-07-03   16: local ok, err = red:connect('127.0.0.1', 6379)
38ec946cba 2014-07-03   17: if not ok then
38ec946cba 2014-07-03   18: 	ngx.log(ngx.ERR, 'redis connection failed: ', err)
38ec946cba 2014-07-03   19: 	ngx.exit(500)
38ec946cba 2014-07-03   20: end
38ec946cba 2014-07-03   21: 
38ec946cba 2014-07-03   22: local cjson = require 'cjson'
38ec946cba 2014-07-03   23: 
38ec946cba 2014-07-03   24: -- decodes values from array into dict
38ec946cba 2014-07-03   25: function decode_bulk(reply)
38ec946cba 2014-07-03   26: 	local data = {}
38ec946cba 2014-07-03   27: 	for j=1, #reply, 2 do
38ec946cba 2014-07-03   28: 		data[reply[j] ] = reply[j+1]
38ec946cba 2014-07-03   29: 	end
38ec946cba 2014-07-03   30: 	return(data)
38ec946cba 2014-07-03   31: end
38ec946cba 2014-07-03   32: 
38ec946cba 2014-07-03   33: local data, empty
38ec946cba 2014-07-03   34: empty, err = red:hsetnx(key, 'today', 0)
38ec946cba 2014-07-03   35: if not empty then
38ec946cba 2014-07-03   36: 	ngx.log(ngx.ERR, 'redis query failed: ', err)
38ec946cba 2014-07-03   37: 	ngx.exit(500)
38ec946cba 2014-07-03   38: end
38ec946cba 2014-07-03   39: 
38ec946cba 2014-07-03   40: if empty == 0 then
38ec946cba 2014-07-03   41: 	data, err = red:hgetall(key)
38ec946cba 2014-07-03   42: 	if not data then
38ec946cba 2014-07-03   43: 		ngx.log(ngx.ERR, 'redis query failed: ', err)
38ec946cba 2014-07-03   44: 		ngx.exit(500)
38ec946cba 2014-07-03   45: 	end
38ec946cba 2014-07-03   46: end
38ec946cba 2014-07-03   47: 
38ec946cba 2014-07-03   48: if empty == 1 or data.whole == nil then
38ec946cba 2014-07-03   49: 	-- postgres fallback
38ec946cba 2014-07-03   50: 	result = ngx.location.capture('/postgres', {
38ec946cba 2014-07-03   51: 		method = ngx.HTTP_PUT,
38ec946cba 2014-07-03   52: 		body = "select * from get_stats('" .. referer .. "') as (today int, lastday int, week bigint, whole bigint);"
38ec946cba 2014-07-03   53: 	})
38ec946cba 2014-07-03   54: 	if result.status ~= 200 or not result.body then
38ec946cba 2014-07-03   55: 		ngx.log(ngx.ERR, 'postgres access failed')
38ec946cba 2014-07-03   56: 		ngx.exit(500)
38ec946cba 2014-07-03   57: 	else
38ec946cba 2014-07-03   58: 		local unrds = require "rds.parser"
38ec946cba 2014-07-03   59: 		local res, err = unrds.parse(result.body)
38ec946cba 2014-07-03   60: 		if res == nil then
38ec946cba 2014-07-03   61: 			ngx.log(ngx.ERR, 'failed to obtain data: ' .. err)
38ec946cba 2014-07-03   62: 			ngx.exit(500)
38ec946cba 2014-07-03   63: 		else
38ec946cba 2014-07-03   64: 			data = res.resultset[1]
38ec946cba 2014-07-03   65: 			local req = {key}
38ec946cba 2014-07-03   66: 
38ec946cba 2014-07-03   67: 			for name, value in pairs(data) do
38ec946cba 2014-07-03   68: 				if value == unrds.null then
38ec946cba 2014-07-03   69: 					value = 0
38ec946cba 2014-07-03   70: 				end
38ec946cba 2014-07-03   71: 				if name ~= 'today' then
38ec946cba 2014-07-03   72: 					table.insert(req, name)
38ec946cba 2014-07-03   73: 					table.insert(req, value)
38ec946cba 2014-07-03   74: 				end
38ec946cba 2014-07-03   75: 			end
38ec946cba 2014-07-03   76: 
38ec946cba 2014-07-03   77: 			red:init_pipeline(3)
38ec946cba 2014-07-03   78: 			red:hmset{req}
38ec946cba 2014-07-03   79: 			red:expire(key, 129600)
38ec946cba 2014-07-03   80: 			red:hincrby(key, 'today', data.today)
38ec946cba 2014-07-03   81: 			res, err = red:commit_pipeline()
38ec946cba 2014-07-03   82: 			if not res then
38ec946cba 2014-07-03   83: 				ngx.log(ngx.ERR, 'redis pipeline failed: ', err)
38ec946cba 2014-07-03   84: 				ngx.exit(500)
38ec946cba 2014-07-03   85: 			end
38ec946cba 2014-07-03   86: 		end
38ec946cba 2014-07-03   87: 	end
38ec946cba 2014-07-03   88: end
38ec946cba 2014-07-03   89: 
38ec946cba 2014-07-03   90: data.today = data.today + 1
38ec946cba 2014-07-03   91: ngx.say(cjson.encode(data))
38ec946cba 2014-07-03   92: ngx.eof()
38ec946cba 2014-07-03   93: 
38ec946cba 2014-07-03   94: res, err = red:hincrby(key, 'today', 1)
38ec946cba 2014-07-03   95: local uid = ''
38ec946cba 2014-07-03   96: 
38ec946cba 2014-07-03   97: if ngx.var.uid_got ~= nil and string.find(ngx.var.uid_got, 'uid=') == 1 then
38ec946cba 2014-07-03   98: 	uid = string.sub(ngx.var.uid_got, 5)
38ec946cba 2014-07-03   99: elseif ngx.var.uid_set ~= nil and string.find(ngx.var.uid_set, 'uid=') == 1 then
38ec946cba 2014-07-03  100: 	uid = string.sub(ngx.var.uid_set, 5)
38ec946cba 2014-07-03  101: end
38ec946cba 2014-07-03  102: 
38ec946cba 2014-07-03  103: local hit_key = uid .. '_' .. referer .. '_' .. ngx.var.remote_addr
38ec946cba 2014-07-03  104: 
38ec946cba 2014-07-03  105: red:init_pipeline(5)
38ec946cba 2014-07-03  106: red:multi()
38ec946cba 2014-07-03  107: red:hincrby('stat_counter_pending', hit_key, 1)
38ec946cba 2014-07-03  108: red:expire('stat_counter_pending', 60)
38ec946cba 2014-07-03  109: red:renamenx('stat_counter_pending', 'stat_counter_pending_tmp')
38ec946cba 2014-07-03  110: red:exec()
38ec946cba 2014-07-03  111: renamed, err = red:commit_pipeline()
38ec946cba 2014-07-03  112: if not renamed then
38ec946cba 2014-07-03  113: 	ngx.log(ngx.ERR, 'redis multi failed: ', err)
38ec946cba 2014-07-03  114: 	ngx.exit(500)
38ec946cba 2014-07-03  115: end
38ec946cba 2014-07-03  116: 
38ec946cba 2014-07-03  117: local continue = false
38ec946cba 2014-07-03  118: if tonumber(renamed[5][3]) == 1 then
38ec946cba 2014-07-03  119: 	continue = true
38ec946cba 2014-07-03  120: end
38ec946cba 2014-07-03  121: 
38ec946cba 2014-07-03  122: while continue do
38ec946cba 2014-07-03  123: 	ngx.location.capture('/sleep')
38ec946cba 2014-07-03  124: 
38ec946cba 2014-07-03  125: 	local data
38ec946cba 2014-07-03  126: 	data, err = red:hgetall('stat_counter_pending_tmp')
38ec946cba 2014-07-03  127: 	if not data then
38ec946cba 2014-07-03  128: 		ngx.log(ngx.ERR, 'redis request failed: ', err)
38ec946cba 2014-07-03  129: 		ngx.exit(500)
38ec946cba 2014-07-03  130: 	end
38ec946cba 2014-07-03  131: 
38ec946cba 2014-07-03  132: 	for name, value in pairs(decode_bulk(data)) do
38ec946cba 2014-07-03  133: 		local fields = {}
38ec946cba 2014-07-03  134: 		name:gsub("[^_]+", function(c) fields[#fields + 1] = c end)
38ec946cba 2014-07-03  135: 		fields[#fields + 1] = value
38ec946cba 2014-07-03  136: 		local result = ngx.location.capture('/postgres', {
38ec946cba 2014-07-03  137: 			method = ngx.HTTP_PUT,
38ec946cba 2014-07-03  138: 			-- prepare select? XXX
38ec946cba 2014-07-03  139: 			body = "select merge_counter('" .. fields[1] .. "'::text, '" .. fields[2] .. "'::text, '" .. fields[3] .. "'::inet, '" .. fields[4] .. "'::smallint);"
38ec946cba 2014-07-03  140: 		})
38ec946cba 2014-07-03  141: 		if result.status ~= 200 or not result.body then
38ec946cba 2014-07-03  142: 			ngx.log(ngx.ERR, 'postgres access failed')
38ec946cba 2014-07-03  143: 			ngx.exit(500)
38ec946cba 2014-07-03  144: 		end
38ec946cba 2014-07-03  145: 	end
38ec946cba 2014-07-03  146: 
38ec946cba 2014-07-03  147: 	red:init_pipeline(5)
38ec946cba 2014-07-03  148: 	red:multi()
38ec946cba 2014-07-03  149: 	red:del('stat_counter_pending_tmp')
38ec946cba 2014-07-03  150: 	red:exists('stat_counter_pending')
38ec946cba 2014-07-03  151: 	red:renamenx('stat_counter_pending', 'stat_counter_pending_tmp')
38ec946cba 2014-07-03  152: 	red:exec()
38ec946cba 2014-07-03  153: 	renamed, err = red:commit_pipeline()
38ec946cba 2014-07-03  154: 	if not renamed then
38ec946cba 2014-07-03  155: 		ngx.log(ngx.ERR, 'redis multi failed: ', err)
38ec946cba 2014-07-03  156: 		ngx.exit(500)
38ec946cba 2014-07-03  157: 	end
38ec946cba 2014-07-03  158: 
38ec946cba 2014-07-03  159: 	if tonumber(renamed[5][1] == 0) or tonumber(renamed[5][2]) == 0 then
38ec946cba 2014-07-03  160: 		continue = false
38ec946cba 2014-07-03  161: 	end
38ec946cba 2014-07-03  162: end