Back

RealtimeSubscription not working if document is being listened to multiple times by the same client

  • 0
  • Self Hosted
  • Flutter
  • Realtime
Drake
9 Oct, 2023, 21:13

i can create additional documents and get the new event to come in. i can update an existing document and see 2 events come in (1 for the subscription on all documents and 1 for just the single document)

TL;DR
TL;DR: The RealtimeSubscription is not working when a document is listened to multiple times by the same client. The supplied methods to the `stream.listen` are not being called. The issue can be reproduced regardless of how the Realtime object is instantiated. There seems to be a ~5 second interval between accepting a stream and its disposal, which may be causing the problem. The bug is reproducible and has been tested with different approaches and state management logics. The number of documents subscribed to may affect the bug reproducibility.
Arrow
9 Oct, 2023, 21:15

Hmmm okay. What if the number of documents I have subscribed to has something to do with the bug reproducibility? I have like ~700 documents on a stream. The moment I take one document and add one additional stream on it (exclusively for itself), the second stream becomes an on-off situation it works and fails to work at times

Drake
9 Oct, 2023, 21:16

the number of documents don't really have an effect...the number of realtime subscriptions might

Arrow
9 Oct, 2023, 21:17

I tinkered around this issue for quite a while and I was able to reproduce it more than 10 times

Arrow
9 Oct, 2023, 21:17

I used different approaches and state management logics

Arrow
9 Oct, 2023, 21:17

The bug is reproducible on my part

Arrow
9 Oct, 2023, 21:18

I think there might be a time interval between a stream's listen and dispose at the backend

Arrow
9 Oct, 2023, 21:19

because I noticed if I disposed the second stream and subscribed to it within 5 seconds, it almost always failed to work

Arrow
9 Oct, 2023, 21:19

there might be some logic on the backend to not process a request until a current one is disposed of

Arrow
9 Oct, 2023, 21:20

and even on the docker realtime logs, i was able to see an open connection yet no response on the client

Drake
9 Oct, 2023, 21:32

so i tested again w/ 2 buttons. 1 subscribe on all documents. Another button calls list documents and then subscribes on each of those individual docuemnts. i updated 1 document from the console and then i received 2 events

Drake
9 Oct, 2023, 21:35

another test with automatically subscribing instead of subscribing with button clicks and it works as expected

Arrow
10 Oct, 2023, 17:20

@Steven I appreciate the time you took to look into this. I want to show you the following video of a test I just performed. The first screen is the list of documents and the second one is the view of that document both screen deploy a stream and every time screen 2 is closed the stream will disposed. The document change is an automated task and is done thru a dart client

Arrow
10 Oct, 2023, 17:28

*Riverpod used to view the model * https://pastebin.com/3sp0cCkw

Repository and methods https://pastebin.com/wTpnXDty

Database class https://pastebin.com/yTKBB6zz

Arrow
10 Oct, 2023, 17:30

Based on my observation I think that there is a ~5 second interval between accepting a stream and its disposal because if I dispose a stream and start the same one within 5 seconds it seems to almost always fail to work

Arrow
10 Oct, 2023, 17:31

as you can see from the video

Drake
10 Oct, 2023, 20:06

where and how is Realtime initialized?

Arrow
10 Oct, 2023, 20:09

I have initialized it as follows but it does not make a difference if I followed the way the doc instantiates it

TypeScript

Client client() => _client;
Realtime get realtime => Realtime(_client);
Arrow
10 Oct, 2023, 20:10

I am able to reproduce the issue regardless of how I instantiate the Realtime object

Drake
10 Oct, 2023, 20:14

can you share the full code around this?

Arrow
10 Oct, 2023, 20:17

Absolutely ```import 'package:appwrite/appwrite.dart'; import 'package:appwrite/models.dart'; Client _client = Client().setEndpoint(_endpoint).setProject(_projectID);

Client client() => _client;

Future<User> getCurrentUser() async => Account(_client).get().then((value) => value);

Future<Preferences> getAccountPrefs() async => getCurrentUser().then((value) => value.prefs);

Account getAccountService() => Account(_client);

Databases get databases => Databases(_client);

Realtime get realtime => Realtime(_client);

Storage get storage => Storage(_client);

Functions get functions => Functions(_client);

TypeScript
usage of my realtime getter

RealtimeSubscription getDoctorRealtimeSubscription(String doctorDocumentId) { try { return realtime.subscribe([ 'databases.$_doctorListDatabaseId.collections.$_doctorListCollectionId.documents.$doctorDocumentId' ]); } catch (e) { if (kDebugMode) print('getDoctorRealtimeSubscription: $e'); rethrow; } }```

Using the RealtimeSub in riverpod

TypeScript

  void _startRealtimeSubscription() {
    _realtimeSubscription = _setDoctorRepository
        .getDoctorModelRealtimeSubscription(doctorModel.documentId);

    _realtimeSubscription?.stream.listen(_onRealtimeMessage,
        onError: _onStreamError, onDone: _onStreamDone);
  }```
Arrow
10 Oct, 2023, 20:18
TypeScript
    if (message.events.contains(documentDeletedEvent)) {
      state = const AsyncData(DoctorModel());
    } else {
      final result =
          _setDoctorRepository.getDoctorModelFromRealtimeMsg(message);

      if (result != null) state = AsyncData(result);
    }
  }```
Arrow
10 Oct, 2023, 20:18

When the issue occurs non of the supplied methods to the stream.listen will get called

Arrow
10 Oct, 2023, 20:20

even though the IDE's console prints out about a realtime subscription and the docker logs show that connection

Arrow
12 Oct, 2023, 20:07

Steven did you conclude anything

Reply

Reply to this thread by joining our Discord

Reply on Discord

Need support?

Join our Discord

Get community support by joining our Discord server.

Join Discord

Get premium support

Join Appwrite Pro and get email support from our team.

Learn more