Papillon6814

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

andreaseriksson

Have you looked into considered Phoenix Presence?

Its build into Phoenix.

I have a tutorial about it here:

mpope

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 :slight_smile:

Where Next?

Popular in Discussions Top

thojanssens1
It would be nice to be able to define a redirect from one route to another from the router.ex file. E.g.: redirect "/", UserController, ...
New
lucaong
Hello Elixir and Nerves community, I have been working for a while on an open-source embedded key-value database for Elixir, that I call...
230 14027 124
New
lorenzo
Hey everone! I created a prototype for my app using Nodejs for the api. But the framework I chose wasnt great (in general theresnt any g...
New
nburkley
AWS re:Invent is on at the moment with some interesting announcements. One new feature in particular is the Lambda Runtime API for AWS La...
New
AlexMcConnell
The reason that Rails is as popular as it is is because it’s very easy for relatively inexperienced developers to get a lot of work done....
588 19652 166
New
PragTob
Hey everyone, this has been brewing in my head some time and it came up again while reading Adopting Elixir. GenServers, supervisors et...
New
und0ck3d
Hello everyone! A few days ago I’ve created a topic here about how people were creating CMSs with Elixir and Phoenix. I’ve been studying...
New
AstonJ
Can you believe the first professionally published Elixir book was published just 8 years ago? Since then I think we’ve seen more books f...
New
pdgonzalez872
If this has been asked here before, please point me to where it was asked as I didn’t find it when I searched the forum. Maybe a mailing ...
New
sashaafm
Piggy backing a bit on @dvcrn topic BEAM optimization for functions with static return type?, I’ve been trying to understand in a deeper ...
New

Other popular topics Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 41989 114
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New

We're in Beta

About us Mission Statement