fetchEvents doesn't handle offline relays correctly
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.
looking at these 3 lines: https://github.com/nostr-dev-kit/ndk/blob/fdbe6e5934c431318f1f210fa9f797f40b53326c/ndk/src/ndk/index.ts#L705-L707
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.
I've been dealing with the same issues. I think https://github.com/nostr-dev-kit/ndk/issues/266 might be related.
3 days ago @pablof7z added this commit https://github.com/nostr-dev-kit/ndk/commit/05d16e1ce1c1cee8daf33fbb65f944a08d773633 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
The fix that I used was to just replace all fetchEvents with regular subscriptions