mod_websocket: Fire pre-session-close event (fixes #1800)
This event was added in a7c183bb4e64 and is required to make mod_smacks know
that a session was intentionally closed and shouldn't be hibernated (see
fcea4d9e7502).
Because this was missing from mod_websocket's session.close(), mod_smacks
would always attempt to hibernate websocket sessions even if they closed
cleanly.
That mod_websocket has its own copy of session.close() is something to fix
another day (probably not in the stable branch). So for now this commit makes
the minimal change to get things working again.
Thanks to Damian and the Jitsi team for reporting.
module:set_global();
local async = require("util.async");
local datetime = require("util.datetime");
local periods = { hourly = 3600; daily = 86400; weekly = 7 * 86400 }
local active_hosts = {}
function module.add_host(host_module)
local last_run_times = host_module:open_store("cron", "map");
active_hosts[host_module.host] = true;
local function save_task(task, started_at) last_run_times:set(nil, task.id, started_at); end
local function task_added(event)
local task = event.item;
if task.name == nil then task.name = task.when; end
if task.id == nil then task.id = event.source.name .. "/" .. task.name:gsub("%W", "_"):lower(); end
if task.last == nil then task.last = last_run_times:get(nil, task.id); end
task.save = save_task;
module:log("debug", "%s task %s added, last run %s", task.when, task.id,
task.last and datetime.datetime(task.last) or "never");
if task.last == nil then
local now = os.time();
task.last = now - now % periods[task.when];
end
return true
end
local function task_removed(event)
local task = event.item;
host_module:log("debug", "Task %s removed", task.id);
return true
end
host_module:handle_items("task", task_added, task_removed, true);
function host_module.unload() active_hosts[host_module.host] = nil; end
end
local function should_run(when, last) return not last or last + periods[when] * 0.995 <= os.time() end
local function run_task(task)
local started_at = os.time();
task:run(started_at);
task.last = started_at;
task:save(started_at);
end
local task_runner = async.runner(run_task);
scheduled = module:add_timer(1, function()
module:log("info", "Running periodic tasks");
local delay = 3600;
for host in pairs(active_hosts) do
module:log("debug", "Running periodic tasks for host %s", host);
for _, task in ipairs(module:context(host):get_host_items("task")) do
module:log("debug", "Considering %s task %s (%s)", task.when, task.id, task.run);
if should_run(task.when, task.last) then task_runner:run(task); end
end
end
module:log("debug", "Wait %ds", delay);
return delay
end);