Masud Hossain
Joined
Activity
Chris's new video might be helpful for you: https://gorails.com/episodes/activerecord-explain?autoplay=1
@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
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 .
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
EDIT: Solved
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!