Handling bad relays in relay_manager.py
vikbtc opened this issue · 6 comments
When posting to multiple relays, sometimes there are failures like the below:
2023-02-09 11:09:12 Start posting to 16 relays
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Handshake status 500 Internal Server Error - goodbye
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:12 Websocket connected
2023-02-09 11:09:13 Websocket connected
2023-02-09 11:09:17 Error posting to nostr
Traceback (most recent call last):
File "/home/zz/ooo/util_nostr.py", line 71, in _post
relay_manager.publish_event(event)
File "/home/zz/.local/share/virtualenvs/ooo-gj3JA2ic/lib/python3.10/site-packages/nostr/relay_manager.py", line 63, in publish_event
self.publish_message(event.to_message())
File "/home/zz/.local/share/virtualenvs/ooo-gj3JA2ic/lib/python3.10/site-packages/nostr/relay_manager.py", line 53, in publish_message
relay.publish(message)
File "/home/zz/.local/share/virtualenvs/ooo-gj3JA2ic/lib/python3.10/site-packages/nostr/relay.py", line 47, in publish
self.ws.send(message)
File "/home/zz/.local/share/virtualenvs/ooo-gj3JA2ic/lib/python3.10/site-packages/websocket/_app.py", line 240, in send
raise WebSocketConnectionClosedException(
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.
- Is it possible to add better logging to tell which relays connected and which failed?
- In case of one bad relay, I would still like to be able to continue posting to the rest without an exception being thrown.
Thanks
i was just about to open an issue for this. This piece of code takes care of sending, and errors out incase the connection goes boom
It's located in /nostr/relay_manager.py
, line 50.
def publish_message(self, message: str):
for relay in self.relays.values():
if relay.policy.should_write:
relay.publish(message)
- We can wrap it in a
try: except:
statement, and popping the bad relay from the list - Or perhaps add a configurable setting to simply ignore the exception and continue
I was hitting this as well. The websocket-client library even has a FAQ for this: https://websocket-client.readthedocs.io/en/latest/faq.html#how-to-solve-the-connection-is-already-closed-error
I patched this library to wrap the call with try: except WebSocketConnectionClosedException:
and it solved the problem. Code has been running for many days now with no issues.
I am running into the same problem. Hopefully I can fix. Where is your patch?
Can we merge a fix for this into the main? When a relay goes down, this makes the program really unstable, if this fix is not integrated.
i was just about to open an issue for this. This piece of code takes care of sending, and errors out incase the connection goes boom
It's located in
/nostr/relay_manager.py
, line 50.def publish_message(self, message: str): for relay in self.relays.values(): if relay.policy.should_write: relay.publish(message)
- We can wrap it in a
try: except:
statement, and popping the bad relay from the list- Or perhaps add a configurable setting to simply ignore the exception and continue
Here's what I did with your try-except, PSA for anyone trying to fix this, the try-except must be implemented in this library, not within your own program otherwise if your first relay is bad your post won't post at all.
def publish_message(self, message: str) -> dict:
from websocket import WebSocketConnectionClosedException
post_stats = {}
for relay in self.relays.values():
if relay.policy.should_write:
try:
relay.publish(message)
post_stats[relay.url] = True
except WebSocketConnectionClosedException:
post_stats[relay.url] = False
print(f"Disconnected from {relay.url} couldn't post to this relay.")
pass
return post_stats
def publish_event(self, event: Event):
""" Verifies that the Event is publishable before submitting it to relays """
if event.signature is None:
raise RelayException(f"Could not publish {event.id}: must be signed")
if not event.verify():
raise RelayException(f"Could not publish {event.id}: failed to verify signature {event.signature}")
return self.publish_message(event.to_message())
Noting that publish_event
now needs to return publish_message
In this case, publish event now says which relay fails, and it returns a dictionary of which relays it posted to and which it didn't.
Disconnected from wss://nostr-pub.wellorder.net couldn't post to this relay.
{'wss://nostr-pub.wellorder.net': False, 'wss://nostr.mutinywallet.com': True, 'wss://relay.snort.social': True, 'wss://nostr.wine': True, 'wss://nos.lol': True, 'wss://relay.damus.io': True}