fix(nostr): exponential reconnect backoff so unreachable relays stop exhausting the thread pool (#191) - #201
Merged
ThomasFarstrike merged 1 commit intoJul 14, 2026
Conversation
…exhausting the thread pool (MicroPythonOS#191)
Contributor
|
Oh that's very cool! Thanks for adding a unit test too - the more, the merrier! ;-) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix #2 for #191. Builds on the reconnect rework already merged to
main.What #191 asked for
The Nostr relay service retried unreachable relays with no backoff. Each attempt resolves DNS and spawns a
_thread, and the ESP32-S3 pool is tiny, so hammering a dead relay starved other apps' networking (this is what broke audio playback in The Free Lantern Player). The DNS cache (#189) was fix #1; this is fix #2.What was still wrong on
mainmainalready normalisesreconnect_intervaland gates on_network_available(), which handles the "Wi-Fi fully down" case. But two gaps remained when Wi-Fi is up and a specific relay is unreachable or flapping:_connect_and_run()returns without raising, so theexceptbranch (with itssleep) never runs. Thewhile self.running:loop reconnects with zero delay and hammers.reconnect_interval(3s) forever, so a permanently dead relay keeps retrying every 3s.The fix
Exponential backoff in
_async_main, seeded fromreconnect_interval:connected_oktracks whether the just-ended session was actually live: reset the delay to the seed interval after a live close, otherwise double it toward a 300s ceiling. An unreachable relay backs off (3s -> 6 -> 12 -> ... -> 300) instead of spinning; a healthy relay that blips recovers fast.The backoff math is a pure helper (
_next_backoff) so it is unit-testable without a network.reconnect_interval <= 0still disables reconnect, and_network_available()gating is unchanged.Scope is exactly the Nostr relay service:
WebSocketAppis only used bynostr/relay.py(nostr app + NWC both go through it).Testing
tests/test_uaiowebsocket_backoff.py: 5/5 pass on the desktop build (./tests/unittest.sh tests/test_uaiowebsocket_backoff.py), network-free. Covers geometric growth, the 300s cap, reset-on-live-connection, and a custom seed interval as the floor.mpy-crosscompiles clean; ASCII-only, MicroPython-compatible.