Reputation: 1608
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
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:
Such combined approach would reliably provide you with users' online status at any time moment.
Upvotes: 2