This commit is contained in:
Jonas Bengtsson
2026-09-19 18:08:02 +02:00
parent a16a01b1e7
commit 680ad7a624
14 changed files with 483 additions and 14 deletions
+21
View File
@@ -115,6 +115,21 @@ def _signal_reload() -> None:
raise _Error(500, f"mosquitto_signal failed: {proc.stderr.strip()}")
def _restart_broker() -> None:
"""Gracefully stop the broker; Docker's restart policy revives it.
The broker is PID 1 in the shared PID namespace. SIGTERM makes it
shut down cleanly (persistence saved); `restart: unless-stopped`
on the mosquitto service then starts the container again. This
sidecar is a separate container and survives, so it can report
status while the broker is down (spec section 29: restart broker
where explicitly supported — no Docker socket involved).
"""
# The HTTP response MUST be flushed before PID 1 dies, so the kill
# happens after the handler returns — orchestrated by the route.
os.kill(1, signal.SIGTERM)
def _broker_pid_alive() -> bool:
try:
# Broker is PID 1 in the shared PID namespace.
@@ -215,6 +230,12 @@ class Handler(BaseHTTPRequestHandler):
try:
if self.path == "/deploy":
self._handle_deploy()
elif self.path == "/restart":
# Acknowledge BEFORE the broker dies: the response must
# reach the client first, then the process is signaled
# in a daemon thread so the handler completes cleanly.
self._send(200, {"status": "restarting"})
threading.Thread(target=_restart_broker, daemon=True).start()
elif self.path == "/reload":
_signal_reload()
self._send(200, {"status": "reloading", "broker_healthy": _post_broker_health()})