fix: residual inter-request pacing instead of blind full-interval sleep

pace() slept the entire rate-limit interval every call regardless of how
much of it had already elapsed since the last real send (e.g. spent
processing the previous block's response). Track the last send timestamp
and only sleep the remainder, recovering time already spent between
requests without changing the enforced minimum interval.

Verified against 10.0.0.129/10.0.0.254: multi-block /device/0 fetches
still complete cleanly, faster per sweep, with the same request spacing
guarantee (patch and measurement from QuiteYellow, PR #8 review).
This commit is contained in:
Marc Billow
2026-07-05 16:51:17 -05:00
parent 27480dcb1d
commit ff688f5d5d
+7 -2
View File
@@ -113,10 +113,14 @@ class DtlsCoapSession:
self._stop = threading.Event()
self._reader_thread = None
self._last_send_ts = 0.0
def pace(self) -> None:
"""Sleep one rate-limit interval. Uses _stop so session teardown wakes it."""
self._stop.wait(self._min_req_interval)
"""Sleep only the part of the rate-limit interval not already consumed
since the last real send. Uses _stop so session teardown wakes it."""
remaining = self._min_req_interval - (time.monotonic() - self._last_send_ts)
if remaining > 0:
self._stop.wait(remaining)
# ---- lifecycle ---------------------------------------------------
@@ -273,6 +277,7 @@ class DtlsCoapSession:
raise ConnectionError("DTLS session closed")
try:
self.conn.send(datagram)
self._last_send_ts = time.monotonic()
while True:
o = self.conn.bio_read(65535)
if not o: