I have a website built on Rails, on Heroku, that typically works fine with about 90% memory usage.
Through Scout I have isolated a problem in my Rails-app where my comments#create-controller sometimes allocates 860k of Memory which shuts down my app for a long time in the time-outs etc that follow. Most of the time the allocated memory is a fraction of it so the problem is intermittent.
The comment-function itself is not super important but I still need it. I believe three different parts of it could cause this memory problem:
The content string (i.e. the comment itself) is too long. For example if a spammer posts a super long text. I don't believe this to be the issue as my last memory spike was caused by a normal user, posting a very short comment.
My rakismet-gem (https://github.com/joshfrench/rakismet) and spam check. I am using the latest version (1.5.4). It could be likely this is a problem as I don't really know what is loaded into the memory when it is being used.
My Notifier-call in the code.
Is there anything I can do to catch memory problems and rescue in the controller so if there are any "bad" comments, they wont break the entire site?
Do you see anything that could cause this monster memory allocation in the code?
Code below:
Comments#Create:
def create
require 'memory_profiler'
report = MemoryProfiler.report do
@comment = Comment.new(comment_params)
spam_features = %w(\xA cialis informative the that this buy href)
unless @current_administrator.present?
if spam_features.any? {|str| @comment.content.include? str}
logger.info "L: Comment include spam features"
redirect_to article_path(Article.find('din-kommentar-har-inte-sparats')) and return
elsif @comment.author.size > 40 || @comment.author_email.size > 40
logger.info "L: Comment author name or email too long (suspicious)"
redirect_to article_path(Article.find('din-kommentar-har-inte-sparats')) and return
end
end
# This shouldn't be here (but don't know how to put it in the model)
if !@comment.blog_post_id.blank? # This is a comment on a blog post
return_to_path = blog_post_path(BlogPost.find(@comment.blog_post_id))
elsif !@comment.gift_id.blank? # This is a comment on a gift
return_to_path = gift_path(Gift.find(@comment.gift_id))
elsif !@comment.contest_id.blank? # This is a comment on a contest
return_to_path = contest_path(Contest.find(@comment.contest_id))
elsif !@comment.christmas_fair_id.blank? # This is a comment on a christmas fair
return_to_path = christmas_fair_path(ChristmasFair.find(@comment.christmas_fair_id))
elsif @comment.tmp_julrim # This is a comment on a christmas fair
return_to_path = rhymes_path
else
raise ActionController::RoutingError.new('Not Found')
end
return_to_path << "#comments"
@comment.status_id = 3
@comment.user_ip = request.remote_ip
@comment.user_agent = request.env['HTTP_USER_AGENT']
@comment.marked_as_spam = @comment.spam? # Using rakismet to check for spam
#if !@comment.marked_as_spam || @current_administrator.present?
respond_to do |format|
#@comment.status_id = 1 if @comment.contest_id == 44
if @comment.save
Notifier.new_comment(@comment).deliver if Rails.env == 'production' unless @comment.marked_as_spam
format.html { redirect_to return_to_path, notice: 'Din kommentar har registrerats och kommer att ses över innan den godkänns.' }
# format.json { render action: 'show', status: :created, location: @comment }
else
format.html { render action: 'new' }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end