Websocket ignoring unmatched topic

Hi,

I have a phoenix app using channels extensively and my problem is that after x number of mins when I try to send data over the channel from the client (js client in web browser), I get no response, and the app just logs the unmatched topic error/warning.

I have set the timeout on the UserSocket transport to :infinity

## Transports
transport :websocket,
  Phoenix.Transports.WebSocket,
  timeout: :infinity

transport :longpoll, Phoenix.Transports.LongPoll

I’m still getting the unmatched topic warning. The topic that is unmatched is the same one that connects fine at sign in, so it appears that if no data is sent after x mins the channel connection drops.

I need to be able to sign in, in a morning, and then have the WebSocket stay open all day.

I could set up a javascript timer to keep pinging the socket every 5 mins or so, but that seems hacky, is there a way to keep the socket open indefinitely?

Thanks

Paul

The phoenix channels client already pings and keeps it active via a heartbeat, so if it is dying then some user code on the server or client is causing it or something between the client and server is killing the connection (proxy?).

Do you have a reproducible example and/or code with it running somewhere?

Ah yes, I forgot about the heartbeat :slight_smile:

I don’t have anything I can make public, if this is still a problem at the weekend I’ll try and put something together and post it.

Don’t know if this would help, but I decided to ping the channel every second, and added the following handler to the channel:

def handle_in("ping", _, socket) do
    IO.puts "Ping"
    {:noreply, socket}
end

I then signed in, and left it running for 10 mins with no interaction. When I checked the logs I found the following:

21:20:51.328 [info]  JOIN "channel_name:public" to AppNameWeb.Channels.AppName ^H^M
  Transport:  Phoenix.Transports.WebSocket (1.0.0)^M
  Serializer:  Phoenix.Transports.WebSocketSerializer^M
  Parameters: %{}^M
^M
21:20:51.328 [info]  Replied channel_name:public :ok^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
Ping^M
^M
21:21:22.428 [info]  GET /^M
^M
21:21:22.429 [info]  Sent 200 in 742µs^M
Ping^M
Ping^M
Ping^M
Ping^M
^M
21:25:12.738 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M

===== Tue Jul 31 21:31:04 BST 2018
^M
21:31:04.763 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
^M
21:31:05.570 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
^M
21:31:06.569 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
^M
21:31:07.571 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
^M
21:31:08.574 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
^M
21:31:09.573 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
^M
21:31:10.576 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
^M
21:31:11.576 [warn]  Ignoring unmatched topic "channel_name:public" in AppNameWeb.UserSocket^M
...

I also started the app locally and left that running in another browser tab. The local version doesn’t die (or hasn’t so far).

The only difference between the two is that one is in dev env and one prod, and the prod env is behind nginx.

I’ll keep digging, and trying to narrow it down. I’ll post back if I have any success.

Thanks.

NGinx has a websocket timeout default as I recall, be sure to up it to something reasonable for what you want (24 hours or so, I think it defaults to like 10 minutes or something?)

As for that unmatched topic, that’s still odd, what’s your channel definitions in AppNameWeb.UserSocket (also how are you getting \r’s in your log file?!)?

I think it’s the client closing the connection.

Adding the following to my nginx conf solves the problem:

proxy_read_timeout 1d;
proxy_connect_timeout 1d;
proxy_send_timeout 1d;
proxy_set_header Connection "";

So when I clear the Connection header, the channel stays open. I guess the client is sending ‘close’.

I’m using Elm for the client code, with an elm-phoenix package for the WebSocket handling, so it looks like it may be this package sending close(?) (which I guess answers why I was getting the unmatched topic warnings).

(The \r’s in my log file are from doing a find/replace in sublime)

It seems to be ok now (prior to fully testing all day today), thanks for the nginx tip.

1 Like

If it’s not my elm phoenix package that uses the official javascript API then the other ones have known bugs of a lot of things like that sadly… ^.^;

I’m using this Elm package:

http://package.elm-lang.org/packages/fbonetti/elm-phoenix-socket/latest

I chose it because the guys at PragmaticStudio.com were using it in their Elm course (https://pragmaticstudio.com/courses/unpacked-bingo) so I figured it would be ok - it also seemed to make it simpler to utilise Phoenix.Presence than the package I was using at the time.

I’ve searched the Elm community packages, but can’t find your package, do you have a link to it? I’d be interested in having a look.

Thanks for your help, appreciate it.

Paul

Packages in the package listing are not allowed to contain javascript, which since mine used the official phoenix javascript interface means it’s not allowed to be hosted there thus it has to be grabbed from github:

Do note, mine was made for 0.16 as I recall so it might need some updating to 0.18, but the edits should be fairly minor.

I’m not in that whole camp in Elm of rewrite-the-everything-in-elm, better to use well tested things instead. ^.^;

1 Like

That’s how I started out using sockets with Phoenix and Elm - I used the official phoenix js interface with my own ports in and out of Elm handling the traffic. Then I started ‘learning Elm more’ and it appeared from what I was ‘learning’ that I should move away from ports + js to pure Elm packages.

I’ve since ended up with a library of my own js modules that all do simple things well (that I find tough in Elm) and are easily tested, so I’ve gone round in a bit of a circle - but learnt things along the way :grin:.

I’ll take a look at your package over the weekend, thanks.

My package is mostly just a set of typed interfaces around phoenix channel ports, you can easily just use ports straight and custom types instead of needing to be generic as mine was too. :slight_smile: