perf: reduce 5A chunk timeout to 10s and stop iteration at requested event index
Two improvements to eliminate the ~2-min-per-event wait and unnecessary
full-event-list download when only one event is requested:
1. protocol.py: pass timeout=10.0 to _recv_one in the 5A chunk loop.
Device responds within ~1s per chunk; 10s gives a safe 10x buffer.
End-of-stream detection (raw_bytes=1) now fires in 10s instead of 120s,
cutting ~110s of dead wait per event.
2. client.py: add stop_after_index parameter to get_events(). When set,
iteration stops immediately after the target event is collected — no
further 0A/1E/0C/5A/1F cycles for events the caller doesn't need.
3. server.py: pass stop_after_index=index to both /device/event/{idx}
and /device/event/{idx}/waveform endpoints so a single-event request
only downloads that one event.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+10
-1
@@ -228,7 +228,7 @@ class MiniMateClient:
|
|||||||
log.info("count_events: %d event(s) found via 1E/1F chain", count)
|
log.info("count_events: %d event(s) found via 1E/1F chain", count)
|
||||||
return count
|
return count
|
||||||
|
|
||||||
def get_events(self, full_waveform: bool = False, debug: bool = False) -> list[Event]:
|
def get_events(self, full_waveform: bool = False, debug: bool = False, stop_after_index: Optional[int] = None) -> list[Event]:
|
||||||
"""
|
"""
|
||||||
Download all stored events from the device using the confirmed
|
Download all stored events from the device using the confirmed
|
||||||
1E → 0A → 0C → 5A → 1F event-iterator protocol.
|
1E → 0A → 0C → 5A → 1F event-iterator protocol.
|
||||||
@@ -439,6 +439,15 @@ class MiniMateClient:
|
|||||||
events.append(ev)
|
events.append(ev)
|
||||||
idx += 1
|
idx += 1
|
||||||
|
|
||||||
|
# Early exit: if the caller only wants events up to a specific
|
||||||
|
# index, stop iterating once we've collected it.
|
||||||
|
if stop_after_index is not None and idx > stop_after_index:
|
||||||
|
log.info(
|
||||||
|
"get_events: reached stop_after_index=%d — stopping early",
|
||||||
|
stop_after_index,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Partial/failed record — skip 5A, just advance with 1F.
|
# Partial/failed record — skip 5A, just advance with 1F.
|
||||||
log.info(
|
log.info(
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ class MiniMateProtocol:
|
|||||||
self._send(build_5a_frame(_BULK_CHUNK_OFFSET, params))
|
self._send(build_5a_frame(_BULK_CHUNK_OFFSET, params))
|
||||||
self._parser.reset() # reset bytes_fed for accurate per-chunk count
|
self._parser.reset() # reset bytes_fed for accurate per-chunk count
|
||||||
try:
|
try:
|
||||||
rsp = self._recv_one(expected_sub=rsp_sub, reset_parser=False)
|
rsp = self._recv_one(expected_sub=rsp_sub, reset_parser=False, timeout=10.0)
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
raw = self._parser.bytes_fed
|
raw = self._parser.bytes_fed
|
||||||
log.warning(
|
log.warning(
|
||||||
|
|||||||
+3
-4
@@ -380,7 +380,7 @@ def device_event(
|
|||||||
def _do():
|
def _do():
|
||||||
with _build_client(port, baud, host, tcp_port) as client:
|
with _build_client(port, baud, host, tcp_port) as client:
|
||||||
client.connect()
|
client.connect()
|
||||||
return client.get_events()
|
return client.get_events(stop_after_index=index)
|
||||||
events = _run_with_retry(_do, is_tcp=_is_tcp(host))
|
events = _run_with_retry(_do, is_tcp=_is_tcp(host))
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
@@ -433,9 +433,8 @@ def device_event_waveform(
|
|||||||
def _do():
|
def _do():
|
||||||
with _build_client(port, baud, host, tcp_port, timeout=120.0) as client:
|
with _build_client(port, baud, host, tcp_port, timeout=120.0) as client:
|
||||||
info = client.connect()
|
info = client.connect()
|
||||||
# full_waveform=True fetches the complete 5A stream inside the
|
# stop_after_index avoids downloading events beyond the one requested.
|
||||||
# 1E→0A→0C→5A→1F loop. Issuing a second 5A after 1F times out.
|
events = client.get_events(full_waveform=True, stop_after_index=index)
|
||||||
events = client.get_events(full_waveform=True)
|
|
||||||
matching = [ev for ev in events if ev.index == index]
|
matching = [ev for ev in events if ev.index == index]
|
||||||
return matching[0] if matching else None, info
|
return matching[0] if matching else None, info
|
||||||
ev, info = _run_with_retry(_do, is_tcp=_is_tcp(host))
|
ev, info = _run_with_retry(_do, is_tcp=_is_tcp(host))
|
||||||
|
|||||||
Reference in New Issue
Block a user