Software /
code /
prosody-modules
Changeset
2170:4652a112a4ba
mod_graceful_shutdown: Experiment in improving the shutdown experience
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 05 May 2016 15:43:01 +0200 |
parents | 2169:9fa588babbba |
children | 2171:85d88ed4f2a2 |
files | mod_graceful_shutdown/README.markdown mod_graceful_shutdown/mod_graceful_shutdown.lua |
diffstat | 2 files changed, 68 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_graceful_shutdown/README.markdown Thu May 05 15:43:01 2016 +0200 @@ -0,0 +1,26 @@ +This module is an experiment about a more graceful shutdown process. + +Why +=== + +When shutting down, a number of sessions, connections and other things +are teared down. Due to all these things happening very quickly, +sometimes eg client unavailable notifications don't make it to all +remote contacts because the server-to-server connections are teared down +just after. + +How +=== + +This module works by breaking the shutdown process into separate steps +with a brief pause between them. + +It goes something like this + +1. Stop accepting new client connections. +2. Close all client connections. +3. Fire event for everything else. +4. Tell `net.server` to quit the main loop. +5. ??? +6. Still here? Kill itself. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_graceful_shutdown/mod_graceful_shutdown.lua Thu May 05 15:43:01 2016 +0200 @@ -0,0 +1,42 @@ +-- luacheck: ignore 122/prosody 113/prosody + +local timer = require "util.timer"; +local portman = require "core.portmanager"; +local server = require "net.server"; + +module:set_global(); +local orig_shutdown = prosody.shutdown; + +local pause = module:get_option_number("shutdown_pause", 1); + +function module.unload() + prosody.shutdown = orig_shutdown; +end + +prosody.shutdown = coroutine.wrap(function (reason, code) + prosody.shutdown_reason = reason; + prosody.shutdown_code = code; + timer.add_task(pause, prosody.shutdown); + coroutine.yield(true, "shutdown initiated"); + -- Close c2s ports, stop accepting new connections + portman.deactivate("c2s"); + -- Close all c2s sessions + for _, sess in pairs(prosody.full_sessions) do + sess:close{ condition = "system-shutdown", text = reason } + end + -- Wait for notifications to be sent + coroutine.yield(pause); + -- Event for everything else to shut down + prosody.events.fire_event("server-stopping", { + reason = reason; + code = code; + }); + -- And wait + coroutine.yield(pause); + -- And stop main event loop + server.setquitting(true); + -- And wait for death + coroutine.yield(pause * 3); + -- you came back? die zombie! + os.exit(1); +end);