Papillon6814
Is there a better way to maintain online status of each user?
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)
Most Liked
andreaseriksson
Have you looked into considered Phoenix Presence?
Its build into Phoenix.
I have a tutorial about it here:
mpope
Can always have an ETS table with the user_id as a key and a timestamp of their last online heartbeat as an index. Then a scheduled process can sweep the ets table and remove users who have ‘disconnected’ (current timestamp is older than a set amount of time from the current time). Online status can just be if the user is in the ets table.
Its ripe for race conditions if ya use only dirty operations ![]()
Popular in Discussions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









