fix(gateway): preserve systemd handoff recovery

This commit is contained in:
fangliquan
2026-08-22 07:51:54 +08:00
committed by kshitij
parent 5b024c7ccc
commit 91fb175188
4 changed files with 146 additions and 9 deletions
+21
View File
@@ -1,4 +1,5 @@
import asyncio
import subprocess
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
@@ -147,6 +148,26 @@ async def test_gateway_stop_settles_completion_batch_before_adapter_disconnect()
assert runner._completion_notification_batch_flush_tasks == set()
@pytest.mark.asyncio
async def test_planned_service_exit_issues_no_restart_of_its_own(monkeypatch):
runner, adapter = make_restart_runner()
adapter.disconnect = AsyncMock()
runner._restart_requested = True
runner._restart_via_service = True
monkeypatch.setattr(
subprocess,
"Popen",
lambda *args, **kwargs: pytest.fail(
f"planned service exit must not spawn a restart helper: {args}"
),
)
with patch("gateway.status.remove_pid_file"), patch("gateway.status.write_runtime_status"):
await runner.stop()
assert runner._exit_code == GATEWAY_SERVICE_RESTART_EXIT_CODE
@pytest.mark.asyncio
async def test_in_chat_restart_skips_home_shutdown_even_with_active_session():
runner, adapter = make_restart_runner()
+75
View File
@@ -756,6 +756,81 @@ class TestGatewaySystemServiceRouting:
assert "21627" not in out # must use the mocked budget, not live defaults
assert "27" in out
def test_systemd_restart_forces_recovery_only_when_handoff_has_no_replacement(
self, monkeypatch, capsys
):
calls = []
monkeypatch.setattr(gateway_cli, "_select_systemd_scope", lambda system=False: False)
monkeypatch.setattr(gateway_cli, "_require_service_installed", lambda action, system=False: None)
monkeypatch.setattr(gateway_cli, "_preflight_user_systemd", lambda **kwargs: None)
monkeypatch.setattr(gateway_cli, "refresh_systemd_unit_if_needed", lambda system=False: None)
monkeypatch.setattr(gateway_cli, "_get_restart_exit_wait_budget", lambda: 27.0)
monkeypatch.setattr("gateway.status.get_running_pid", lambda: 654)
monkeypatch.setattr(gateway_cli, "_graceful_restart_via_sigusr1", lambda pid, timeout: True)
waits = iter((False, True))
monkeypatch.setattr(
gateway_cli,
"_wait_for_systemd_service_restart",
lambda system=False, previous_pid=None: next(waits),
)
monkeypatch.setattr(gateway_cli, "_systemd_service_is_start_limited", lambda system=False: False)
monkeypatch.setattr(
gateway_cli,
"_read_systemd_unit_properties",
lambda system=False, properties=None: {"ActiveState": "inactive", "MainPID": "0"},
)
monkeypatch.setattr(
gateway_cli,
"_run_systemctl",
lambda args, **kwargs: calls.append((args, kwargs))
or SimpleNamespace(returncode=0, stdout="", stderr=""),
)
gateway_cli.systemd_restart()
assert [call[0][0] for call in calls] == ["reset-failed", "restart"]
assert "did not relaunch" in capsys.readouterr().out
def test_systemd_restart_does_not_force_an_unready_replacement(self, monkeypatch):
calls = []
monkeypatch.setattr(gateway_cli, "_select_systemd_scope", lambda system=False: False)
monkeypatch.setattr(gateway_cli, "_require_service_installed", lambda action, system=False: None)
monkeypatch.setattr(gateway_cli, "_preflight_user_systemd", lambda **kwargs: None)
monkeypatch.setattr(gateway_cli, "refresh_systemd_unit_if_needed", lambda system=False: None)
monkeypatch.setattr(gateway_cli, "_get_restart_exit_wait_budget", lambda: 27.0)
monkeypatch.setattr("gateway.status.get_running_pid", lambda: 654)
monkeypatch.setattr(gateway_cli, "_graceful_restart_via_sigusr1", lambda pid, timeout: True)
monkeypatch.setattr(
gateway_cli,
"_wait_for_systemd_service_restart",
lambda system=False, previous_pid=None: False,
)
monkeypatch.setattr(gateway_cli, "_systemd_service_is_start_limited", lambda system=False: False)
monkeypatch.setattr(
gateway_cli,
"_read_systemd_unit_properties",
lambda system=False, properties=None: {"ActiveState": "active", "MainPID": "777"},
)
monkeypatch.setattr(gateway_cli, "_run_systemctl", lambda args, **kwargs: calls.append(args))
gateway_cli.systemd_restart()
assert calls == []
def test_systemd_restart_wait_timeout_includes_supervisor_budgets(self, monkeypatch):
monkeypatch.setattr(
gateway_cli,
"_read_systemd_unit_properties",
lambda system=False, properties=None: {
"RestartUSec": "5s",
"TimeoutStartUSec": "1min 30s",
},
)
assert gateway_cli._systemd_restart_wait_timeout() == 155.0