Mercurial > prosody-modules
changeset 652:3e6f43ab7e22
mod_inotify_reload: Reload modules when their code changes
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sun, 29 Apr 2012 16:57:21 +0100 |
parents | 78a23a7dc613 |
children | c08b0e4b7b38 |
files | mod_inotify_reload/mod_inotify_reload.lua |
diffstat | 1 files changed, 85 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_inotify_reload/mod_inotify_reload.lua Sun Apr 29 16:57:21 2012 +0100 @@ -0,0 +1,85 @@ +-- mod_inotify_reload +-- Reloads modules when their files change +-- Depends on linotify: https://github.com/hoelzro/linotify + +module:set_global(); + +local inotify = require "inotify"; +local modulemanager = require "core.modulemanager"; + +local inh = inotify.init(); + +local watches = {}; +local watch_ids = {}; + +-- Fake socket object around inotify +local inh_conn = { + getfd = function () return inh:fileno(); end; + dirty = function (self) return false; end; + settimeout = function () end; + send = function (_, d) return #d, 0; end; + close = function () end; + receive = function () + local events = inh:read(); + for _, event in ipairs(events) do + local mod = watches[watch_ids[event.wd]]; + if mod then + local host, name = mod.host, mod.name; + module:log("debug", "Reloading changed module mod_%s on %s", name, host); + modulemanager.reload(host, name); + else + module:log("warn", "no watch for %d", event.wd); + end + end + return ""; + end +}; +require "net.server".wrapclient(inh_conn, "inotify", inh:fileno(), { + onincoming = function () end, ondisconnect = function () end +}, "*a"); + +function watch_module(name, host, path) + local id, err = inh:addwatch(path, inotify.IN_CLOSE_WRITE); + if not id then return nil, err; end + local k = host.."\0"..name; + watches[k] = { id = id, path = path, name = name, host = host }; + watch_ids[id] = k; + return true; +end + +function unwatch_module(name, host) + local k = host.."\0"..name; + if not watches[k] then + return nil, "not-watching"; + end + local id = watches[k].id; + local ok, err = inh:rmwatch(id); + watches[k] = nil; + watch_ids[id] = nil; + return ok, err; +end + +function module_loaded(event) + local host, name = event.host, event.module; + local path = modulemanager.get_module(host, name).module.path; + if not path then + module:log("warn", "Couldn't watch mod_%s, no path", name); + return; + end + if watch_module(name, host, path) then + module:log("debug", "Watching mod_%s", name); + end +end + +function module_unloaded(event) + unwatch_module(event.module, event.host); +end + +function module.add_host(module) + module:hook("module-loaded", module_loaded); + module:hook("module-unloaded", module_unloaded); +end + +module:hook("module-loaded", module_loaded); +module:hook("module-unloaded", module_unloaded); +