chore(vp): per-minute MQTT status-push counter for idle-disconnect triage (#1548 follow-up)

The 1 Hz status push was silent at INFO, so support bundles couldn't show
  whether the push task was actually reaching a specific slicer connection.
  Now ``_periodic_status_push`` emits one line per minute per connected
  slicer ("1Hz status push: N pushes/min to <client>") and stays silent when
  no slicer is attached. No behaviour change to the push itself — counters
  are local to the task and reset every 60 ticks.

  Motivated by the open follow-up on #1548: keepalive parser shipped (b6636053)
  and the symptom moved 60 s → 90 s, but OrcaSlicer still disconnects on idle.
  This adds the missing observability so the reporter's next support bundle
  shows whether our outbound 1 Hz push is alive for the disconnecting
  connection.
This commit is contained in:
maziggy
2026-05-30 14:47:06 +02:00
parent f6f6f92e38
commit 4ffefa60f4
2 changed files with 24 additions and 0 deletions
@@ -399,9 +399,19 @@ class SimpleMQTTServer:
async def _periodic_status_push(self) -> None:
"""Send periodic status updates to all connected clients (1 Hz, exact pre-bridge behaviour)."""
logger.info("Starting periodic status push task")
# Per-client push counters reset every 60 ticks. Lets us confirm from
# logs whether the 1Hz push is actually reaching a specific slicer
# connection (#1548 keepalive follow-up: keepalive parser shipped but
# OrcaSlicer still disconnects on idle, and the periodic push is
# otherwise silent at INFO level so it can't be observed in the
# support bundle). One log line per minute per active connection —
# nothing when no slicer is attached.
push_counts: dict[str, int] = {}
ticks_since_summary = 0
while self._running:
try:
await asyncio.sleep(1) # Push every 1 second like real printers
ticks_since_summary += 1
disconnected = []
for client_id, writer in list(self._clients.items()):
@@ -411,6 +421,7 @@ class SimpleMQTTServer:
continue
serial = self._client_serials.get(client_id, self.serial)
await self._send_status_report(writer, serial=serial)
push_counts[client_id] = push_counts.get(client_id, 0) + 1
except OSError as e:
logger.debug("Failed to push status to %s: %s", client_id, e)
disconnected.append(client_id)
@@ -419,6 +430,18 @@ class SimpleMQTTServer:
for client_id in disconnected:
self._clients.pop(client_id, None)
self._client_serials.pop(client_id, None)
push_counts.pop(client_id, None)
if ticks_since_summary >= 60:
for cid, count in push_counts.items():
logger.info(
"%s1Hz status push: %d pushes/min to %s",
self._log_prefix,
count,
cid,
)
push_counts.clear()
ticks_since_summary = 0
except asyncio.CancelledError:
break