mirror of
https://github.com/pe1hvh/meshcore-gui.git
synced 2026-10-31 01:42:04 +01:00
fix(worker): run repeater poll as cancellable background task WHAT Run _poll_repeaters() as an asyncio.Task instead of awaiting it in _main_loop(). The task is cancelled as soon as has_pending_commands() reports queued work, and a new poll is only started when the queue is empty. RepeaterPoller.poll_due() catches the CancelledError, resets the repeater's _next_due to now and re-raises, so a cancelled poll writes no archive record and is retried on the next tick. Adds SharedData.has_pending_commands() with its SharedDataWriter protocol entry, and REPEATER_POLL_CANCEL_TIMEOUT (default 5.0) to bound the logout cleanup of a cancelled poll. Corrects the comment on REPEATER_POLL_MAX_ATTEMPTS, which still claimed a poll blocks the loop. WHY _main_loop() awaited the poll in the same iteration as process_all(), so a repeater poll blocked command dispatch for its full duration. With the 1.24.2 defaults an unreachable repeater occupies 5 x 30 s login timeout plus 4 x 5 s retry delay, roughly 190 s. A bot reply queued in that window was only transmitted once the poll gave up, and a restart within the window discarded it because the command queue lives in memory. Confirmed in journal meshcore-gui-ttyUSB1.service of 2026-09-06: replies queued at 09:33:46 and 09:35:23 were both sent at 09:36:25, the second the poll ran out of attempts. Statistics collection has no deadline; a bot reply does. Shortening the retry budget would only shorten the window, not remove it. NOTES No breaking changes. has_pending_commands() is additive. Archive schema unchanged, but no record is written for a cancelled poll, so the number of polls per day can be lower than the interval suggests. A repeater on a busy channel may go longer without a measurement — the intended trade-off. Bumps version to 1.24.3.