Skip to content

Supabase Realtime stream cancel and initialize again #585

Closed
@iampopal

Description

@iampopal

Describe the bug

We are using Supabase realtime for a chat app, and we are facing an unusual behavior with stream and channels

1) We have a global cubit that listens to room status name RoomStatusCubit

This RoomStatusCubit is initialized by listening to the room_status table:

initStream() {
  var realstream = from('room_status')
      .stream(primaryKey: ['id'])
      .eq('to_uid', supabase.uid)
      .order('at');
  var subscription = realStream!.listen(
    (event) {
      log('realtime 0 listen event: $event');
      emit(
        state.copyWith(
          rooms: RoomStatus.listFrom(event),
          status: RealtimeStatus.result,
        ),
      );
    },
    onError: (e, s) {
      log('realtime 1 error: $e \ns:$s');
      if (e.toString() == '' || e.toString() == '{}') return;
      emit(state.copyWith(status: RealtimeStatus.error, error: e));
    },
  );
}

The above cubit has worked well for a while but has an issue when 


  1. the internet disconnects and reconnects 

  2. when for a long time there is no internet
    
3) when an error happens



    
To solve our above issue we have decided to close current channel and reinitalize stream 



Future cancelStream() async {
    try {
      await subscription?.cancel();
      subscription = null;
    } catch (e, s) {
      subscription = null;
      loges(e, s, type: 'realtime cancelStream');
    }
  }

  List<RealtimeChannel> get roomStatusChannels => supabase
      .getChannels()
      .where((e) => e.topic.contains('room_status'))
      .toList();

  Future cancelChannel() async {
    for (RealtimeChannel c in roomStatusChannels) {
      log('realtime cancel topic ${c.topic}');
      await supabase.removeChannel(c);
    }

    await cancelStream();
  }




The issue is when we call cancelChannel() and then initStream() the stream is not working anyway. 

currently, we need to restart our app to solve this issue and we need a better solution for restarting superbase realtime channel to work correctly so users do not close and open their app.

To Reproduce
Steps to reproduce the behavior:

  1. Create an app with realtime stream in a cubit
  2. Try to cancelChannel() and initStream()

Expected behavior
Allow us to cancel a realtime stream and init stream again without any error and stream shall work like restarting an app

Version (please complete the following information):
On Linux/macOS
Please run dart pub deps | grep -E "supabase|gotrue|postgrest|storage_client|realtime_client|functions_client" in your project directory and paste the output here.
│ └── supabase 1.10.0
│ ├── functions_client 1.3.2
│ ├── gotrue 1.11.2
│ ├── postgrest 1.5.0
│ ├── realtime_client 1.1.3
│ ├── storage_client 1.5.1
├── supabase_flutter 1.10.12
│ ├── supabase...

Additional context
We sometime also see heartbeat timeout issue and not understand how this is related
and sometime see Bad state: Cannot add event after closing error event or cubit is not closed and working correctly

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrealtimeThis issue or pull request is related to realtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions