mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-05-02 19:52:14 +02:00
Replace the _route_tasks set in PacketRouter with a simple integer counter (_in_flight / _max_in_flight=30) and add an early-drop guard in _process_queue. Problems solved: 1. No cap on concurrent sleeping tasks: burst arrivals (multi-hop amplification, collision retries) could stack unbounded _route_packet tasks, each holding a packet closure and asyncio Task overhead, before the duty-cycle gate fired. 2. _route_tasks set held a strong reference to every Task object for the full duration of its sleep — unnecessary in Python 3.12+ where the event loop already holds tasks alive. 3. stop() iterated the full set to cancel tasks on shutdown — O(n) where n is the in-flight count at shutdown time. Fix: _in_flight counter increments before create_task and decrements in the _on_route_done callback. The cap check (>= 30) in _process_queue is a last-resort safety valve — LoRa airtime and the duty-cycle gate keep _in_flight in the low single digits under normal load. Also lower companion dedup prune threshold from 1000 to 200: the original 1000 allowed stale entries to accumulate for hundreds of PATH packets before the O(n) dict comprehension sweep ran. Trade-off documented: explicit task cancellation on shutdown is removed; tasks are cancelled implicitly by event loop shutdown with identical outcome (no packet transmits after the radio is closed regardless). Docs: docs/pr_in_flight_cap.md — full problem analysis, alternative approaches (semaphore, keep set + add cap), proof of counter sufficiency, rationale for cap=30, and unit + field test plan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>