I really love using Phoenix Channels, but I find my channels files growing too fast. Is there any conventions how to organize your code? (for instance in rails you should keep fat models)
Also I use a lot of defp
s in my channels. Is it a good practice?
Thanks in advance!
If youâre asking then you probably start to feel yourself that something is wrong I guess no single module should be too fat, whether thatâs a controller, model or anything else. Itâs the same in Rails where models were only the first layer that tended to get fat but with time, patterns emerged to make every part of MVC slimmer.
Is it easy enough to understand what the channel module does and how the function calls flow within it? You could move some parts to separate modules with good descriptive names. If you need help, post the code or at least function signatures and then we could propose some candidates for extracting.
I tend to break things up into lots of channels. On my single websocket I have about 7 channels just for the messaging part.
Out of curiosity, can you break down what the different channels do?
One handles the messaging interface and what else to join. One for public channels (broadcasting to sync). One for each private channel set (1 for normal users, more for admins depending on who they are interacting with). One for the currently active room. One for notifications. Etc⊠Mostly separated so make Endpoint.broadcast
trivial to use for each case.
Lots of channels is a good idea . I have only 2 and it becomes a lil bit tedious
Something that I wish were added to channels were a way to alias a single âchannelâ in elixir with multiple topic names. I want to be able to broadcast, say âroom:38174â with a âuser:joinedâ or a âroomlist:271â with a âroom:joinedâ message or so without needing to make a dozen processes on the server.
hinthintphoenixdevshint ^.^
Why is the process count problematic?
Ease of holding the data internally primarily. Currently I have to duplicate data between them, which makes me twitchâŠ
Waiting eagerly to see what architecture sins will people start committing when designing their channels. And what patterns and conventions will emerge to amend that. RESTful channels? Channel broadcaster modules? Channel joiner modules?
Heh, I think the main thing that causes multiple channels right now for me is Phoenix Presence sends the same âpresence_diffâ regardless of topic or anything, so no way to differentiate which names the presence is trying to sync.
Iâve found that simply allowing the channels to handle traffic and delegating that traffic off to something else in the lib or better yet, another OTP app enables a good separation and also makes testing easier. This way, much like a controller in Rails is just dealing with HTTP, your channels just deal with Websockets data, and your actual application logic is somewhere else. Just my 2 cents though, Iâm sure everyone has different ideas on this.
That is what I do. Like for my example above my Messenger Channel set (topic âMessenger:*â) for "Messenger:Lobby sends basic connection info and what else should be connected to. The client then connects to (for example) âMessenger:RoomList:Publicâ and âMessenger:RoomList:437891231123236178â (where 437891231123236178 is the user ID, it denies if they do not have access to view that users joined channels) and âMessenger:Notifications:437891231123236178â. Then when they click a room to view it then they also join âMessenger:Room:76â (where 76 is the room id, it denies if they are not allowed to join the room).
The point of the separation is that Phoenix.Presence always sends it presence information via âpresence_diffâ, and as I got tired of hooking that to translate to other channels for each tracked topic I just make each topic its own full channel instead. Now I can do Endpoint.broadcast("Messenger:RoomList:76", "users:joined", %{users: userlist})
and so forth, in addition to being able to sync room information via presence as well as internal room information like joined users simultaneously.
Iâve also thought about so-called âChannel Dispatcherâ, which could catch messages flow from channel to channel all in one place and let them share their payload.
I do not know if I understand exactly your situation. This is how I separate my channels logic:
AQ: How to split channel source code in multiple ex files
AQ: How to delegate message handling handle_in to another file
###Context
So we had all our logic in room_channel.ex like this
defmodule MyAppWeb.RoomChannel do
use MyAppWeb, :channel
def handle_in("show_user", params, socket) do
IO.inspect params
{:noreply, socket}
end
end
```
..and we want to move the user logic.
###Solution
We can create another module/ex file like user_module.ex, move source code that you like and call it simply by full name.
in room_channel.ex
```
defmodule MyAppWeb.RoomChannel do
use MyAppWeb, :channel
def handle_in("show_user", params, socket) do
UserModule.handle_in("show_user", params, socket)
end
end
```
in user_module.ex
```
defmodule MyAppWeb.UserModule do
use MyAppWeb, :channel
def handle_in("show_user", params, socket) do
IO.inspect params
{:noreply, socket}
end
end
```
Hi, please note that Phoenixâs way of organizing code has changed significantly since this thread was created and it may only be useful for those running older versions. For this reason Iâm closing the thread but if you have any further questions about the issue please feel free to start a new thread.