Masud Hossain

Joined

3,660 Experience
3 Lessons Completed
3 Questions Solved

Activity

@shakeycode & @Mark Radford , I did eager loading on all my conversations and messages.

This is a descent guide for it: https://code.tutsplus.com/articles/improving-the-performance-of-your-rails-app-with-eager-loading--cms-25018
You would need to set your eager loading up based on your settings, but it's pretty straightforward tbh.

It's nothing you do on your connection.rb, it has to do with your controller. Basically it's creating TOO many queries.

@shakeycode

The high memory is now fixed. I needed to optimize my cache.

Go check your rails logs to see if you see a lot of
CACHE (0.0ms) .....

loading when you go to a specific page or conversation. This was my issue and soon as I fixed it, my CPU+memory usage dropped dramatically and my app got faster.

The next thing I'm trying to figure out is how to use token based authentication.

Cookies and sessions isn't 100% safe and cross-domain happy (safari), so token based authentication may be really good. Also, you'll need to do this if you're going to build an iOS app to work.

connection.rb

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

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.email
    end

    protected

    def find_verified_user # this checks whether a user is authenticated with devise

    user_id = request.headers['x-user-id']
    if user_id == nil
      user_id = cookies[:user_id]
    end
      if current_user = User.find(user_id)
      current_user
      else
        reject_unauthorized_connection
      end
    end
  end
end

In application controller, you need to modify your current_user lines of code

  def current_user
    user_id = request.headers['x-user-id'] || cookies[:user_id]
    @current_user ||= if user_id.present?
      User.find_by(id: user_id) 
    else params[:token].present?
      User.find_by(token: params[:token])
    end
  end

Posted in Does actioncable create 1 channel per user only?

Thanks for the response, Chris. The only thing im worried about is having too much real time stuff using actioncable and slowing down my app because my redis server or heroku server cant handle the high memory usage .

Posted in Does actioncable create 1 channel per user only?

Let's say you're planning on having real time Notifications and messaging.

Does that mean that for each User, there will be 1 actioncable channel (redis) open?

Or

Does that mean for each User, there will be 2 actioncable channels (redis) opened? One for messaging and one for the notfications.

@shakeycode

I'm on rails 5.0 and my REDIS is at least not giving me the Sessions full error anymore, the 20limit on channels from heroku redis is complete bullshit tbh. AFter that, it doesn't seem like I got any errors.

HOWEVER, my rails app on heroku is still giving me a crap load of high Memory usage. I'm 100% convinced it's my fault though. I upgraded my heroku to 2x dyno with 1gb of memory, and my app sometimes hits 214% with 2.2gb.

I'm working on a solution, but not a whole lot of luck. It's hard to even determine what the problem is.

Ended up switching to digitalocean. Heroku redis kinda sucks in general.

@everyone thanks for the responses! I haven't found a 100% solid solution, yet, but i'm working on it!

I hope Chris keeps on coming out with more performance videos!

Thanks for all that info, Jacob! I'll get on that article reading.

Also, it seems I got that high memory usage with only 3-5 people on the site (my team testing it), that's what worrisome for me.

I DID use actioncable chat during that time, so I think that's the reason why. Would you happen to know if i'm suppose to run a procfile for my puma to start working on heroku production as shown in Chris's video: https://gorails.com/episodes/deploying-to-heroku-with-puma?autoplay=1 ? Because I didn't, and my chat is still working. but i wonder if i do what he did, if it'll lower my memory or redis usage.

EDIT: This worries me a lot: http://prntscr.com/dzimys

So i built my web app that allows users to chat with eachother, see who's online, and send notifications all using actioncable and it's using up A LOT of memory it seems. Correct me if i'm wrong, but memory can highly affect your websites speed, cpu usage, ect. Right?
http://image.prntscr.com/image/9cf01fb6787c42cf9a2859f9c398fc43.png

So is there any types of strategies one can do to lower the memory usage down that I can look into? Possibly any videos that Chris has done to improve memory performance?

Does using front end frameworks like Emberjs even help with this type of problem?

Thanks so much for the help, Chris!

In case anyone else wants to know, this is what i did:

1) I'm basically specificying which users id it is by storing a cookie of the current_user.id .
2) In application_controller.rb i have this with before_action :cookie_set and

            def cookie_set
                @user = current_user
                return unless current_user
                cookies[:user_name] = @user.id
            end

3) and connection.rb , this will pull w/e is inside that user_name cookie.

def find_verified_user # this checks whether a user is authenticated with devise
    if current_user = User.find(cookies[:user_name])
    current_user
    else
        reject_unauthorized_connection
    end
end

4) this is probably not secure since someone can change the cookie to any user. So i'll add a token:string to my users datatable to fix this later.

So when I use Chrises code, it's still doing the same thing.

Except when I went back to my rails logs , i see an error like this

There was an exception - NameError(undefined local variable or method `session' for #<ApplicationCable::Connection:0x007fd5689d0860>)
/home/ubuntu/workspace/app/channels/application_cable/connection.rb:14:in `find_verified_user'
/home/ubuntu/workspace/app/channels/application_cable/connection.rb:7:in `connect'

Hey guys, i'm still a bit stuck on this. So i'm hoping one of you guys can tell me what i'm doing wrong.
I thought it would be either these two codes, but it doesn't seem so...
What I've tried:

verified_user = User.find_by(id: params[:id]) and verified_user = User.find_by(id: session[:user_id])

Here are my two files for authentication:

class SessionsController < ApplicationController

  def create
    user = User.find_by(email: session_params[:email].downcase)
    respond_to do |format|
      if user && user.authenticate(session_params[:password])
        session[:user_id] = user.id
        format.html { redirect_to conversations_path }
        format.json { render json: { success: true, user: user }, status: :ok }
      else
        format.html {
          flash[:notice] = 'Incorrect user or password'
          render 'new'
        }
        format.json {
          render json: { success: false, error: 'Incorrect user or password' }, status: :unprocessable_entity
        }
      end
    end
  end

  def destroy
    session.delete(:user_id)
    reset_session
    redirect_to signin_path
  end

  private

  def session_params
    params.require(:session).permit!
  end
end
class RegistrationsController < ApplicationController

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params.merge({
      is_admin: true
    }))

    respond_to do |format|
      if @user.save
        session[:user_id] = @user.id
        format.html { redirect_to sites_path, notice: 'Successfully registered!' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: user.errors, status: :unprocessable_entity }
      end
    end
  end

  def user_params
    params.require(:user).permit!
  end
end

I'm watching https://gorails.com/series/realtime-group-chat-with-actioncable
and i noticed that in channels/application_cable/connection.rb , chris put this code to find verified users.

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

    def connect
      self.current_user = find_verified_user
      logger.add_tags "ActionCable", "User #{current_user.id}"
    end

    protected

      def find_verified_user
        if current_user = env['warden'].user
          current_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

The part i'm particuarly having problem with is the 'env['warden'].user part. I'm not using devise because i created my authentication from scratch...so what would it be than?

I want to use actioncable to pull notifications AND also use it for user to user chatting. Is this possible and pain free to do?

I guess what i'm asking is, can i join these two videos together into one project without doing anything special:

https://gorails.com/episodes/realtime-notifications-with-actioncable?autoplay=1
https://gorails.com/episodes/direct-messages-in-realtime-with-actioncable?autoplay=1

Thanks for the great response, Chris!

Is there any disadvantages to using Widgets over API's? Cause it seems to me that widgets are far more easier to install than certain API's.
So is Intercom.io considered an API or widget?

So say i wanna build a website widget where people can install it with a few lines of codes. And in that widget users are able to sign up for my website or see certain information that's on my website.

Is something like this possible to do on rails?

I'm fairly new to building API's or widgets (are they even the same thing?), so I'm trying to see how to go about learning these type of stuff.

EDIT: Correct me if I am wrong, but a website widget is basically someone else's website...within someones website. And you just use HTML/CSS to design it to look like a widget, and you use Javascript to do the API or GET/PULL requests. Right??

Thanks a whole bunch for clearing it up, Chris!