fix(ops): self-restart/stop of the host bridge returns 200 (detached)
Restarting/stopping legal-court-fetch-service from its own /pm2/control kills the process before it can reply — the client got a misleading 502 even though pm2 performed the restart. Detach the self-action (sleep 1; pm2 ...) so the HTTP response flushes first, and report success optimistically. Other targets are unchanged. Own name via COURT_FETCH_SERVICE_PM2_NAME (default legal-court-fetch-service). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,10 @@ async def pm2_status(request: web.Request) -> web.Response:
|
|||||||
# Whitelisted to ``legal-`` names only — never paperclip or arbitrary processes.
|
# Whitelisted to ``legal-`` names only — never paperclip or arbitrary processes.
|
||||||
_PM2_ACTIONS = {"restart", "stop", "start"}
|
_PM2_ACTIONS = {"restart", "stop", "start"}
|
||||||
|
|
||||||
|
# Our own pm2 process name. Restarting/stopping ourselves kills this process
|
||||||
|
# mid-reply, so those self-actions are detached (see pm2_control).
|
||||||
|
_OWN_PM2_NAME = os.environ.get("COURT_FETCH_SERVICE_PM2_NAME", "legal-court-fetch-service")
|
||||||
|
|
||||||
|
|
||||||
async def pm2_control(request: web.Request) -> web.Response:
|
async def pm2_control(request: web.Request) -> web.Response:
|
||||||
"""Run ``pm2 <action> <name>`` for a whitelisted legal-* process."""
|
"""Run ``pm2 <action> <name>`` for a whitelisted legal-* process."""
|
||||||
@@ -143,6 +147,18 @@ async def pm2_control(request: web.Request) -> web.Response:
|
|||||||
{"error": "name must be a legal-* process"}, status=403
|
{"error": "name must be a legal-* process"}, status=403
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Self restart/stop kills this process before it can reply (client sees a
|
||||||
|
# dropped connection / 502) even though pm2 does perform the action. Detach
|
||||||
|
# it with a brief delay so the HTTP response flushes first, then report
|
||||||
|
# success optimistically.
|
||||||
|
if name == _OWN_PM2_NAME and action in ("restart", "stop"):
|
||||||
|
import asyncio as _asyncio
|
||||||
|
|
||||||
|
await _asyncio.create_subprocess_shell(f"sleep 1; pm2 {action} {name} --silent")
|
||||||
|
return web.json_response(
|
||||||
|
{"ok": True, "action": action, "deferred": True, "service": None}
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
rc, out, err = await _pm2_run(action, name, "--silent", timeout=30)
|
rc, out, err = await _pm2_run(action, name, "--silent", timeout=30)
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
|
|||||||
Reference in New Issue
Block a user