How to keep a user subscribed to every chat it is

2019-04-17 11:41发布

问题:

Thats the messenger's facebook UI

If you were implementing that with phoenix (elixir framework)

Would you create one phoenix-channel for one chat?

Which will implies that you client (mobile, web etc...) will have to open one channel for every chat it is suscribed at

Which will implies that if there is 2000 chats he is suscribed at, he will have to open 2000 channels (client load).

Would you create one phoenix-channel for one user?

Which will implies that your client (mobile, web etc...) will have to open just one channel and

Which will implies that for every incoming message you'll have to query for al the users in a room (server load).

回答1:

In messaging apps, there are two primary concerns. Managing the list of resources (users, rooms, etc) that a user is subscribed too. This is typically displayed as a list in the client. So you need to render that list and update for thinks like presence, new message alerts, and perhaps showing if the use has an open chat window. The solution for this part is similar regardless if the users/rooms are point-to-point or multi-user (rooms).

The second concern is displaying messages in individual chat windows that are open/visible. The solution for this may vary depending on whether they are point-to-point or multi-user. However, Facebook does support multi-user chat, so I'll answer this based on my experience building a Slack clone in Phoenix.

I recommend two channels, one for users and one for the open chat windows, lets call it chat. Each user will have 1 instance of a user channel and an instance of the chat channel for each open chat window. The user_id can be used for the topic of the user channel like "user:" <> user.user_id. You will probably have a schema for each of the chat sessions (which uses are part of the chat session). So use that id for the chat channel topic like "chat:" <> chat.id.

You can then broadcast new incoming messages in the chat channel and they will go out to everyone in that chat session (people that have the chat window open). This will work for both point-to-point and multi-user windows.

The example you provided in the question shows two uses with different state (text color). One shows a missed call and the other I presume indicates an unread message. This type of state is typically specific to the user, so you would use the use channel put push this information.

To track indicators on the user list, you can subscribe to messages in the chat channel from the user channel. You will then receive info messages in the user channel and take appropriate actions if needed. If you subscribe to the chat join messages, you can build a list of these and store it in your socket.assigns struct. See Phoenix Channels - Multiple channels per socket for more details.

Another API that I use for messaging apps is the intercept api. This allows you define a handle_out function that gets called for specific broadcast events of a channel. It can be used to filter or manipulate outgoing messages broadcast on that channel