Search code examples
flutterdartriverpodflutter-riverpodappwrite

Appwrite Realtime subscription Flutter riverpod problem when unsubscribe to subscription


Appwrite realtime subscription dispose of (unsubscribe) issue with flutter_riverpod. By using this for a single document it is working. But the problem is when I am fetching multiple documents and subscribing to the doc When the page gets closed and the provider gets disposed of the Subscription gets closed appwrite RealtimeSubscription shows this error.

  • All documents that are subscribe exist in Database Collection
  • The Current user has permission to read the docs
  • All Documents in the Same Collection
  • Appwrite instance in a singleton class so no duplication

Which I already tried: Appwrite endpoint set With HTTPS and HTTP Self Signed TRUE and FALSE

flutter: AppwriteRealtime: Allow self-signed certificate
flutter: subscription: wss://10.100.110.13/v1/realtime?project=63b04724be0f82751c50
[ERROR: flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: AppwriteException: null, Missing channels (1008)

Here is the provider:

final testProvider = StateNotifierProvider.family
    .autoDispose<TestNotifier, BracketStats, String>((ref, bracketID) {
  return TestNotifier(ref, docID: bracketID);
});

class TestNotifier extends StateNotifier<BracketStats> {
  final Ref ref;
  final String docID;

  RealtimeSubscription? _subscription;
  TestNotifier(this.ref, {required this.docID}) : super(BracketStats.empty());

  Future getData() async {
    final k = await ref.read(BracketRepository.getBracketStats(docID).future);
    state = k ?? BracketStats.empty();
  }

  void subscribe() {
    final realtime = ref.watch(AppwriteDependencies.realtime);
    _subscription = realtime
        .subscribe(['databases.bracket_db.collections.stats.documents.$docID']);

    if (_subscription != null) {
      _subscription?.stream.listen((response) {
        final bracketStats = BracketStats.fromJson(response.payload);
        state = bracketStats;
      });
    }
  }

  @override
  void dispose() {
    if (_subscription != null) {
      _subscription?.close();
    }
    super.dispose();
  }
}

Solution

  • There may be a race condition when multiple subscriptions are closed simultaneously. Perhaps it might be better if each of these notifiers uses a separate Realtime instance rather than sharing.