Skip to content

Unthrottled reconnect loop against relays that answer every connection with a NOTICE #720

Description

@grunch

Split out of the review on #712, where it was found while verifying that PR's shouldReconnectToRelayOnNotice: false change.

Problem

shouldReconnectToRelayOnNotice is a dead parameter in the pinned dart_nostr fork (anasfik/nostr ref ca07ddd, pubspec.yaml:37-40). It is threaded through a dozen function signatures and never read in any condition — no if (shouldReconnectToRelayOnNotice) exists anywhere in the library. _handleNoticeFromRelay (lib/nostr/instance/relays/relays.dart:1048-1094) closes and reconnects unconditionally:

if (nostrRegistry.isRelayRegistered(relay)) {
  registeredRelay?.sink.close().then((value) {
    final relayUnregistered = nostrRegistry.unregisterRelay(relay);
    _reconnectToRelay(relayUnregistered: relayUnregistered, relay: relay, ...);
  });
}

_reconnectToRelay has no backoff, so a relay that greets every connection with a NOTICE puts the app in a tight reconnect loop.

Impact

Roughly 127 WebSocket handshakes per second against a single relay, with no throttling at all. The trigger is any relay that sends a NOTICE on every connection — which is what relays doing auth-required or persistent rate-limiting do. Not the common case, but when it happens the app burns far more than the periodic recovery work #712 targets, and it happens on main today.

Reproduction

Point dart_nostr directly (no app) at a local relay on ws://127.0.0.1:7788 that answers every connection with ["NOTICE","rate-limited: slow down"], with both socket-level retries off, so any reconnection can only come from the notice handler:

shouldReconnectToRelayOnNotice: false,
retryOnClose: false,
retryOnError: false,

Connections the server accepts in ~10 seconds:

flag connections
false 1273
true 1926

Same order of magnitude either way — the difference is machine load, not the flag. The behavior is identical with the flag on or off, which is what confirms it is dead.

Fix

Belongs in the fork: either honor the flag in _handleNoticeFromRelay, or at minimum add backoff to _reconnectToRelay.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions