Back

Guys, I'm trying to detect a disconnection in realtime, but it's not working... how to doit correct?

  • 1
  • Web
  • Realtime
  • Cloud
Waldemar
8 Sep, 2023, 06:02

Because I imagine that if the user loses connection for internet reasons or things like that, I should warn him that the application will not receive updates until he solves this internet problem...

TL;DR
The user is trying to detect a disconnection in realtime but is experiencing issues. They have written code that restarts the subscription, but they encounter a problem when trying to restart without internet. They are looking for a way to warn the user when they lose connection and suggest creating a feature request. A library that checks internet connection could be used in the meantime. There is a discussion about the possibility of using multiple realtime instances and making the subscribe method synchronous. The issue is specific to Flutter and there is no similar functionality in the web SDK. The user is using Appwrite v1.3.8 and the Appwrite Flutter SDK v9
safwan
8 Sep, 2023, 06:09

Isn't there an onDone callback?

Waldemar
8 Sep, 2023, 13:58

I just want to warn the user that he has lost connection with the Appwrite, would there be no way to do that currently? πŸ₯²

safwan
8 Sep, 2023, 14:46

There might be. I’ll need to look at my code to be absolutely sure, but yeah.

What version of Appwrite are you using?

safwan
8 Sep, 2023, 14:52
TypeScript
void realtimeConnection() {
    final client = _appwriteProvider.client;
    final realtime = Realtime(client);

    subscription = realtime.subscribe(['account']);

    subscription.stream.listen((res) {
      print('Events: ${res.events}');
      if (res.events.contains('users.*.update.prefs')) {
        // do something here
      }
    }, onDone: () => print("Connection to Realtime closed");
  }
safwan
8 Sep, 2023, 14:52

You could do this!

safwan
8 Sep, 2023, 14:53

I'm using Appwrite v1.3.8 and the appwrite flutter sdk v9.0.0

Drake
8 Sep, 2023, 16:14

this is in flutter. web SDK doesn't have this.

safwan
8 Sep, 2023, 16:17

ooooh whoops

corax
8 Sep, 2023, 16:57

I was about to create issue on something similar like that, like make subscribe method synchronous so that we can use await to confirm connection is established. It will help in making connections to realtime in a chain instead parallelly which is happening now. This way we can subscribe to multiple channels in a chained manner on frequent channel changes and also a callback to know when connection is broken to try to make the connection to realtime again.

Waldemar
8 Sep, 2023, 17:45

Do you have plans for the web api to have this kind of functionality?

Drake
8 Sep, 2023, 18:14

This way we can subscribe to multiple channels in a chained manner on frequent channel changes

Why exactly is this important?

corax
8 Sep, 2023, 18:34

Well, first of all we will know when connection is established, and then for example in some app we have frequent channel changes for example if there are two channel changes at the same time, it breaks connection and connects at the same time too but if we can await for the subscribe method we can put the channel changes(adding or removing) in queue so that It doesn't send too many requests to realtime and we can wait for current request (open or close connection) to finish before executing next.

Also, I am referencing using multiple realtime instances because single instance gets set to null after adding the 3rd channel (Flutter).

Drake
8 Sep, 2023, 19:54

wait are you using flutter or web?

Also, I am referencing using multiple realtime instances because single instance gets set to null after adding the 3rd channel (Flutter).

This is only a problem in flutter...and we plan on fixing it

Drake
8 Sep, 2023, 19:56

so that It doesn't send too many requests to realtime and we can wait for current request (open or close connection) to finish before executing next.

But you'd still have the same amount of open and closes...and a lot of the socket stuff is done via setTimeout() so a lot of it is async and it would be a big change to make it awaitable

Drake
8 Sep, 2023, 19:59

if you have multiple subscribe() calls at the same time...the SDK might even batch it beacuse createSocket() call happens in 50ms or something https://github.com/appwrite/sdk-for-web/blob/ca4ef6dd0f8d7110db57f8b3b295ce62e629eec5/src/client.ts#L192-L197 and at that time, there's a check to see what channels should the socket be for and it will only create a new websocket if there was a change

corax
8 Sep, 2023, 21:50

Flutter

corax
8 Sep, 2023, 21:53

It does in web, it might still be useful, if we have onConnected or onError callbacks in flutter for subscribe, for now it throws AppwriteException internally

Drake
8 Sep, 2023, 23:17

oops i got mixed up between who the original poster was.

Because I imagine that if the user loses connection for internet reasons or things like that, I should warn him that the application will not receive updates until he solves this internet problem...

We don't have plans to add this type of feature. I suggest creating a feature request. For now, maybe you can use some library that checks internet connection

Waldemar
9 Sep, 2023, 02:59

:c

Waldemar
9 Sep, 2023, 02:59

where can i create a feature request ?

Drake
9 Sep, 2023, 03:17

GitHub issue on our appwrite repo

Lenolium
9 Sep, 2023, 05:16

That's why I am here I wrote a simple class that restarts the Realtime subscription as soon as they are one done (which is sometimes quite random when it will happen) but because a error is thrown internal I have a Problem as soon as the subscription trys to restart without internet. Heres my code :

Lenolium
9 Sep, 2023, 05:17
TypeScript
class SyncerServiceFamilyProvider {
  final Ref ref;
  final MapEntry<StreamSubscription Function(), void Function()> functions;
  late final StreamSubscription Function() _realtimeFunction = functions.key;
  late final void Function() _fetchFunction = functions.value;


SyncerServiceFamilyProvider({required this.ref, required this.functions}) {
    _watchAppLifecycleState();
    _watchInternetConnectionStatus();
    _watchStreamSubscriptions();
  }

  AppLifecycleState _appLifecycleState = AppLifecycleState.resumed;
  bool _connected = true;

  DateTime? _streamSubscriptionStoppedAt;

  _watchAppLifecycleState() {
    _appLifecycleState = ref.read(appLifecycleStateProvider);
    ref
        .read(appLifecycleStateProvider.notifier)
        .stream
        .listen((appLifecycleState) {
      _appLifecycleState = appLifecycleState;
      if (_appLifecycleState == AppLifecycleState.resumed) {
        _restartStreamSubscriptions();
      }
    });
  }
Lenolium
9 Sep, 2023, 05:17
TypeScript
_watchInternetConnectionStatus() {
    _connected = ref.read(internetConnectionStateNotifierProvider);
    ref
        .read(internetConnectionStateNotifierProvider.notifier)
        .stream
        .listen((connected) {
      _connected = connected;
      if (_connected) {
        _restartStreamSubscriptions();
      } else {
        _streamSubscriptionStoppedAt = DateTime.now();
      }
    });
  }

  _watchStreamSubscriptions() {
    print('Started _watchSubscriptions');
    _realtimeFunction().onDone(_onDone);
  }

  _restartStreamSubscriptions() {
    print(_streamSubscriptionStoppedAt);
    if (_streamSubscriptionStoppedAt != null) {
      print('restartSubscriptions: $_streamSubscriptionStoppedAt');
      try {
        _fetchFunction(_streamSubscriptionStoppedAt);
        _realtimeFunction().onDone(_onDone);
        _streamSubscriptionStoppedAt = null;
      } catch (exception) {
        print('Realtime: $exception');
      }
    }
  }

  _onDone() {
    print('onDone');
    if (_appLifecycleState == AppLifecycleState.resumed && _connected) {
      print('onDone: restart');
      _realtimeFunction().onDone(_onDone);
    } else {
      print('onDone: waiting');
      _streamSubscriptionStoppedAt = DateTime.now();
    }
  }
}

final syncerServiceFamilyProvider = Provider.family<SyncerServiceFamilyProvider,
    MapEntry<StreamSubscription Function(), void Function()>>((ref, functions) {
  return SyncerServiceFamilyProvider(ref: ref, functions: functions);
});

final appLifecycleStateProvider = StateProvider<AppLifecycleState>((ref) {
  return AppLifecycleState.resumed;
});
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