pubnub / dart

PubNub Dart SDK
Other
28 stars 15 forks source link

Feature request: unsubscribe() #44

Closed alecxandrys closed 3 years ago

alecxandrys commented 3 years ago

Good day, Is it possible to add next feature: unsubscribe() I want to change subscription's list, but can't remove only one or few of them. So i have to use unsubscribeAll() and make subscribe() again.

With best wishes.

are commented 3 years ago

Hi! You can cancel a subscription by calling .cancel() on a specific subscription.

Example:

var subscription1 = pubnub.subscribe(channels: {'channel-a'});

await subscription1.cancel();
alecxandrys commented 3 years ago

Hello, I see two problem:

In my case I add eventHandler by next code: pubnub! .subscribe(channels: _channelsList.toSet(), withPresence: false) .messages .listen(eventHandler);

However, for every changes, which remove channel, in _channelsList I have to unsubscribe and resubscribe again.

Also i would not keep excess objects for every channel.

are commented 3 years ago

The way the SDK is designed it is very cheap to create and destroy the Subscription objects, so it is not an expensive operation. Underneath it is managed in such a way that multiple subscriptions are not using separate resources, so this should be inexpensive.

In general I recommend grouping your long-lived subscriptions into one, but if you know that a subscription will be short-lived it can be a separate subscription.

It's important to manage your subscriptions especially in a Flutter app. It's important to be able to granularly destroy subscriptions and stream listeners in a Flutter app, and that is the reason this SDK was designed.

However, if you feel like this isn't fitting in your use-case and you want a more centralized approach, I can add a feature request for this. Also you can experiment with writing your own subscription manager if you have the time and resources, we greatly appreciate any contributions!

Here is a rough sketch of how the SubscriptionManager maybe implemented for your use case:


import 'package:async/async.dart' show StreamGroup;
import 'package:pubnub/pubnub.dart';

class SubscriptionManager {
  final Set<Subscription> _subscriptions = Set();
  final StreamGroup<Envelope> _group = StreamGroup.broadcast();
  final PubNub pubnub;

  SubscriptionManager(this.pubnub);

  Stream<Envelope> get messages => _group.stream;

  void subscribe(List<String> channels) {
    for (var channel in channels) {
      var sub = pubnub.subscribe(channels: {channel});
      _subscriptions.add(sub);
      _group.add(sub.messages);
    }
  }

  Future<void> unsubscribe(List<String> channels) async {
    var subsToRemove = _subscriptions
        .where((sub) => sub.channels.any(channels.contains))
        .toList();

    for (var sub in subsToRemove) {
      _subscriptions.remove(sub);
      _group.remove(sub.messages);
      await sub.cancel();
    }
  }
}
alecxandrys commented 3 years ago

Hello! Thanks, i think this solution can help me for a time.

But I don't know which subscription will be short or long lived, so I have to keep every channel in separated subscription. It can become problem in the future, with up scaling of program.