All threads / Realtime Online User Tracking with ActionCable Discussion

Ask A Question

Notifications

You’re not receiving notifications from this thread.

Realtime Online User Tracking with ActionCable Discussion

How would you limit those users by tenant ( account)? Would you make the data sent to redis an array of two integers, like [1, 2] where 1 is the account.id and 2 is the user.id? Or is there a simpler way to approach this?

Hi Matt,
what about setting a different key per tenant ?

ActionCable.server.pubsub.redis_connection_for_subscriptions.sadd(
        "online_users_account#{account.id}", current_user.id)

As I was facing another (but I think related) issue, storing apperance for multiple models, I store a key per model and each one has its own array.

Thanks Nathan,
I was thinking something like that as well, but I'm pretty new to how ActionCable works so am stumbling through this a bit... Good to know that I had thought through this in a decent way despite not knowing how to implement this. Do you think that it'd be good to add something to connection.rb to deal with multitenancy and whethere 'current_account' is set?

Hi,
I never worked with multy tenancy and I'm also quite new to ActionCable
so I don't really know, but my guess is you could pass an array to identified_by and identify by both current_user and current_tenant.
Then set current_tenant or reject connection if none is found.
I did some testing and the following make the current_tenant variable availble in all channels and seems to work fine.

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user, :current_tenant

    def connect
      self.current_user = find_verified_user
      self.current_tenant = find_tenant
      logger.add_tags "ActionCable", "#{current_user.class.name} #{current_user.id}"
    end

    protected

    def find_verified_user
      # some logic to find the user
    end

    def find_tenant
      # just an example
      if user.tenant.present?
        user.tenant
      else
        reject_unauthorized_connection
      end
    end
  end
end

Again, I never had to do that so I'm not sure about this solution but it seems to work fine.
Let me know if this i working :)

Reply

Iam not using Jumpstart and if i try to even get the members in console i get an error:

NoMethodError (undefined method `redis_connection_for_subscriptions' for #ActionCable::SubscriptionAdapter::Async:0x00007f8bc0a80ba8)

has anyone an idea why ? or how to fix

I got the same error. Were you able to figure out the cause or a fix ?

After digging around a little I noticed the problem was in cabl.yml, (Im assuming you both encountered this issue while working in development).
There is an 'adapter: async' under the development namespace, just set it to redis and that solved my problem.

Reply

have I missed something?
if a user is logged in in two browsers and then unsubscribes from only one of the browsers doesn't the unsubscribe incorrectly remove them from the redis data bas?

Reply

If I have multiple devise users scopes (Admin, User) and I plan to display the list of online Users and also the list of online Admins, should I generate 2 different channels, or should it be done in the same channel ? I am able to set the following:

identified_by :current_user, :current_admin

    def connect
      find_verified
    end

    protected

    def find_verified
      if (current_user = env["warden"].user(:user))
        self.current_user = current_user
        logger.add_tags "ActionCable", "User #{current_user.id}"
      elsif (current_admin = env["warden"].user(:admin))
        self.current_admin = current_admin
        logger.add_tags "ActionCable", "Admin #{current_admin.id}"
      else
        reject_unauthorized_connection
      end
    end

But how should my online_channel.rb and js looks like ?

Reply

We got this working, but... just because someone is 'logged in' doesn't mean that person is online.

We use devise and it allows members to stay logged in for long periods of time, just like most websites. But that doesn't really mean someone is 'online'. In fact, it may mean someone logged in 3 days ago but hasn't had any activity since.

We originally wanted to use this to help members find other members who were online in particular chatrooms, but the way this works, it's not based on actual recent user activity, but rather 'logged in' status (which is not very accurate at all).

Anyone have any idea how to modify this so it's actually 'real time' (within 5 minutes)?

Reply
Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 48,387+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2021 GoRails, LLC. All rights reserved.