centrifugal / centrifugo

Scalable real-time messaging server in a language-agnostic way. Self-hosted alternative to Pubnub, Pusher, Ably. Set up once and forever.
https://centrifugal.dev
Apache License 2.0
8.44k stars 598 forks source link

[question] resubscribe to same channel #891

Closed plopezlpz closed 1 month ago

plopezlpz commented 1 month ago

I'd like to subscribe or unsubscribe to channels, but I can see that this is not really possible.

I have a svelte component when navigating to a page I want to subscribe to the updates on that ID, when I navigate out I want to unsubscribe, since I no longer need those:

$effect(() => {
    const channel = 'a-' + myid;
    const sub = this.client.newSubscription(channel, {
            minResubscribeDelay: 0,
        maxResubscribeDelay: 0,
            recoverable: true
        });
        sub.on('publication', function (ctx) {
            console.log('OK: ', ctx);
        }).on('subscribing', function (ctx) {
            console.log(`subscribing: ${ctx.code}, ${ctx.reason}`);
        }).on('subscribed', function (ctx) {
            console.log('subscribed', ctx);
        }).on('unsubscribed', function (ctx) {
            console.log(`unsubscribed: ${ctx.code}, ${ctx.reason}`);
        }).subscribe();
    return () => {
        sub?.unsubscribe();
    };
});

So on loading the page I get subscribed correctly to say channel a-123 then I get this when calling unsubscribe(): unsubscribed: 0, unsubscribe called

If I navigate back to the page I want to resubscribe, I get this error:

Uncaught Error: Subscription to the channel a-123 already exists
    at Centrifuge.newSubscription (centrifuge.js?v=7bc2ce3e:1975:13)

I'm not sure if this is somehow possible or desirable.

versions:

JS client: centrifuge: 5.2.2 node: 5.4.5

FZambia commented 1 month ago

@plopezlpz hello,

newSubscription adds the subscription to channel to the SDK's internal registry. Duplicate call of newSubscription with the same channel results into error you've shown.

To solve this you should not only call unsubscribe, but also removeSubscription method. See common description all Centrifugo SDKs try to follow: https://centrifugal.dev/docs/transports/client_api#subscription-management

Alternatively, you may keep newSubscription outside of the component, calling it only once, then when component opens – call subscribe, on navigating out - just call unsubscribe. In this case though subscription will stay in the internal registry after component finished.

Internal registry's goal is to automatically manage resubscribes to channels on reconnect.

plopezlpz commented 1 month ago

thanks a lot @FZambia, working now just calling unsubscribe and subscribe withouth the call to newSubscription