38ec946cba 2014-07-03 arcade@b1t.na: -- module counter - counts some junk
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: local today = os.date('*t')
38ec946cba 2014-07-03 arcade@b1t.na: local timestamp = os.time{year = today['year'], month = today['month'], day = today['day']}
38ec946cba 2014-07-03 arcade@b1t.na: local referer = '-';
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: if ngx.var.http_referer ~= nil then
38ec946cba 2014-07-03 arcade@b1t.na: _, _, referer = string.find(ngx.var.http_referer, '^https?://([%w%.]+)')
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: local key = 'stat_counter_' .. timestamp .. '_' .. referer
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: -- connect to redis
38ec946cba 2014-07-03 arcade@b1t.na: local redis = require 'resty.redis'
38ec946cba 2014-07-03 arcade@b1t.na: local red = redis:new()
38ec946cba 2014-07-03 arcade@b1t.na: local ok, err = red:connect('127.0.0.1', 6379)
38ec946cba 2014-07-03 arcade@b1t.na: if not ok then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'redis connection failed: ', err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: local cjson = require 'cjson'
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: -- decodes values from array into dict
38ec946cba 2014-07-03 arcade@b1t.na: function decode_bulk(reply)
38ec946cba 2014-07-03 arcade@b1t.na: local data = {}
38ec946cba 2014-07-03 arcade@b1t.na: for j=1, #reply, 2 do
38ec946cba 2014-07-03 arcade@b1t.na: data[reply[j] ] = reply[j+1]
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: return(data)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: local data, empty
38ec946cba 2014-07-03 arcade@b1t.na: empty, err = red:hsetnx(key, 'today', 0)
38ec946cba 2014-07-03 arcade@b1t.na: if not empty then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'redis query failed: ', err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: if empty == 0 then
38ec946cba 2014-07-03 arcade@b1t.na: data, err = red:hgetall(key)
38ec946cba 2014-07-03 arcade@b1t.na: if not data then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'redis query failed: ', err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: if empty == 1 or data.whole == nil then
38ec946cba 2014-07-03 arcade@b1t.na: -- postgres fallback
38ec946cba 2014-07-03 arcade@b1t.na: result = ngx.location.capture('/postgres', {
38ec946cba 2014-07-03 arcade@b1t.na: method = ngx.HTTP_PUT,
38ec946cba 2014-07-03 arcade@b1t.na: body = "select * from get_stats('" .. referer .. "') as (today int, lastday int, week bigint, whole bigint);"
38ec946cba 2014-07-03 arcade@b1t.na: })
38ec946cba 2014-07-03 arcade@b1t.na: if result.status ~= 200 or not result.body then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'postgres access failed')
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: else
38ec946cba 2014-07-03 arcade@b1t.na: local unrds = require "rds.parser"
38ec946cba 2014-07-03 arcade@b1t.na: local res, err = unrds.parse(result.body)
38ec946cba 2014-07-03 arcade@b1t.na: if res == nil then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'failed to obtain data: ' .. err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: else
38ec946cba 2014-07-03 arcade@b1t.na: data = res.resultset[1]
38ec946cba 2014-07-03 arcade@b1t.na: local req = {key}
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: for name, value in pairs(data) do
38ec946cba 2014-07-03 arcade@b1t.na: if value == unrds.null then
38ec946cba 2014-07-03 arcade@b1t.na: value = 0
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: if name ~= 'today' then
38ec946cba 2014-07-03 arcade@b1t.na: table.insert(req, name)
38ec946cba 2014-07-03 arcade@b1t.na: table.insert(req, value)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: red:init_pipeline(3)
38ec946cba 2014-07-03 arcade@b1t.na: red:hmset{req}
38ec946cba 2014-07-03 arcade@b1t.na: red:expire(key, 129600)
38ec946cba 2014-07-03 arcade@b1t.na: red:hincrby(key, 'today', data.today)
38ec946cba 2014-07-03 arcade@b1t.na: res, err = red:commit_pipeline()
38ec946cba 2014-07-03 arcade@b1t.na: if not res then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'redis pipeline failed: ', err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: data.today = data.today + 1
38ec946cba 2014-07-03 arcade@b1t.na: ngx.say(cjson.encode(data))
38ec946cba 2014-07-03 arcade@b1t.na: ngx.eof()
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: res, err = red:hincrby(key, 'today', 1)
38ec946cba 2014-07-03 arcade@b1t.na: local uid = ''
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: if ngx.var.uid_got ~= nil and string.find(ngx.var.uid_got, 'uid=') == 1 then
38ec946cba 2014-07-03 arcade@b1t.na: uid = string.sub(ngx.var.uid_got, 5)
38ec946cba 2014-07-03 arcade@b1t.na: elseif ngx.var.uid_set ~= nil and string.find(ngx.var.uid_set, 'uid=') == 1 then
38ec946cba 2014-07-03 arcade@b1t.na: uid = string.sub(ngx.var.uid_set, 5)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: local hit_key = uid .. '_' .. referer .. '_' .. ngx.var.remote_addr
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: red:init_pipeline(5)
38ec946cba 2014-07-03 arcade@b1t.na: red:multi()
38ec946cba 2014-07-03 arcade@b1t.na: red:hincrby('stat_counter_pending', hit_key, 1)
38ec946cba 2014-07-03 arcade@b1t.na: red:expire('stat_counter_pending', 60)
38ec946cba 2014-07-03 arcade@b1t.na: red:renamenx('stat_counter_pending', 'stat_counter_pending_tmp')
38ec946cba 2014-07-03 arcade@b1t.na: red:exec()
38ec946cba 2014-07-03 arcade@b1t.na: renamed, err = red:commit_pipeline()
38ec946cba 2014-07-03 arcade@b1t.na: if not renamed then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'redis multi failed: ', err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: local continue = false
38ec946cba 2014-07-03 arcade@b1t.na: if tonumber(renamed[5][3]) == 1 then
38ec946cba 2014-07-03 arcade@b1t.na: continue = true
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: while continue do
38ec946cba 2014-07-03 arcade@b1t.na: ngx.location.capture('/sleep')
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: local data
38ec946cba 2014-07-03 arcade@b1t.na: data, err = red:hgetall('stat_counter_pending_tmp')
38ec946cba 2014-07-03 arcade@b1t.na: if not data then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'redis request failed: ', err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: for name, value in pairs(decode_bulk(data)) do
38ec946cba 2014-07-03 arcade@b1t.na: local fields = {}
38ec946cba 2014-07-03 arcade@b1t.na: name:gsub("[^_]+", function(c) fields[#fields + 1] = c end)
38ec946cba 2014-07-03 arcade@b1t.na: fields[#fields + 1] = value
38ec946cba 2014-07-03 arcade@b1t.na: local result = ngx.location.capture('/postgres', {
38ec946cba 2014-07-03 arcade@b1t.na: method = ngx.HTTP_PUT,
38ec946cba 2014-07-03 arcade@b1t.na: -- prepare select? XXX
38ec946cba 2014-07-03 arcade@b1t.na: body = "select merge_counter('" .. fields[1] .. "'::text, '" .. fields[2] .. "'::text, '" .. fields[3] .. "'::inet, '" .. fields[4] .. "'::smallint);"
38ec946cba 2014-07-03 arcade@b1t.na: })
38ec946cba 2014-07-03 arcade@b1t.na: if result.status ~= 200 or not result.body then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'postgres access failed')
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: red:init_pipeline(5)
38ec946cba 2014-07-03 arcade@b1t.na: red:multi()
38ec946cba 2014-07-03 arcade@b1t.na: red:del('stat_counter_pending_tmp')
38ec946cba 2014-07-03 arcade@b1t.na: red:exists('stat_counter_pending')
38ec946cba 2014-07-03 arcade@b1t.na: red:renamenx('stat_counter_pending', 'stat_counter_pending_tmp')
38ec946cba 2014-07-03 arcade@b1t.na: red:exec()
38ec946cba 2014-07-03 arcade@b1t.na: renamed, err = red:commit_pipeline()
38ec946cba 2014-07-03 arcade@b1t.na: if not renamed then
38ec946cba 2014-07-03 arcade@b1t.na: ngx.log(ngx.ERR, 'redis multi failed: ', err)
38ec946cba 2014-07-03 arcade@b1t.na: ngx.exit(500)
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na:
38ec946cba 2014-07-03 arcade@b1t.na: if tonumber(renamed[5][1] == 0) or tonumber(renamed[5][2]) == 0 then
38ec946cba 2014-07-03 arcade@b1t.na: continue = false
38ec946cba 2014-07-03 arcade@b1t.na: end
38ec946cba 2014-07-03 arcade@b1t.na: end