Nowadays, almost Rails applications have more than a web process (start with rails s
). They often contain a web process (rails s
) and some background processes (Delayed Job, Resque...).
So far so good, this helps us to improve application performance or UX. But, how can we start our application, assume that we have 1 web process, 3 Delayed Job workers (for 3 different queues) and 1 Clock process for scheduling? You may said: it is so easy, just some commands
bundle exec rails s
bundle exec rake jobs:work --queue=mailer
bundle exec rake jobs:work --queue=importer
bundle exec rake jobs:work --queue=tasks
bundle exec clockwork clock.rb
It seems easy! But not convenient! Imagine that you will need to open 5 terminal tabs and run above 5 commands multiple times each day. Unless you have special hobby with repeating them, you will pray or find for easier way to start your application.
Solution
Of course, you can use shell script to simplify above process but you will meet many issues, such as: stop them, view logs...
The best solution that I know is using Foreman. It helps us to run as many processes as we want with only 1 command as well as stop all of them with 1 Ctrl + C
. It also shows logs of all processes with different color for each process.
Using foreman
is simple
- Add
foreman
gem to yourGemfile
- Run
bundle install
- Create
Procfile
file in your application root - Add your commands to
Procfile
- Run
foreman start
Example Procfile
for above 5 commands
web: bundle exec rails s
mailer_worker: bundle exec rake jobs:work --queue=mailer
importer_worker: bundle exec rake jobs:work --queue=importer
tasks_worker: bundle exec rake jobs:work --queue=tasks
clock: bundle exec clockwork clock.rb
As you can see, each line of Procfile
contains 2 parts: <process type>:<process command>
- Process type (web/mailer_worker/clock...): type of process, it is not needed to be in a predefined list, name it anything compatible with you
- Process command: command to start the process. Because
Procfile
can also be used (or exported to be used) on production environments (Heroku is an example), some of them don't install gems to global environment but install gems to local place likevendor
, so we need to usebundle exec
to run commands related to gems inGemfile
. Research about bundler to know more about thebundle exec
.
Notice: web: bundle exec rails s
in above Procfile
will start rails server on port 5000
instead of 3000
because foreman
assign ports from 5000
and each process type has 100 port slots. So, with above Procfile
, web
type will have port 5000
, mailer_worker
will have port 5100
(worker doesn't need a port but foreman
still give it port slots to make it consistent) and so on... You can change rails s
port by adding -p
option, but you should not do it if you are using Heroku because Heroku expects default ports of foreman
.
When I mention 100 port slots for each type, you may have a question: "What is it for? I see the commands create only 1 process, no need to have 100 port slots". Foreman
does this because we can start multiple process for each process type (that is also why I called it process type
instead of process name
).
In above Procfile
, if we want to have 2 importer_worker
and 3 tasks_worker
, we will start Foreman
with command
foreman start -c importer_worker=2,tasks_worker=3
Default process count for each type is 1, so we don't need to specify process count for web
and clock
type.