Visit http://devcenter.heroku.com/articles/rails-unicorn
The issue with the rails server, is that it only allows for one web process at a time. Unicorn allows you to add additional servers, which can be specified in your config/unicorn.rb file
gem 'unicorn'
then, run bundle install
This is where you define the number worker processes. Worker processes in this context is all processes not just background processes. Below indicates that we want three worker processes running at once.
#config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true
Set Unicorn as the server for the web process in your Procfile:
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
heroku addons:create redistogo
heroku config:set REDISPROVIDER=REDISTOGOURL
Running more than 1 dyno (server) on Heroku costs, and ain't nobody got time for that. Coderwall has created a hack:
layout: post title: "Build Robust & Production Quality Applications - Lesson 6: Procfile & Foreman" tags: tealeaf
On your server, you can run both web and worker processes locally - you can also do the same on Heroku, identifiying the processes you would like to run in your Procfile. A procfile is placed in the root of your diretory and declare what types of processes you want run in your app.
In your procfile, you will define:
<process type>: <command>
web: bundle exec rails server -p $PORT
worker: bundle exec rake jobs:work (example from delayed jobs)
worker: sidekiq
Instead of having to start both Sidekiq and our Rails server locally, we can use format to initiate both processes by runniong "foreman start" in your app directory.
will parse out the web processes from your Procfile.
heroku ps
will list the processes running
heroku logs
will list all process types
Heroku will allow you to run one web & worker processes but if you'd like to run more, it may costs.
Email sending typically is not very fast since we have to rely on some third party application. Waiting can slow up your app and potentially frustrate users so it's best to put non-essential and non-time-sensitive tasks in background jobs.
Since you can web processes and background job processes running locally, you need tp run both the rails server and sidekiq servers to process jobs respectively.
came out of Github - Resque is our Redis-backed library for creating background jobs, placing those jobs on multiple queues, and processing them later.
Benefits: has admin interface, is powered by Github Delayed Job does not require Redis, both uses a pulling queue Beanstalk and Stalker may be better if you care about speed, as they have a pulling mechanism
Sidekiq is a higher performance background solution than Resque and can even be ported, added on top of resque solution.
Check out the Railscast on Resque for intro.
In order to use Sidekiq, you must install and run Redis. Once downloaded, run the "$ src/redis-server" in the redis-3.0.2 folder.
You must also gem install sidekiq, and run "bundle exec sidekiq"
When watching the Railscast on Sidekiq, it talks about the creation of workers:
#app/controllers/invitations_controller.rb
class InvitationsController < ApplicationController
before_filter :require_user
def new
@invitation = Invitation.new
end
def create
@invitation = Invitation.create(invitation_params.merge!(inviter_id: current_user.id))
if @invitation.save
InivtationWorker.perform_async
flash[:success] = "You've successfully invited #{@invitation.recipient_name}."
redirect_to new_invitation_path
else
flash[:error] = "Please fill in all inputs."
render :new
end
end
#app/workers
class InvitationWorker
include Sidekiq::Worker
def perform(invitation_id)
invitation = Invitation.find(invitation_id)
AppMailer.send_invitation_email(invitation).deliver
end
end
But instead of creating workers, we can just use delayed extentions
#app/controlers/invitations_controller.rb
def create
@invitation = Invitation.create(invitation_params.merge!(inviter_id: current_user.id))
if @invitation.save
AppMailer.delay.send_invitation_email(@invitation.id)
flash[:success] = "You've successfully invited #{@invitation.recipient_name}."
redirect_to new_invitation_path
else
flash[:error] = "Please fill in all inputs."
render :new
end
end
Since we aren't running .perform_async on a worker, we need to pass @invitiation.id to the AppMailer:
#app/app_mailer.rb
def send_invitation_email(invitation_id)
@invitation = Invitation.find(invitation_id)
mail to: @invitation.recipient_email, from: "info@myflix.com", subject: "Invitation to join Myflix"
end
end
To run tests, you have to add the following to run them inline:
#spec/spec_helper.rb
require 'sidekiq/testing'
Sidekiq::Testing.inline!
Add the Mailgun add-on to your Heroku app through the command line (within your app project directory)
heroku addons:create mailgun
or you can add via their web interface
Then you copy and paste their smtp settings into your config/production.rb file. Make sure to change your domain name and add your default url options (which should point to your domain name) - if not, you will get an error: Errno::ECONNREFUSED: Connection refused - connect(2) for action mailer ...port(25)
config.action_mailer.delivery_method = :smtp
# SMTP settings for mailgun
config.action_mailer.smtp_settings = {
:port => ENV['MAILGUN_SMTP_PORT'],
:address => ENV['MAILGUN_SMTP_SERVER'],
:user_name => ENV['MAILGUN_SMTP_LOGIN'],
:password => ENV['MAILGUN_SMTP_PASSWORD'],
:domain => 'aqueous-coast-5067.herokuapp.com',
:authentication => :plain,
}
config.action_mailer.default_url_options = { :host => 'aqueous-coast-5067.herokuapp.com' }
You do not have to store the ENV variable in application.yml, you only have to run "heroku config" from your command line.