1

I'm a Rails beginner building a quiz webapp. Currently I'm using ActionCable.server.connections.length to display how many people are connected to my quiz, but there are multiple problems:

  1. When the page is reloaded half of the time the old connection is not disconnected properly by ActionCable, so the number keeps rising even though it shouldn't
  2. it only gives you the current number of connections for the specific thread this is called in, as @edwardmp pointed out in this actioncable-how-to-display-number-of-connected-users thread (which also means, that the number of connections displayed for the quiz hoster, which is one type of user in my app, can vary from the number of connections displayed to a quiz participant)
  3. When a user connects with multiple browser windows each connection is counted seperately which falsely inflates the number of participants
  4. And last but not least: it would be great to be able to display the number of people connected per room of my channel, instead of across all rooms

I've noticed that most answers concerning this topic use a Redis server, so I was wondering if that is generally recommended for what I'm trying to do and why. (e.g. here: Actioncable connected users list )

I currently use Devise and cookies for my authentication.

Any pointers or answers to even part of my questions would be greatly appreciated :)

megahra
  • 295
  • 2
  • 19

1 Answers1

1

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. :)

megahra
  • 295
  • 2
  • 19