Hello.
I made an online status indicator function with elixir.
It manages online status of users with database and channels.
Codes and a table and json examples
online_channel.ex
defmodule PappapWeb.OnlineChannel do
use Phoenix.Channel
require Logger
alias Pappap.Accounts
def join("online", _payload, socket) do
{:ok, socket}
end
def handle_in("online", payload, socket) do
%{"sender" => sender} = payload
case Accounts.get_user_by_user_id(sender) do
[] ->
Logger.info("Unknown user")
user ->
user
|> hd()
|> Accounts.update_user(%{is_online: true})
end
broadcast!(socket, "online", %{user: sender})
{:noreply, socket}
end
def handle_in("offline", payload, socket) do
%{"sender" => sender} = payload
case Accounts.get_user_by_user_id(sender) do
[] ->
Logger.info("Unknown user")
user ->
user
|> hd()
|> Accounts.update_user(%{is_online: false})
end
broadcast!(socket, "offline", %{user: sender})
{:noreply, socket}
end
end
database
# select * from users;
id | user_id | is_online | inserted_at | updated_at
----+---------+-----------+---------------------+---------------------
1 | 1 | t | 2020-08-05 04:25:55 | 2020-08-05 11:03:36
2 | 2 | f | 2020-08-05 04:25:55 | 2020-08-06 14:51:06
(2 rows)
json
{"topic":"online", "ref":1, "payload": {"sender": "2"}, "event":"phx_join"}
or
{"topic":"online", "ref":1, "payload": {"sender": "2"}, "event":"online"}
or
{"topic":"online", "ref":1, "payload": {"sender": "2"}, "event":"offline"}
The server changes is_online
by a json sent from a user through websocket. When user 2 joins a topic online, he need to send 2 json data.
{"topic":"online", "ref":1, "payload": {"sender": "2"}, "event":"phx_join"}
{"topic":"online", "ref":1, "payload": {"sender": "2"}, "event":"online"}
The former one just means āuser 2 joined topic onlineā, and the latter one means like āuser 2 is onlineā.
And then, is_online
turns true
by the latter json. The former one does not have meanings more than āuser 2 joined topic onlineā.
It was about how to turn online. Then, the next is about how to turn offline.
To be offline in the system, a user has to send json before leaving a channel and disconnecting from the server. This is the json.
{"topic":"online", "ref":1, "payload": {"sender": "2"}, "event":"offline"}
It means like āuser 2 is offlineā.
handle_in("offline", payload, socket)
works when the json is sent, and is_online
of user 2 turns false
.
With those processes, the system can manage online status of users.
But I think the system has a problem.
It cannot manage online status without handle_in/3
. If a client get disconnected from the server without sending json. The online status does not turn offline. So I want to have the system send json at the disconnecting event. But I donāt think phoenix can get message at disconnecting.
If thereās a better way of managing online status, teach me how!
(Let me know my English feels weird, because Iām from Japan)