Upload with paperclip very slow (unicorn) - ruby-on-rails-3

Sitting here with a simple rails 3 app in which I have a simple Gallery model and each gallery has many images. The image model is extended with paperclip and with the following options
has_attached_file :local,
:styles => {
:large => "800x800>",
:medium => "300x300>",
:thumb => "100x100#",
:small => "60x60#"
}
In my galleries_controller I have the following action that is implemented in order to work with the jQuery-File-Upload plugin. thereby the json response.
def add_image
gallery = Gallery.find params[:id]
image = gallery.images.new({:local => params[:local]})
if image.save
render :json => {:thumb => image.url(:thumb), :original => image.url}
else
render :json => { :result => 'error'}
end
end
To me this is fairly straight forward. But here comes the issue. In Development under mongrel any kind of upload works just fine with about 500-1000ms/upload.
However when I push it in to production I constantly get timeouts of my unicorn workers and when it does send an image through it takes anywhere from 30-55 seconds for one file.
the files I upload are around 100k in size
I have done some testing of the bandwidth between my VPS and my dev computer witH ipref and got an average speed of about 77kbps so the upload should not be a problem.
Note I also did a test with a non ajax file upload using the same app with user model that has an avatar.
Development => Completed 302 Found in 693ms
Production => Completed 302 Found in 21618ms
Anyone experienced a similar issue with (rails3, unicorn) file uploads?

So after digging around I managed to determine that on my VPS it was the OpenMP Option in ImageMagick that was causing the very slow operation. So my first attempt was to rebuild the native Ubuntu 10.04 package with the --disable-openmp flag added. This failed for some reason and while I am not sure why the package kept comming out with openMP still active. My current solution is now instead to backport ImageMagick from Ubuntu 10.10. Below follows the steps I took:
Step 1 download the following files:
imagemagick_6.6.2.6-1ubuntu1.1.dsc
imagemagick_6.6.2.6.orig.tar.bz2
imagemagick_6.6.2.6-1ubuntu1.1.debian.tar.bz2
from here
Step 2 unpack the package
$ dpkg-source -x imagemagick_6.6.2.6-1ubuntu1.1.dsc
Step 3 edit the rules
$ cd imagemagick-6.6.2.6
$ vim debian/rules
Add the the follwing line to the ./configure statment on line 25-39. I added mine on line 34.
34: --disable-openmp \
Step 4 add dependencies and build ( I needed these dependencies)
$ sudo apt-get install liblqr-1-0-dev librsvg2-dev
$ dpkg-buildpackage -b
Step 5 Out with the old, in with the new
$ sudo apt-get remove --purge imagemagick
$ sudo dpkg -i libmagickcore3_6.6.2.6-1ubuntu1.1_amd64.deb
$ sudo dpkg -i libmagickwand3_6.6.2.6-1ubuntu1.1_amd64.deb
$ sudo dpkg -i imagemagick_6.6.2.6-1ubuntu1.1_amd64.deb
Step 6 Once again have fast image conversions
_before_ (with openmp)
$ time utilities/convert 'image.jpg' -resize "x60" -crop "60x60+10+0" +repage 'thumb'
real 0m11.602s
user 0m11.414s
sys 0m0.069s
_after_
$ time utilities/convert 'image.jpg' -resize "x60" -crop "60x60+10+0" +repage 'thumb'
real 0m0.077s
user 0m0.058s
sys 0m0.019s

If processing takes a long time, consider processing the thumbnails in a separate workers.
Request: accept file; save it to disk; post job to queue
Worker: pop job from queue; create thumbnails; repeat
Delayed::Job and Resque are great solutions for this.

Related

Deploy rails application after git push

I want to deploy my application on remote test server using capistrano gem.
Both git and rails should run on same server.
I have 2 users 'git' for git repositories and 'rails' with installed rvm. After git push i want to execute hook post-receive which runs su rails and then cap deploy.
When i tried push i got message:
remote: su: must be run from a terminal
How can i work around this message. Can i enable tty some way over git ssh connection?
I can give up from capistrano for this case but still i want rvm and rails to be used only by user rails (so su probably have to be used in each case).
edit
Now i walk around problem. Probably this is very bad solution but works ;). From bellow script's i removed original paths and echo's.
post-receive hook before walkaround
#!/bin/bash
while read oldrev newrev ref
do
su rails #here script fails
cd /path/to/rails/app/current/ && cap deploy
done
post-recive now
#!/bin/bash
while read oldrev newrev ref
do
ssh rails#localhost '/path/to/scripts/deploy.sh'
done
deploy.sh script
#!/bin/bash
CAP_DIR="/path/to/capistrano/dir"
RUBY="1.9.3-p194"
GEMSET="gemset_name"
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"
rvm use $RUBY
rvm gemset use $GEMSET
cd $CAP_DIR
cap deploy

Heroku image corruption

When uploading an image through git to heroku, the image is corrupted when it gets sent from the web server. I've been trying to fix it by going g rm --cached images/contact-me.png and then g add images/contact-me.png again, and then pushing.
Also;
xyz#co-data:~/labs/exposeit-site$ sha1sum images/contact-me.png
2d319cd64e94afe7cdd169347653670a1dd82581 images/contact-me.png
xyz#co-data:~/labs/exposeit-site$ wget http://exposeit.herokuapp.com/images/contact-me.png
--2012-08-16 16:50:35-- http://exposeit.herokuapp.com/images/contact-me.png
Resolving exposeit.herokuapp.com (exposeit.herokuapp.com)... 50.19.121.246, 174.129.192.155, 184.73.155.93, ...
Connecting to exposeit.herokuapp.com (exposeit.herokuapp.com)|50.19.121.246|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1230115 (1.2M) [image/png]
Saving to: `contact-me.png'
100%[=================================================================================>] 1,230,115 963K/s in 1.2s
2012-08-16 16:50:36 (963 KB/s) - `contact-me.png' saved [1230115/1230115]
xyz#co-data:~/labs/exposeit-site$ sha1sum contact-me.png
74d97745d35bb67e5517611b683ed461bd0c1686 contact-me.png
and
xyz#co-data:~/labs/exposeit-site$ g ls-files | grep contact-me
images/contact-me.png
Is this a problem of Heroku's?
Update:
Procfile:
web: bundle exec thin start -R config.ru -e $RACK_ENV -p $PORT
So the answer is that the thin gem has a bug that takes string length instead of length of the byte array that is the underlying image. Why it would first be converted to a string, I don't know.
The solution is to add, to your Gemfile:
gem 'rack-jekyll', :git => 'https://github.com/adaoraul/rack-jekyll.git', :require => 'rack/jekyll'
...and it will be downloaded from github rather than RubyGems.
Weird. Still, you look okay to me. http://exposeit.herokuapp.com/images/contact-me.png
Is best to host images and static content elsewhere rather than put megabytes in source control https://devcenter.heroku.com/articles/s3

apn_sender gem daemon not running

Im using apn_sender for rails 3 and i have been able to install the gem and get it working just fine by using
rake apn:sender
I have tried to get it started in production mode on a ubuntu box by starting the daemon and it does not seem to work. When i type
script/apn_sender --environment=production --verbose start
I dont see anything. No log present.
when i try to type
script/apn_sender status
It returns with
apn_sender: no instances running
Just trying to understand why it is not running.
i just solved this problem. Try to create a file called 'script' in generators/apn_sender/templates . .
Put this in your script file
# !/usr/bin/env ruby
# Daemons sets pwd to /, so we have to explicitly set RAILS_ROOT
RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
require 'rubygems'
require 'apn'
require 'apn/sender_daemon'
APN::SenderDaemon.new(ARGV).daemonize
bash 'rails g apn_sender' in your terminal and will create 'script/apn_server' with same content as above
After that bash this code
./script/apn_server --environment=production --verbose start
it will create log/apn_sender.log . Try running
APN.notify('token',{:alert => '#' , :badge => 1})
or else in rails c to confirm if it works or not , and of course
rake apn:sender
Hope it will help :)
EDIT
You have to install redis and configure

Rails 3 - Whenever gem error: /usr/bin/env: ruby: No such file or directory

When using the 'whenever gem', I get an error in the log:
/usr/bin/env: ruby: No such file or directory
It works when I run the job manually. I've installed everything with RVM.
I've used the which command to find where my Ruby installation is, and I get:
kevin#lovely:/opt/personal$ which ruby
/home/kevin/.rvm/rubies/ruby-1.9.2-p290/bin/ruby
and I've checked my $PATH variable, where it returns:
kevin#lovely:/opt/personal$ echo $PATH
/home/kevin/.rvm/gems/ruby-1.9.2-p290/bin:/home/kevin/.rvm/gems/ruby-1.9.2-p290#global/bin:/home/kevin/.rvm/rubies/ruby-1.9.2-p290/bin:/home/kevin/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
I believe this should be set up right, but I'm probably wrong since it doesn't work. Can anyone point me in the right direction?
If you're interested, this is what my whenever crontab output is:
# Begin Whenever generated tasks for: rss
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /bin/bash -l -c 'cd /opt/personal && script/rails runner -e development '\''FeedEntry.update_from_feed("http://lovely/blog/feed/")'\'' >> /opt/personal/log/feedzirra.log 2>&1'
You're probably long past this issue but for future reference:
I had a similar problem only I was getting
/usr/bin/env: ruby: No such file or directory
It turned out the first line of the file script\rails was #!/usr/bin/env ruby1.9.1, which tells the system to invoke it with ruby1.9.1 as explained here. But it should have been #!/usr/bin/env ruby1.9.3 since that was the version I had installed.
Hope this helps someone in the future :)
My issue was that ruby is in /usr/local/bin which is not in the path of a headless bash. So I just made my rake task line in schedule.rb:
job_type :rake, "cd :path && PATH=/usr/local/bin:$PATH RAILS_ENV=:environment bundle exec rake :task :output"
I am successfully using whenever with RVM and bundler in production. Here are the relevant pieces of my capistrano setup that may help you:
# rvm and bundler integration
require 'rvm/capistrano'
require 'bundler/capistrano'
# RVM environment
set :rvm_ruby_string, "ruby-1.9.2#mygemset"
# crontab
set :whenever_roles, :cron
set :whenever_command, "bundle exec whenever"
set :whenever_environment, defer { stage }
require 'whenever/capistrano'
The :whenever_environment setting is because I am using a multi-stage deployment setup. You can ignore that or set it to a string that matches your setup if needed.
Most of this information can be found at the whenever github page under the "Capistrano integration" and "RVM Integration" section headers in the README.
I hope that helps.
I solved the problem about the same as Duke. Except I figure out that $PATH variable is not working for me.
sys_path = '/home/[user]/.rbenv/versions/[ruby_version]/bin'
job_type :runner, "cd :path && PATH=#{sys_path} bin/rails runner -e :environment ':task' :output"
job_type :rake, "cd :path && PATH=#{sys_path} :environment_variable=:environment bin/bundle exec rake :task --silent :output"
If none of these worked for you, try:
gem install rails
This did the job for me, hope it helps!

Updating files after RVM install

I have installed RVM enroute to updating and running different ruby and rails. After install I received message to update shell's loading files.
1) Place the folowing line at the end of your shell's loading files
(.bashrc or .bash_profile for bash and .zshrc for zsh),
after all PATH/variable settings:
[[ -s "/Users/eric/.rvm/scripts/rvm" ]] && source "/Users/eric/.rvm/scripts/rvm" # This loads RVM into a shell session.
You only need to add this line the first time you install rvm.
I typed [[ -s "/Users/eric/.rvm/scripts/rvm" ]] && source "/Users/eric/.rvm/scripts/rvm"
and hit enter. Does this update my files? Or do I have to open some type of file and cut and paste code?
Since I did not see any notice as stated below from part 2 of the post install, I closed the shell and opened a new one. but the RVM command does not seem to work. Part 2 of the instructions post install was:
2) Ensure that there is no 'return' from inside the ~/.bashrc file,
otherwise rvm may be prevented from working properly.
This means that if you see something like:
'[ -z "$PS1" ] && return'
then you change this line to:
if [[ -n "$PS1" ]] ; then
# ... original content that was below the '&& return' line ...
fi # <= be sure to close the if at the end of the .bashrc.
# This is a good place to source rvm v v v
[[ -s "/Users/eric/.rvm/scripts/rvm" ]] && source "/Users/eric/.rvm/scripts/rvm" # This loads RVM into a shell session.
EOF - This marks the end of the .bashrc file
Be absolutely *sure* to REMOVE the '&& return'.
If you wish to DRY up your config you can 'source ~/.bashrc' at the bottom of your .bash_profile.
Placing all non-interactive (non login) items in the .bashrc,
including the 'source' line above and any environment settings.
Thanks for the help as I am very new and trying to learn RoR but so far have not been able to get past the setup in many of the tutorials I've attempted. It seems many [
1 2 are out of date with new software or I get error messages before I can even attempt to learn the code. If someone knows of a good beginner tutorial that would be great. Thanks again!
The snippet that the installer gives you need to go in a file called the bashrc. The file lives in your home directory: /Users/eric/.bashrc
You need to edit this file and add the line from rvm and then you should be good to go.
As for getting rolling with rails I'd recommend The Pragmatic Programmers book on rails. You can find their books at pragprog.com
If you're on Ubuntu, my tutorial on setting rvm will get you roll all the way up to rails installation:
http://blog.dcxn.com/2011/06/20/setting-up-rvm-on-ubuntu-11-04/