Title: Nostr relay service retries unreachable relays with no backoff, exhausting the ESP32 thread pool and breaking other apps' networking · Issue #191 · MicroPythonOS/MicroPythonOS · GitHub
Open Graph Title: Nostr relay service retries unreachable relays with no backoff, exhausting the ESP32 thread pool and breaking other apps' networking · Issue #191 · MicroPythonOS/MicroPythonOS
X Title: Nostr relay service retries unreachable relays with no backoff, exhausting the ESP32 thread pool and breaking other apps' networking · Issue #191 · MicroPythonOS/MicroPythonOS
Description: Summary The background Nostr service (com.micropythonos.nostr, nostr_boot_service) retries unreachable relays with no backoff. On a Fri3d 2024 badge this drained the ESP32-S3 thread pool and broke other apps' networking — The Free Lanter...
Open Graph Description: Summary The background Nostr service (com.micropythonos.nostr, nostr_boot_service) retries unreachable relays with no backoff. On a Fri3d 2024 badge this drained the ESP32-S3 thread pool and broke ...
X Description: Summary The background Nostr service (com.micropythonos.nostr, nostr_boot_service) retries unreachable relays with no backoff. On a Fri3d 2024 badge this drained the ESP32-S3 thread pool and broke ...
Opengraph URL: https://github.com/MicroPythonOS/MicroPythonOS/issues/191
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Nostr relay service retries unreachable relays with no backoff, exhausting the ESP32 thread pool and breaking other apps' networking","articleBody":"## Summary\n\nThe background Nostr service (`com.micropythonos.nostr`, `nostr_boot_service`) retries unreachable relays with no backoff. On a Fri3d 2024 badge this drained the ESP32-S3 thread pool and broke **other apps' networking** — The Free Lantern Player could not fetch fragments during playback and the audio broke up badly.\n\n## What happens\n\nThe service connects to three relays that are currently failing:\n\n```\nERROR:nostr.relay:relay error wss://relay.damus.io: b'HTTP/1.1 522 '\nERROR:uaiowebsocket:_async_main's await self._connect_and_run() for wss://relay.primal.net got exception: -113\nERROR:uaiowebsocket:_async_main's await self._connect_and_run() for wss://relay.0xchat.com got exception: -113\n```\n\nIt reconnects immediately and continuously. Each connection attempt resolves the relay host via `async_dns.getaddrinfo_async`, which spawns a `_thread` per lookup. With no backoff, the retries spawn resolver threads faster than the small ESP32-S3 pool allows, and it exhausts:\n\n```\nWARNING:notification_manager:Failed to play notification sound: can't create thread\n...\nFile \"mpos/net/async_dns.py\", line 106, in getaddrinfo_async\nOSError: can't create thread\nTFLPlayer prefetch error (retrying): can't create thread\nERROR:nostr.relay:relay error wss://relay.damus.io: can't create thread\n```\n\nAt that point `_thread.start_new_thread` fails everywhere on the device (I confirmed a bare `_thread.start_new_thread` from the REPL also raised `can't create thread`). Disabling the Nostr boot service made the pool healthy again and TFL streamed smoothly.\n\n## Root cause / two fixes\n\n1. **DNS re-resolution per attempt** (the thread-exhaustion trigger). A DNS cache in `async_dns` removes this: retries reuse the cached relay IP instead of spawning a resolver thread each time. Submitted as #189 — it makes the retries pure-async and stops the thread starvation for Nostr and any other repeat-lookup workload.\n\n2. **No relay backoff** (the remaining waste). Even with the DNS cache, the service still hammers unreachable relays as fast as it can, wasting CPU and network. It should back off on failed connections (e.g. exponential backoff per relay, capped), so a set of down relays does not spin the event loop.\n\nFix #1 (via #189) stops it from breaking other apps; fix #2 is the proper behavior for the service itself.\n\n## Environment\n\n- Fri3d 2024 badge, MicroPythonOS reporting BuildInfo 0.14.2 (flashed via the web flasher labelled \"1.0.4\").\n","author":{"url":"https://github.com/jnuyens","@type":"Person","name":"jnuyens"},"datePublished":"2026-07-09T20:14:55.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/191/MicroPythonOS/issues/191"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:d56e4ad5-a05d-b917-4758-34e9623ec21d |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A8AE:2BA38A:5731B3:751B34:6A5346D4 |
| html-safe-nonce | ee55d4b2c5a85cdbf15c3ba97b44f363039424f651ef84aee11fbbdff1ac675b |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBOEFFOjJCQTM4QTo1NzMxQjM6NzUxQjM0OjZBNTM0NkQ0IiwidmlzaXRvcl9pZCI6IjM4NzM0MzM3NzY4NTMwNDI5MDAiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | d598da8b6a85f3e8ae979fca04ed59865a9daacd5ed00e0034f82f94e8b69822 |
| hovercard-subject-tag | issue:4849579624 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/MicroPythonOS/MicroPythonOS/191/issue_layout |
| twitter:image | https://opengraph.githubassets.com/67c83ab982249087750f089f92be51fcde6a638ded42805bf551b426ff2e0750/MicroPythonOS/MicroPythonOS/issues/191 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/67c83ab982249087750f089f92be51fcde6a638ded42805bf551b426ff2e0750/MicroPythonOS/MicroPythonOS/issues/191 |
| og:image:alt | Summary The background Nostr service (com.micropythonos.nostr, nostr_boot_service) retries unreachable relays with no backoff. On a Fri3d 2024 badge this drained the ESP32-S3 thread pool and broke ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | jnuyens |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| go-import | github.com/MicroPythonOS/MicroPythonOS git https://github.com/MicroPythonOS/MicroPythonOS.git |
| octolytics-dimension-user_id | 213598128 |
| octolytics-dimension-user_login | MicroPythonOS |
| octolytics-dimension-repository_id | 975472483 |
| octolytics-dimension-repository_nwo | MicroPythonOS/MicroPythonOS |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 975472483 |
| octolytics-dimension-repository_network_root_nwo | MicroPythonOS/MicroPythonOS |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 07a982c1d40157c619b364352b704c3ce66bb332 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width