Concurring messages from single client over a Phoenix channel

Hello, everyone.

I have a question about how phoenix process messages coming from each client. By my experiments I discovered that phoenix handles one message per client at a time, so if a client push’s one message and then push’s another message before the first one has been replied by the server, the second message is not processed until the first is replied. So if a request takes several seconds to be replied, its several seconds without any communication trough the we-bsocket for that client.

First of all are my assumptions correct?

If so is there a way to tweak this on Phoenix, any config that enables processing multiple message from the same client at the same time?

If there’s no tweak, can anyone suggest a pattern/method to avoid this problem when a clients websocket communication gets blocked by a request that is taking too long to process?

Yes, Channels are processes and they can only handle 1 message at a time. It is possible to concurrently process messages by spawning linked processes and then using https://hexdocs.pm/phoenix/Phoenix.Channel.html#reply/2, you can reply to the client. You need the socket_ref, which is another function on Phoenix.Channel.

2 Likes

Thanks that solution is very useful, works pretty well.

I’m tempted to just use this technique on all the handle_in’s, but I wonder if there is some downside to doing this too much, maybe some performance issue.

1 Like

You will have some overhead from spawning the process, which wouldn’t be necessary if it’s a very basic request. However, spawning processes is very cheap. Also, you lose a bit of backpressure, because a bunch of processes could spawn at once and cause requests to go to external resources.

I would be tempted to use it for things that are to external resources (database, API, etc) and you know could be delayed. For example, sometimes I see database performance get a bit slow on things that it should be fast for due to other underlying issues. It is nice that Channels would keep working great in that case.

I would not use it for things that are flow-control related, because then you run the risk of race conditions.

1 Like

Thanks for the advice, it will be very useful. I will consider all that before making a decision.