How to Find Out Who Is Connected to Actioncable

ActionCable - how to display number of connected users?

Seems that one way is to use

ActionCable.server.connections.length

(See caveats in the comments)

Actioncable connected users list

Ya kinda have to roll your own user-tracking.

The important bits are as follows:

# connection
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :uid

def connect
self.uid = get_connecting_uid
logger.add_tags 'ActionCable', uid
end

protected

# the connection URL to this actioncable/channel must be
# domain.tld?uid=the_uid
def get_connecting_uid
# this is just how I get the user id, you can keep using cookies,
# but because this key gets used for redis, I'd
# identify_by the user_id instead of the current_user object
request.params[:uid]
end
end
end


# Your Channel
def subscribed
stop_all_streams
stream_from broadcasting_name
ConnectedList.add(uid)
end

def unsubscribed
ConnectedList.remove(uid)
end

And then in Models:

class ConnectedList
REDIS_KEY = 'connected_nodes'

def self.redis
@redis ||= ::Redis.new(url: ActionCableConfig[:url])
end

# I think this is the method you want.
def self.all
redis.smembers(REDIS_KEY)
end

def self.clear_all
redis.del(REDIS_KEY)
end

def self.add(uid)
redis.sadd(REDIS_KEY, uid)
end

def self.include?(uid)
redis.sismember(REDIS_KEY, uid)
end

def self.remove(uid)
redis.srem(REDIS_KEY, uid)
end
end

from: https://github.com/NullVoxPopuli/mesh-relay/

Detect Action Cable connection status

Got it sorted out. In my components, when I need to find out cable status, I do

this.$root.cable.connection.isOpen()

If false I revert to HTTP.

Hope this helps someone later on.

Get list of all registered connections

I finally found a solution.

def connect
self.uuid = SecureRandom.uuid
transmit({'title': 'players_online', 'message': ActionCable.server.connections.size + 1})
ActionCable.server.connections.each do |connection|
connection.transmit({'title': 'players_online', 'message': ActionCable.server.connections.size + 1})
end
end

def disconnect
transmit({'title': 'players_online', 'message': ActionCable.server.connections.size})
ActionCable.server.connections.each do |connection|
connection.transmit({'title': 'players_online', 'message': ActionCable.server.connections.size})
end
end

ActionCable.server.connections gets a list of all server connection, except of the one which is currently connecting to the socket. That's why you need to transmit him a message directly with ActionCable.server.connections.size + 1

How do I get current_user in ActionCable rails-5-api app?

If you see the doc you provided, you will know that identified_by is not a method for a Channel instance. It is a method for Actioncable::Connection.
From Rails guide for Actioncable Overview, this is how a Connection class looks like:

#app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user

def connect
self.current_user = find_verified_user
end

private
def find_verified_user
if current_user = User.find_by(id: cookies.signed[:user_id])
current_user
else
reject_unauthorized_connection
end
end
end
end

As you can see, current_user is not available here. Instead, you have to create a current_user here in connection.

The websocket server doesn't have a session, but it can read the same cookies as the main app. So I guess, you need to save cookie after authentication.

ActionCable display correct number of connected users (problems: multiple tabs, disconnects)

I finally at least got it to work for counting all users to the server (not by room) by doing this:

CoffeeScript of my channel:

App.online_status = App.cable.subscriptions.create "OnlineStatusChannel",
connected: ->
# Called when the subscription is ready for use on the server
#update counter whenever a connection is established
App.online_status.update_students_counter()

disconnected: ->
# Called when the subscription has been terminated by the server
App.cable.subscriptions.remove(this)
@perform 'unsubscribed'

received: (data) ->
# Called when there's incoming data on the websocket for this channel
val = data.counter-1 #-1 since the user who calls this method is also counted, but we only want to count other users
#update "students_counter"-element in view:
$('#students_counter').text(val)

update_students_counter: ->
@perform 'update_students_counter'

Ruby backend of my channel:

class OnlineStatusChannel < ApplicationCable::Channel
def subscribed
#stream_from "specific_channel"
end

def unsubscribed
# Any cleanup needed when channel is unsubscribed
#update counter whenever a connection closes
ActionCable.server.broadcast(specific_channel, counter: count_unique_connections )
end

def update_students_counter
ActionCable.server.broadcast(specific_channel, counter: count_unique_connections )
end

private:
#Counts all users connected to the ActionCable server
def count_unique_connections
connected_users = []
ActionCable.server.connections.each do |connection|
connected_users.push(connection.current_user.id)
end
return connected_users.uniq.length
end
end

And now it works! When a user connects, the counter increments, when a user closes his window or logs off it decrements. And when a user is logged on with more than 1 tab or window they are only counted once. :)



Related Topics



Leave a reply



Submit