I am planning on building multiple chat rooms with different names “room:lobby, room:1, room:2, etc”
In my room_channel.ex file, I set up something simple like this to save chat messages to the database:
def handle_in("new_msg", %{"body" => body}, socket) do
if (socket.assigns.is_anon == 0) do
IO.inspect("user is logged in - send message")
spawn(fn -> save_message(%{body: body, userid: String.to_integer(socket.assigns.user_id), roomid: socket.topic}) end)
broadcast!(socket, "new_msg", %{body: body})
{:noreply, socket}
else
IO.inspect("user is anonymous - do not send message")
{:noreply, socket}
end
end
defp save_message(message) do # Use a schema called SaveChats here. Note: saved in schemas folder.
Exchat.Repo.insert(%SaveChats{roomid: message.roomid, userid: message.userid, message: message.body})
end
The first question: Does the spawn
function to save_message
look appropriate? I got this advice from an online guide: Adding a Persistence layer , so I don’t know how long ago this guide was written or if this is an outdated method or not. If there are millions of people chatting at once, I would like the database saves being done on the side, in it’s own process to prevent slowing down everything (as the guide stated).
Second question: As you can see from my spawn
function, I am grabbing the userid from socket.assigns and converting it to an integer, and the roomid from socket.topic. Is this a solid way of getting this information, or am I supposed to send the roomid and userid from the client side along with the message? I’m using the socket.assigns.userid to prevent malicious users from injection fake userids from the client side. In my script, is socket.topic actually showing the roomid at the time the message is sent (accurate roomid every time?), or is it fixed to just one value when joining a room, or can it accumulate a list of room ids, or topics?
How would you obtain this info in your own app?
Last question: Once in awhile, the database can go down, or an insert might not execute (mysql server down, aborted connection, etc). Is there a way to save these “inserts” on the Phoenix server for later, and insert them when the database comes back up? When I first read the Elixir docs, I recall something about mailboxes
that can store messages in the system for awhile. I was wondering if Phoenix had some simple way of utilizing this for MySQL - saving the failed queries so they can run later when the database is up again.