Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fetchEvents doesn't handle offline relays correctly #306

Open
chakany opened this issue Feb 11, 2025 · 3 comments
Open

fetchEvents doesn't handle offline relays correctly #306

chakany opened this issue Feb 11, 2025 · 3 comments

Comments

@chakany
Copy link
Member

chakany commented Feb 11, 2025

Incident

i've noticed that when using ndk's fetchEvents, if one of the explicit relay urls (eg, kitchen.zap.cooking) is offline, the fetch call hangs and an error message is logged to console. meanwhile, using subscribe works fine, even with the offline relay.

Details

testing with two configs:

  • config 1. both relays online
    • fetchEvents returns events as expected.
  • config 2: one relay (kitchen.zap.cooking) offline
    • fetchEvents hangs and errors out, but subscribe successfully receives events.

interestingly, when testing in node.js, there is no error message outputted even when wrapping in a try/catch. on node, the only error message is outputted if DEBUG='ndk:*'
this behavior is the opposite on the web, even if the localStorage debug variable is blank, an error message is outputted after ~30 seconds.

How to reproduce

This is the node.js example i wrote. if the offline relay is set, it will hang. if it is commented out however, it works just fine.

fetchEvents example

const ndk = require("@nostr-dev-kit/ndk");
const WebSocket = require('ws');

global.WebSocket = WebSocket;

const nostr = new ndk.default({
  explicitRelayUrls: ["wss://relay.nostr.band",
    "wss://relay.google.com" // the "offline relay"
  ],
});

(async () => {
  try {
    await nostr.connect();
    console.log("connected");
    const sub = await nostr.fetchEvents({ kinds: [1] });
    console.log(sub);
  } catch (error) {
    console.error(error);
  }
})()

subscribe example

const ndk = require("@nostr-dev-kit/ndk");
const WebSocket = require('ws');

global.WebSocket = WebSocket;

const nostr = new ndk.default({
  explicitRelayUrls: ["wss://relay.nostr.band",
    "wss://relay.google.com" // the "offline relay"
  ],
});

(async () => {
  try {
    await nostr.connect();
    console.log("connected");
    const sub = nostr.subscribe({ kinds: [1] });
    sub.on("event", (event) => {
      console.log(`${event.content}`);
    });
  } catch (error) {
    console.error(error);
  }
})()

my guess is that fetchEvents isn't handling timeouts or errors correctly based on the console error behavior.

@chakany
Copy link
Member Author

chakany commented Feb 11, 2025

looking at these 3 lines:

ndk/ndk/src/ndk/index.ts

Lines 705 to 707 in fdbe6e5

relaySetSubscription.on("eose", () => {
resolve(new Set(events.values()));
});

maybe the problem is that a subscription will only send back an eose if it receives events from all relays whether they are connected or not. since it never recieves an eose from an offline relay, maybe thats why it never resolves.

@digitalbase
Copy link

I've been dealing with the same issues. I think #266 might be related.

3 days ago @pablof7z added this commit 05d16e1 which I wonder might be related.

Someone suggested that I add a timeout promise wrapper around fetchEvents with to catch this but that feels like a dirty fix.

Hope to spend time on this in the next days once I'm done with some other tasks

@chakany
Copy link
Member Author

chakany commented Mar 18, 2025

The fix that I used was to just replace all fetchEvents with regular subscriptions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants