Software /
code /
prosody
Comparison
plugins/mod_cron.lua @ 11986:3d5135e8a2a7
mod_cron: Initial commit of periodic task runner
A number of modules now have periodic tasks that need to run, e.g. for
cleaning out old messages or files. This has highlighted a need for
coordinating and optimizing scheduling of such tasks.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 21 Nov 2021 15:50:36 +0100 |
child | 11995:bbd3ac65640d |
comparison
equal
deleted
inserted
replaced
11985:3740cf7a66a3 | 11986:3d5135e8a2a7 |
---|---|
1 module:set_global(); | |
2 | |
3 local async = require("util.async"); | |
4 | |
5 local periods = { hourly = 3600; daily = 86400 } | |
6 | |
7 local active_hosts = {} | |
8 | |
9 function module.add_host(host_module) | |
10 | |
11 local last_run_times = host_module:open_store("cron", "map"); | |
12 active_hosts[host_module.host] = true; | |
13 | |
14 local function save_task(task, started_at) last_run_times:set(nil, task.id, started_at); end | |
15 | |
16 local function task_added(event) | |
17 local task = event.item; | |
18 if task.name == nil then task.name = task.when; end | |
19 if task.id == nil then task.id = event.source.name .. "/" .. task.name:gsub("%W", "_"):lower(); end | |
20 if task.last == nil then task.last = last_run_times:get(nil, task.id); end | |
21 task.save = save_task; | |
22 module:log("debug", "%s task %s added, last run %s", task.when, task.id, | |
23 task.last and require("util.datetime").datetime(task.last) or "never"); | |
24 return true | |
25 end | |
26 | |
27 local function task_removed(event) | |
28 local task = event.item; | |
29 host_module:log("debug", "Task %s removed", task.id); | |
30 return true | |
31 end | |
32 | |
33 host_module:handle_items("task", task_added, task_removed, true); | |
34 | |
35 function host_module.unload() active_hosts[host_module.host] = nil; end | |
36 end | |
37 | |
38 local function should_run(when, last) return not last or last + periods[when] <= os.time() end | |
39 | |
40 local function run_task(task) | |
41 local started_at = os.time(); | |
42 task:run(started_at); | |
43 task:save(started_at); | |
44 end | |
45 | |
46 local task_runner = async.runner(run_task); | |
47 module:add_timer(1, function() | |
48 module:log("info", "Running periodic tasks"); | |
49 local delay = 3600; | |
50 for host in pairs(active_hosts) do | |
51 module:log("debug", "Running periodic tasks for host %s", host); | |
52 for _, task in ipairs(module:context(host):get_host_items("task")) do | |
53 module:log("debug", "Considering %s task %s (%s)", task.when, task.id, task.run); | |
54 if should_run(task.when, task.last) then task_runner:run(task); end | |
55 end | |
56 end | |
57 module:log("debug", "Wait %ds", delay); | |
58 return delay | |
59 end); |