rust-nostr/nostr

Reliably receiving past and future events without duplication

xeruf opened this issue · 13 comments

Is there a way to atomically subscribe to new events and obtain past events matching a certain filter thus that you can be sure not to have missed an event, but also not to receive duplicates?

While we are at it, is there a way to create a subscription that does not receive events submitted by self?
I can use Filter::remove_authors(), but that would exclude events sent by other programs logged into the same user. Or do I have to manually filter on the client-side, probably with one of those database methods?

And I am a bit confused about auto-closing and dropping subscriptions - do I need to call client.unsubscribe_all before ending my program or is that implicit on exit? I see no implementation of Drop so I am a bit dumbstruck.
Also, are the subscriptions in client only for the current instance of Client or do they somehow come from the relay and are shared between instances?

I thought about using Filters::new().since to minimize duplication, but for my application it is totally valid for somebody to sent an event dated in the past, and I still would want to receive that.

Ah I think I got the answer to the original question: client.subscribe receives old events too.

But Filter::remove_authors wasn't what I thought, so it seems I have to manually filter out, which unfortunately might incur unnecessary traffic.

do I need to call client.unsubscribe_all before ending my program or is that implicit on exit?

No, when websocket connection is closed, the subscriptions are automatically dropped by the relay

Ah I think I got the answer to the original question: client.subscribe receives old events too.

Yeah, that depends by the filters you set.

While we are at it, is there a way to create a subscription that does not receive events submitted by self?

Yes if using RelayPoolNotification::Event variant.

To avoid to receive event duplicates you can subscribe and listen for RelayPoolNotification::Event variant. BUT, the RelayPoolNotification::Event variant is sent only for the first time the event is seen, so if you query the same filters again you'll not receive again that event notification.

client
    .handle_notifications(|notification| async {
        if let RelayPoolNotification::Event { event, .. } = notification {
            // This notification is sent ONLY the first time the event is seen
        }
        Ok(false) // Set to true to exit from the loop
    })
    .await?;

That is what I am already using - but if I run Client::send_event in another thread, I still get a notification from this.
I would ideally like a subscription that returns me all events except the ones I submitted from this program. Are there negative filters? Then I could maybe use a kind of session-tag.

Ah ok, that shouldn't happen (as specified in RelayPoolNotification::Event variant docs). I'm going to publish the fix.

Let me know if you still receive events sent by the SDK

Checking right now, but realized I first need to find out how to migrate from 0.30 - especially how to get tag values as I am doing right now: https://forge.ftt.gmbh/janek/mostr/src/branch/main/src/tasks.rs#L104

What is the point of the Arc there?
A tag can just be cloned easily when needed?

What is the point of the Arc there?

Where?

A tag can just be cloned easily when needed?

Yes, the Tag can be cloned.

See #522

i'm seeing similar issues using 0.33.0. i receive an event notification reliably twice. it appears it comes from two different relays.

loop {
    let (event, relay_url) = match notifications.recv().await {
        Ok(RelayPoolNotification::Event {
            event, relay_url, ..
        }) => (event, relay_url),
        Ok(RelayPoolNotification::Shutdown) => break,
        _ => continue,
    };

    info!(
        "Received event from relay {}: {:?}",
        relay_url,
        event.as_json()
    );
}

this will output a new event at least more than once. this may differ between filters and such, but with my setup, my code is notified twice.

i'm seeing similar issues using 0.33.0. i receive an event notification reliably twice. it appears it comes from two different relays.

loop {
    let (event, relay_url) = match notifications.recv().await {
        Ok(RelayPoolNotification::Event {
            event, relay_url, ..
        }) => (event, relay_url),
        Ok(RelayPoolNotification::Shutdown) => break,
        _ => continue,
    };

    info!(
        "Received event from relay {}: {:?}",
        relay_url,
        event.as_json()
    );
}

this will output a new event at least more than once. this may differ between filters and such, but with my setup, my code is notified twice.

I'll publish v0.34 this week, it'll include the fix for this (commit 5627c40).