braverhealth / phoenix-socket-dart

Cross-platform and stream-based implementation of Phoenix Sockets
https://pub.dev/packages/phoenix_socket
BSD 3-Clause "New" or "Revised" License
74 stars 37 forks source link

PhoenixChannel.leave error #15

Closed MOPineyro closed 3 years ago

MOPineyro commented 3 years ago

When calling leave on the phoenix channel I notice that I'm still receiving data. On subsequently attempting to rejoin I'm faced with the !joinOnce error.

Here's a basic implementation:

class PhoenixWebSocketClient {
  String baseUrl;

  PhoenixWebSocketClient(String baseUrl);

  Future<void> connect(String token) async {
    PhoenixSocketOptions opts = PhoenixSocketOptions(params: {"token": token});

    await PhoenixSocket(
      baseUrl,
      socketOptions: opts,
    ).connect();
  }

  Future<Stream<Message>> openChannel(FreerollChannelType channelTopic) async {
    phxChannel = socket.addChannel(topic: channelTopic, parameters: {});

    if (!phxChannel.isJoined) await phxChannel.join().future;

    return phxChannel.messages;
  }

  Future<void> leaveChannel(PhoenixChannel channel) async {
    await channel.leave().future;
  }
}

Any guidance as to how to properly dispose of channel subscriptions would be appreciated.

hworld commented 3 years ago

I just found this error as well. I don't think leaving a channel works at all currently. This is the leave() function in its entirety:

  Push leave({Duration timeout}) {
    _joinPush?.cancelTimeout();
    _rejoinTimer?.cancel();

    _state = PhoenixChannelState.leaving;

    final leavePush = Push(
      this,
      event: PhoenixChannelEvent.leave,
      payload: () => {},
      timeout: timeout,
    );

    final __onClose = _onClose;
    leavePush..onReply('ok', __onClose)..onReply('timeout', __onClose);

    if (!socket.isConnected || !isJoined) {
      leavePush.trigger(PushResponse(status: 'ok'));
    } else {
      leavePush.send().then((value) => close());
    }

    return leavePush;
  }

You can see it changes _state = PhoenixChannelState.leaving; and then below that does a check for !isJoined. That's just a getter that does this:

bool get isJoined => _state == PhoenixChannelState.joined;

isJoined will always be false because the state was changed to leaving. It just immediately returns as an 'ok'.

Another place this same sort of issue is encountered is in the triggerError method of the same class:

_state = PhoenixChannelState.errored;
if (isJoining) {
  _joinPush.reset();
}
matehat commented 3 years ago

Thanks for reporting this, should be fixed really soon.

matehat commented 3 years ago

Fix is part of the 0.4.9 just released version