plugins/mod_cron.lua
author Kim Alvefur <zash@zash.se>
Wed, 27 Mar 2024 19:33:11 +0100
changeset 13471 c2a476f4712a
parent 13447 98a6ec4ce140
permissions -rw-r--r--
util.startup: Fix exiting on pidfile trouble prosody.shutdown() relies on prosody.main_thread, which has not been set yet at this point. Doing a clean shutdown might actually be harmful in case it tears down things set up by the conflicting Prosody, such as the very pidfile we were looking at. Thanks again SigmaTel71 for noticing
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
module:set_global();
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12493
diff changeset
     3
local async = require("prosody.util.async");
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
13425
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
     5
local cron_initial_delay = module:get_option_number("cron_initial_delay", 1);
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
     6
local cron_check_delay = module:get_option_number("cron_check_delay", 3600);
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
     7
local cron_spread_factor = module:get_option_number("cron_spread_factor", 0);
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
     8
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
local active_hosts = {}
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    10
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    11
function module.add_host(host_module)
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    12
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    13
	local last_run_times = host_module:open_store("cron", "map");
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    14
	active_hosts[host_module.host] = true;
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    15
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    16
	local function save_task(task, started_at) last_run_times:set(nil, task.id, started_at); end
13269
6ac5ad578565 mod_cron: Load last task run time inside task runner to fix async
Kim Alvefur <zash@zash.se>
parents: 13268
diff changeset
    17
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    18
	local function restore_task(task) if task.last == nil then task.last = last_run_times:get(nil, task.id); end end
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    19
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    20
	local function task_added(event)
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    21
		local task = event.item;
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    22
		if task.name == nil then task.name = task.when; end
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    23
		if task.id == nil then task.id = event.source.name .. "/" .. task.name:gsub("%W", "_"):lower(); end
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    24
		task.period = host_module:get_option_period(task.id:gsub("/", "_") .. "_period", "1" .. task.when, 60, 86400 * 7 * 53);
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    25
		task.restore = restore_task;
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    26
		task.save = save_task;
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    27
		module:log("debug", "%s task %s added", task.when, task.id);
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    28
		return true
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    29
	end
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    30
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    31
	local function task_removed(event)
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    32
		local task = event.item;
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    33
		host_module:log("debug", "Task %s removed", task.id);
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    34
		return true
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    35
	end
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    36
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    37
	host_module:handle_items("task", task_added, task_removed, true);
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    38
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    39
	function host_module.unload() active_hosts[host_module.host] = nil; end
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    40
end
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    41
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    42
local function should_run(task, last) return not last or last + task.period * 0.995 <= os.time() end
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    43
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    44
local function run_task(task)
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    45
	task:restore();
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    46
	if not should_run(task, task.last) then return end
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    47
	local started_at = os.time();
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    48
	task:run(started_at);
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    49
	task.last = started_at;
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    50
	task:save(started_at);
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    51
end
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    52
13425
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
    53
local function spread(t, factor)
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
    54
	return t * (1 - factor + 2*factor*math.random());
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
    55
end
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
    56
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    57
local task_runner = async.runner(run_task);
13425
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
    58
scheduled = module:add_timer(cron_initial_delay, function()
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    59
	module:log("info", "Running periodic tasks");
13425
92301fa7a673 mod_cron: Allow configuring various "internal" delay parameters
Matthew Wild <mwild1@gmail.com>
parents: 13375
diff changeset
    60
	local delay = spread(cron_check_delay, cron_spread_factor);
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    61
	for host in pairs(active_hosts) do
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    62
		module:log("debug", "Running periodic tasks for host %s", host);
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    63
		for _, task in ipairs(module:context(host):get_host_items("task")) do task_runner:run(task); end
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    64
	end
13447
98a6ec4ce140 mod_cron: Fix log format to account for float that was integer before
Kim Alvefur <zash@zash.se>
parents: 13425
diff changeset
    65
	module:log("debug", "Wait %gs", delay);
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    66
	return delay
11990
3d5135e8a2a7 mod_cron: Initial commit of periodic task runner
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    67
end);
13368
6f9b15757384 mod_cron: Add shell command to list registered cron tasks with status
Matthew Wild <mwild1@gmail.com>
parents: 13288
diff changeset
    68
6f9b15757384 mod_cron: Add shell command to list registered cron tasks with status
Matthew Wild <mwild1@gmail.com>
parents: 13288
diff changeset
    69
module:add_item("shell-command", {
13375
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    70
	section = "cron";
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    71
	section_desc = "View and manage recurring tasks";
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    72
	name = "tasks";
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    73
	desc = "View registered tasks";
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    74
	args = {};
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    75
	handler = function(self, filter_host)
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    76
		local format_table = require("prosody.util.human.io").table;
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    77
		local it = require("util.iterators");
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    78
		local row = format_table({
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    79
			{ title = "Host"; width = "2p" };
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    80
			{ title = "Task"; width = "3p" };
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    81
			{ title = "Desc"; width = "3p" };
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    82
			{ title = "When"; width = "1p" };
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    83
			{ title = "Last run"; width = "20" };
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    84
		}, self.session.width);
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    85
		local print = self.session.print;
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    86
		print(row());
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    87
		for host in it.sorted_pairs(filter_host and { [filter_host] = true } or active_hosts) do
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    88
			for _, task in ipairs(module:context(host):get_host_items("task")) do
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    89
				print(row({ host; task.id; task.name; task.when; task.last and os.date("%Y-%m-%d %R:%S", task.last) or "never" }));
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    90
			end
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    91
		end
a22e3a980178 mod_cron: Rebuild with new LuaFormatter settings (tabs!)
Kim Alvefur <zash@zash.se>
parents: 13370
diff changeset
    92
	end;
13368
6f9b15757384 mod_cron: Add shell command to list registered cron tasks with status
Matthew Wild <mwild1@gmail.com>
parents: 13288
diff changeset
    93
});