Tolerate a restarting server after the native update

The first ping after `herdr update --handoff` was sent exactly once. A
server still binding its socket turned into "更新/热切换未完成" even
though the update had succeeded. Retry connection errors for up to 20
seconds before giving up; a healthy server still answers immediately.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 03:00:09 +00:00
co-authored by Claude Fable 5.1
parent 3f11734ce4
commit 83dc7b5ef9
2 changed files with 51 additions and 1 deletions
+24 -1
View File
@@ -32,6 +32,29 @@ def request(socket_path: str, method: str, params: dict, timeout: float = 10) ->
return result
def ping_when_reachable(socket_path: str, *, timeout: float = 20) -> dict:
"""Ping a server that may still be restarting right after an update.
The native updater can return while the new server is still binding the
socket; a single refused connection must not be reported as a failed
update. The first attempt is immediate so a healthy server adds no delay.
"""
deadline: float | None = None
while True:
try:
return request(socket_path, "ping", {}, timeout=2)
except (OSError, ValueError, RuntimeError) as error:
now = time.monotonic()
if deadline is None:
deadline = now + timeout
elif now >= deadline:
raise RuntimeError(
f"更新后 {timeout:g} 秒内无法连接 Herdr 服务器:{error};"
"请检查 Session 状态,不会自动重启"
) from error
time.sleep(.2)
def installed_version(binary: str) -> str:
version = subprocess.check_output([binary, "--version"], text=True, timeout=10).strip()
if not version.startswith("herdr ") or not version[6:].strip():
@@ -62,7 +85,7 @@ def update_and_handoff(binary: str, session: str) -> None:
# Let the native updater perform its opt-in handoff, scoped to this session.
subprocess.run([binary, "--session", session, "update", "--handoff"], check=True, timeout=300)
version = installed_version(binary)
current = request(socket_path, "ping", {})
current = ping_when_reachable(socket_path)
if current.get("version") != version:
if binary_identity(binary) != identity_before:
raise RuntimeError(