Phoenix: Explicit reconnect doesn't rejoin channels

Created on 2 Jul 2019  路  8Comments  路  Source: phoenixframework/phoenix

  • Phoenix version: 1.4.8

Expected behavior

Explicit reconnect should rejoin the channels.

Actual behavior

Doing an explicit reconnect on existing open connection using:

socket.disconnect()
socket.connect()

or

socket.reconnectTimer.scheduleTimeout()

does not rejoin the channels. Instead we start getting reason: "unmatched topic" errors.

We use this to try to switch from LongPoll connection to WebSocket connection.

Basically what we do is (coffeescript):

  startAvoidLongPollWorker = (socket) ->
    work = ->
      # Avoid changing transports and interfering with the reconnection logic
      # when we don't have an established connection and the reconnection might
      # already be in progress
      return if socket.connectionState() != 'open'

      # Return if the user is already not using LongPoll
      return if socket.transport != Phoenix.LongPoll

      newTransport = findNewTransport(socket.transport)

      # Return if the new transport is the same
      return if socket.transport == newTransport

      # Change socket transport and schedule a reconnect
      socket.transport = newTransport
      socket.reconnectTimer.scheduleTimeout()

    setInterval(work, AVOID_LONGPOLL_WORKER_INTERVAL_IN_MS)

As a workaround we currently did:

    socket.onOpen ->
      # Do channel rejoin in next event loop, otherwise it's too soon and
      # doesn't work.
      channels = socket.channels
      setTimeout(->
        channels.forEach((channel) ->
          channel.rejoinTimer.scheduleTimeout()
        )
      )
bug

Most helpful comment

@snewcomer definitely something we should handle on our side. Channels rejoins happen automatically on connection recovery, but sounds like there is a bug here when disconnect => reconnect in the same event loop. Can you take a look? Thanks!

All 8 comments

socket.reconnectTimer.scheduleTimeout() these are private APIs so to avoid confusion, can you confirm if the following alone triggers this issue:

socket.disconnect()
socket.connect()

Do things rejoin in this case?

They don't. The result is same. There's no rejoin and I start getting unmatched topic errors.

@indrekj Based on your knowledge, is this still a current bug and do you think this should be fixed by the library (and not userland code)? If so, I can startg taking a look...

@snewcomer definitely something we should handle on our side. Channels rejoins happen automatically on connection recovery, but sounds like there is a bug here when disconnect => reconnect in the same event loop. Can you take a look? Thanks!

https://github.com/phoenixframework/phoenix/pull/3665/files#r375649649

Hi @indrekj. My comment in your PR relates to the test context. So, in a non-test environment, it would be great to hear what happens if you connect in the next macroTask...

socket.disconnect();
setTimeout(() => {
  socket.connect();
}, 100);

Is "onConnClose" eventually called (w/ master or your latest version of phoenix)?

Is "onConnClose" eventually called

It is not.

馃憤 Seeing the same thing in a running app.

Although, I'm unable to reproduce reason: "unmatched topic"calling disconnect and connect sequentially in a very simple case. I hate to ask b/c you have put in a bunch of great work, but is this something you can provide in a demo app?

@indrekj I think we have it fixed! Would love to hear what you think about #3708!!

Before

Screen Shot 2020-04-04 at 2 26 55 PM

Screen Shot 2020-04-04 at 2 28 37 PM

After

Screen Shot 2020-04-04 at 2 22 33 PM

Screen Shot 2020-04-04 at 2 35 43 PM

Was this page helpful?
0 / 5 - 0 ratings