Hi, I’m creating an app where users, after making a connection, can speak to each other, this is not the classic chat room example as are just direct messages between 2 users. Is there a specific way to implement this using Phoenix Channels? been googling but couldn’t find something useful, from the top of my head I’m just thinking of having a topic like conversation and as subtopic a combination of both users ids, so that the subtopic will be unique for any 2 users combination.
Is this a good approach? or is there a better/cleaner way to implement this?
Yeah, I also see it this way. Everyone joined one big channel and then communication rely on direct handle_in eg. someone pushes into this channel for topic user:#{user_id} and only that user can read it and in return he uses push or reply, but not broadcast.
I would have a topic like private:user1:user2 and then just have a consistent sort for the users so that you don’t end up with private:user2:user1 also. Maybe use user IDs. That way the messages are contained and you don’t have to worry about another user reading them as much.
Oh yes, then it could be better to just have private:user inbox for every user as said above and only have the user in question be able to connect to it for reading. Just include the sender’s ID/name in the message payload.
I like the idea of having a topic like private:user1:user2. When an event occurs, I know I have to connect both users to the private channel, that way I think A wants to call B, but B does not know it should connect to the private channel between A and B wouldn’t be a problem.
I was just thinking that as I had the idea in my head but haven’t implemented it yet. When an event occurs, I have to notify both users in order to them to connect to the private channel, so I guess for the event notification I can use the approach filtering in handle_out, and then use the user1:user2 approach. I could just filter everything in handle_out but I think having a specific subtopic for a private channel makes more sense conceptually speaking.
Well, I do the same, I send notification on a common channel.
The difference is I notify only the targeted people I need. In my case, the common channel is already private, as the notification occurs between A and B only.
yeah, it makes sense, and I wouldn’t have to open a new socket for the private channel, but I’m just thinking, if I look at a code where only one common channel is used filtering the receptors in handle_out, I would ask myself, where are the private conversations being managed/handled? until I find out that’s being filtered in handle_out, whereas if I have a specific private channel for direct messages, with only one glance I could answer that question.
Does it make sense?
The best way to accomplish this is to have a “control” channel for each user, such as a UserChannel, a topic like user:[user_id]. When User A wants to start a private conversation with User B, they broadcast to User A’s channel:
You want to avoid the handle_out usage where all users join the same topic since filtering any individual convo would be extremely expensive. Hope the helps!
Here is a very simplified code, to show what I mean. It assumes payload contains a message, and a receiver_id. It also assumes You store user_id in your socket
def handle_in("notify", payload, socket) do
sender_id = socket.assigns.user_id
# This method is intercepted when going out!
broadcast! socket, "notify_out", %{
message: payload.message,
sender_id: sender_id,
receiver_id: payload.receiver_id}
{:noreply, socket}
end
intercept ["notify_out"]
def handle_out("notify_out", payload, socket) do
user_id = socket.assigns.user_id
if (user_id === payload.sender_id || user_id === payload.receiver_id) do
push socket, "notify_out", payload
{:noreply, socket}
else
{:noreply, socket}
end
end
I’d like to quickly point out that you won’t need a new socket to join a new private channel, you can have multiple (lightweight!) channels multiplexed over a single websocket.
Hi, i may have a question, in the direct message only one user should get the message, but in the phoenix pg2 pubsub, all the nodes will get notify of the message, is it true and is there some ways to avoid it? thanks!