Skip to content

Commit 18c0107

Browse files
shbatmclaude
andcommitted
docs(ws): trim duplicated SYNCING rationale, note first-frame assumption
Collapse the replay/SYNCING explanation that was restated in the module constant comment and the websocket() inline comment down to the canonical _promote_when_quiet docstring, and document that the quiet window is anchored to socket-open (the known first-frame-latency limitation, matching pyisyox). No behaviour change. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 041ce95 commit 18c0107

1 file changed

Lines changed: 11 additions & 10 deletions

File tree

pyisy/events/websocket.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,8 @@
5252
WS_MAX_RETRIES = 4
5353
WS_RETRY_BACKOFF: list[float] = [0.01, 1, 10, 30, 60] # Seconds
5454

55-
# After the socket opens the controller replays every node's current
56-
# status as a burst of ST/DON/DOF frames. The stream is held in
57-
# ES_SYNCING until that burst goes quiet for WS_SYNC_QUIET_SECONDS (no
58-
# frame), then flips to ES_CONNECTED. WS_SYNC_MAX_SECONDS is a hard cap
59-
# so a perpetually chatty controller can never stall the stream in
60-
# ES_SYNCING. Module-level so tests can monkeypatch them small.
55+
# Quiet-window / hard-cap timings for the post-connect SYNCING gate (see
56+
# _promote_when_quiet). Module-level so tests can monkeypatch them small.
6157
WS_SYNC_QUIET_SECONDS: float = 1.0
6258
WS_SYNC_MAX_SECONDS: float = 10.0
6359

@@ -282,6 +278,12 @@ async def _promote_when_quiet(self) -> None:
282278
chatty controller still goes live. Cancelled by ``websocket``'s
283279
``finally`` if the socket drops first, so a connection that never
284280
settles never reports ES_CONNECTED.
281+
282+
The window is anchored to socket-open, not to the first replayed
283+
frame: the gate assumes the replay begins within the first quiet
284+
window (true in practice — IoX serves it from cache on the
285+
subscribe round-trip). A pathologically delayed first frame is the
286+
known limitation, accepted to keep the silent-controller path fast.
285287
"""
286288
deadline = self._loop.time() + WS_SYNC_MAX_SECONDS
287289
seen = self._frame_count
@@ -308,10 +310,9 @@ async def websocket(self, retries: int = 0) -> None:
308310
) as ws:
309311
retries = 0
310312
_LOGGER.debug("Successfully connected to websocket.")
311-
# Socket is open, but the controller now replays every
312-
# node's current status. Hold ES_SYNCING (not ES_CONNECTED)
313-
# until that burst drains so consumers don't fire on the
314-
# replay; the watcher promotes once it goes quiet (#512).
313+
# Hold ES_SYNCING through the controller's post-connect status
314+
# replay so consumers don't fire on it; watcher promotes once
315+
# quiet (#512).
315316
self._frame_count = 0
316317
self.status = ES_SYNCING
317318
self._sync_task = self._loop.create_task(self._promote_when_quiet())

0 commit comments

Comments
 (0)