fix: reconnect after silent control heartbeat loss

This commit is contained in:
2026-07-27 02:45:21 +00:00
parent 4ba5e92248
commit 1a06da3984
7 changed files with 70 additions and 6 deletions
+18 -1
View File
@@ -11,6 +11,7 @@ from pathlib import Path, PurePosixPath
from typing import Any
from websockets.asyncio.client import connect
from websockets.exceptions import ConnectionClosedOK
from archive_clients.backup import SQLiteBackupManager
from archive_clients.config import ClientConfig
@@ -205,7 +206,23 @@ class ArchiveClientDaemon:
command_tasks: set[asyncio.Task[None]] = set()
try:
await self._resume_commands(outbound, command_tasks)
async for frame in websocket:
# A proxy can leave the TCP/WebSocket socket apparently open
# after the control server has discarded its session. The
# server then cannot deliver durable commands and its pending
# outbox remains stranded unless the client independently
# detects the missing application heartbeats and reconnects.
while True:
try:
frame = await asyncio.wait_for(
websocket.recv(),
self.config.connection.offline_timeout,
)
except ConnectionClosedOK:
return
except asyncio.TimeoutError as exc:
raise RuntimeError(
"control heartbeat timed out"
) from exc
await self._handle(decode(frame), outbound, command_tasks)
finally:
writer.cancel()