mod_inotify_reload/mod_inotify_reload.lua
author Matthew Wild <mwild1@gmail.com>
Fri, 23 Sep 2022 22:41:15 +0100
changeset 5058 62480053c87b
parent 744 ab988e98a9f9
child 5399 82207f936f1f
permissions -rw-r--r--
mod_cloud_notify_encrypted: Additional debug logging when enabling/skipping
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
652
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
-- mod_inotify_reload
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
-- Reloads modules when their files change
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
-- Depends on linotify: https://github.com/hoelzro/linotify
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
module:set_global();
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
local inotify = require "inotify";
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
local modulemanager = require "core.modulemanager";
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
local inh = inotify.init();
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
local watches = {};
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
local watch_ids = {};
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
-- Fake socket object around inotify
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
local inh_conn = {
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
	getfd = function () return inh:fileno(); end;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
	dirty = function (self) return false; end;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
	settimeout = function () end;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
	send = function (_, d) return #d, 0; end;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
	close = function () end;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
	receive = function ()
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
		local events = inh:read();
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
		for _, event in ipairs(events) do
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
			local mod = watches[watch_ids[event.wd]];
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
			if mod then
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
				local host, name = mod.host, mod.name;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
				module:log("debug", "Reloading changed module mod_%s on %s", name, host);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
				modulemanager.reload(host, name);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
			else
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
				module:log("warn", "no watch for %d", event.wd);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
			end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
		end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
		return "";
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
	end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
};
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
require "net.server".wrapclient(inh_conn, "inotify", inh:fileno(), {
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
	onincoming = function () end, ondisconnect = function () end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
}, "*a");
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
function watch_module(name, host, path)
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
	local id, err = inh:addwatch(path, inotify.IN_CLOSE_WRITE);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
	if not id then return nil, err; end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
	local k = host.."\0"..name;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    45
	watches[k] = { id = id, path = path, name = name, host = host };
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
	watch_ids[id] = k;
744
ab988e98a9f9 mod_inotify_reload: Add debug logging
Matthew Wild <mwild1@gmail.com>
parents: 652
diff changeset
    47
	module:log("debug", "Watching %s:%s with id %d", name, host, id);
652
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
	return true;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
function unwatch_module(name, host)
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
	local k = host.."\0"..name;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
	if not watches[k] then
744
ab988e98a9f9 mod_inotify_reload: Add debug logging
Matthew Wild <mwild1@gmail.com>
parents: 652
diff changeset
    54
		module:log("warn", "Not watching %s:%s", name, host);
652
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
		return nil, "not-watching";
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
	end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
	local id = watches[k].id;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
	local ok, err = inh:rmwatch(id);
744
ab988e98a9f9 mod_inotify_reload: Add debug logging
Matthew Wild <mwild1@gmail.com>
parents: 652
diff changeset
    59
	module:log("info", "Removed watch %d", id);
652
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
	watches[k] = nil;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
	watch_ids[id] = nil;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
	return ok, err;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
function module_loaded(event)
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
	local host, name = event.host, event.module;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
	local path = modulemanager.get_module(host, name).module.path;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
	if not path then
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
		module:log("warn", "Couldn't watch mod_%s, no path", name);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
		return;
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
	end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
	if watch_module(name, host, path) then
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
		module:log("debug", "Watching mod_%s", name);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
	end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    76
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    77
function module_unloaded(event)
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
	unwatch_module(event.module, event.host);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    81
function module.add_host(module)
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    82
	module:hook("module-loaded", module_loaded);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    83
	module:hook("module-unloaded", module_unloaded);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    84
end
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    85
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    86
module:hook("module-loaded", module_loaded);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    87
module:hook("module-unloaded", module_unloaded);
3e6f43ab7e22 mod_inotify_reload: Reload modules when their code changes
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88