pubnub / javascript

PubNub JavaScript SDK docs https://www.pubnub.com/docs/sdks/javascript
Other
553 stars 401 forks source link

[Question] Cost Effective migration to SubscriptionSets #389

Closed roman-rr closed 4 months ago

roman-rr commented 4 months ago

Hello Everyone. Please advice a best cost effective way (considering pubnub billing) to using new SubscriptionSet method.

For example, right now we are using such way:

pubnub.subscribe({
    channels: ['channel-1', 'channel-2', 'channel-3', 'channel-4', 'channel-5'],
    withPresence: false
});

pubnub.subscribe({
    channels: ['presence-channel-1', 'presence-channel-2'],
    withPresence: true
});

And then our server-side send to our client-side request to subscribe into channel-6 and unsubscribe from channel-2:

pubnub.subscribe({ channels: ['channel-6'], withPresence: false });
pubnub.unsubscribe({ channels: ['channel-2'] });

But since we have SubscriptionSet, how to implement similar logic?

From my vision, we have to create 2 subscriptionSets:

// Regular set
let regularSubscriptionSet = this.pubnubService.pubnub.subscriptionSet({ 
  channels: ['channel-1', 'channel-2', 'channel-3', 'channel-4', 'channel-5'], 
  subscriptionOptions: { receivePresenceEvents: false },
});

// Presence set
let presenceSubscriptionSet = this.pubnubService.pubnub.subscriptionSet({ 
  channels: ['presence-channel-1', 'presence-channel-2'], 
  subscriptionOptions: { receivePresenceEvents: true },
});

And than, let's imagine we need to subscribe to channel-6 and unsubscribe from channel-2.

What is the best way to do so?

a) Unsubscribe and clean from all sets, and re-create new sets including channel updates.

Will it be cost effective and doesn't reflect a bill? Will there some resource or memory lags?

b) Using subscriptionSet.addSubscription(); and subscriptionSet.removeSubscription();, to update sets.

In this case, how we can apply changes for subscriptionSet ? Docs doesn't fully clear on this.

roman-rr commented 4 months ago

Or I can just call

subscriptionSet.addChannels(['channel-6']);
subscriptionSet.removeChannels(['presence-channel-2']);

And then set will be updated ? Or should I need additionally call this, after any updates at set ?

subscriptionSet.unsubscribe();
subscriptionSet.subscribe();
parfeon commented 4 months ago

Hello! I want to apologize for so long response and provide some guidance.

A subscription set is what it names “say”: it is an aggregation / set of Subscription object for each specific channel / group (presence channel / groups with -pnpres suffix is part of a single Subscription object). This aggregation makes it easier to subscribe to the group of objects at once or attach listeners to the group of channels and groups used in the set at once.

Important: SDK won't create parallel subscription calls for each of the set. The SDK will keep using the multiplex feature of the current subscribe REST API by providing a set of channels and groups to subscribe to.

Actual subscribe REST API calls done only as part of underlying subscription loop or when subscribe / unsubscribe functions have been used.

In the last response, you mentioned addChannels and removeChannels, but the public interface doesn't have such functions. It looks like the IDE just suggested you any method which matches function signature (those available for push notifications management).

When you manipulate the content of the SubscriptionSet, there are two options:

You can even have a single Subscription object if you'd like. Maybe following sample code will give some ideas how to organize your code:

// Bootstrap
const bootstrapSubscription = pubnub.channel('channel-2').subscription();

// Unified set
let subscriptionsSet = pubnub.subscriptionSet({});

// Regular set
let regularSubscriptionSet = pubnub.subscriptionSet({
  channels: ['channel-1', 'channel-3', 'channel-4', 'channel-5'],
});

// Presence set
let presenceSubscriptionSet = this.pubnubService.pubnub.subscriptionSet({
  channels: ['presence-channel-1', 'presence-channel-2'],
  subscriptionOptions: { receivePresenceEvents: true },
});

subscriptionsSet.addSubscriptionSet(regularSubscriptionSet);
subscriptionsSet.addSubscriptionSet(presenceSubscriptionSet);
subscriptionsSet.addSubscription(bootstrapSubscription);

subscriptionsSet.onMessage = (message) => {
  // Handle messages here.
  subscriptionsSet.removeSubscription(bootstrapSubscription);
  bootstrapSubscription.unsubscribe();

  const channelSubscription = pubnub.channel('channel-6').subscription();
  // Addition into `subscriptionsSet` will forward all messages from 'channel-6' into already 
  // attached `onMessage` listener. It is also possible to attach listeners directly to the 
  // `channelSubscription` but if it has been added into `subscriptionsSet` then new messages 
  // will be received in both `onMessage` listeners (for set and separate channel).
  subscriptionsSet.addSubscription(channelSubscription);

  // We need to call this because set already subscribed.
  channelSubscription.subscribe();
};

// Make channels active.
subscriptionsSet.subscribe();
roman-rr commented 4 months ago

Thank you for detailed answer @parfeon ! Yes, addChannels and removeChannels just my mistake, I mean removeSubscription, addSubscription.

At this moment it's seems to be more clear, on how to structure subscriptions into sets. I will working out on my end next to find a best solution!