Keep user "online" with ActionCable

I have code that hugely relies on whether or not a user is online.

Currently I've setup ActionCable like this:

class DriverRequestsChannel < ApplicationCable::Channel
  def subscribed
      stream_from "requests_#{current_user.id}"
  end

  def unsubscribed
    current_user.unavailable! if current_user.available?
  end
end

Now what I'll ideally like to cover is the case where a user just instead of going offline just closes their browser. However the issue with unsubscribed is that it goes on page refresh. So every time they refresh their page they'll trigger the unsubscribed. Thus they'll be put as unavailable even though they think they're available.

Now the key thing is that being available isn't a default so I can just put it back, it's something a user chooses in order to receive requests.

Does anybody have experience with the best way to handle a case like this?

Upvotes: 1

Views: 1146

Answers (1)

prograils
prograils

Reputation: 2376

You should not only rely on Websockets, but also put a user online status into the database:

1: Add a migration

class AddOnlineToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :online, :boolean, default: false
  end
end

2: Add an AppearanceChannel

class AppearanceChannel < ApplicationCable::Channel
  def subscribed

    stream_from "appearance_channel"

    if current_user

      ActionCable.server.broadcast "appearance_channel", { user: current_user.id, online: :on }

      current_user.online = true

      current_user.save!

    end


  end

  def unsubscribed

    if current_user

      # Any cleanup needed when channel is unsubscribed
      ActionCable.server.broadcast "appearance_channel", { user: current_user.id, online: :off }

      current_user.online = false

      current_user.save!      

    end


  end 

end

Now you are guaranteed against any occasional Websockets connection losses. On every HTML-page refresh do 2 things:

  1. Check for database's user online status.
  2. Connect to socket and subscribe to Appearance Channel.

Such combined approach would reliably provide you with users' online status at any time moment.

Upvotes: 2

Related Questions