Create Ruby on Rails scheduler with Sidekiq and Whenever

When developing web applications, I often encounter a need of implementing some background jobs run regularly. With Ruby on Rails, we have many powerful gems helping us write background job, and sidekiq is a good option. How about scheduling the job to run daily in certain time? You can use crontab on server, set scheduler using curl command to call an API. However, it requires you knowledge about system. Thanks towhenever gem which makes our task much easier in Rails.

Dependencies

Sidekiq is simple, efficient background processing which enqueues your jobs in Redis using multiple threads to run as many jobs as it can in the same time.

Thus, in order to make it work, you will initially need to install Redis on your server. Below is short version how to install Redis on Ubuntu server ( You can ignore this part if you installed Redisbefore )

sudo apt-get update 
sudo apt-get install build-essential tcl 
cd /tmp curl -O http://download.redis.io/redis-stable.tar.gz 
tar xzvf redis-stable.tar.gz 
cd redis-stable 
make 
make test 
sudo make install 
sudo mkdir /etc/redis 
sudo cp /tmp/redis-stable/redis.conf /etc/redis 
sudo nano /etc/redis/redis.conf

Then, to continue, you need to update you config file

# /etc/redis/redis.conf 
# ... 
# change this line 
supervised no 
# to this line 
supervised systemd 
# And change this line 
dir . 
# To 
dir /var/lib/redis

After that, create redis systemd unit file

sudo nano /etc/systemd/system/redis.service

With below content

[Unit]
Description=Redis In-Memory Data Store
After=network.target
[Service]
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/bin/redis-cli shutdown
Restart=always
[Install]
WantedBy=multi-user.target

What you need is to run some more commands to make it run

sudo adduser --system --group --no-create-home redis
sudo mkdir /var/lib/redis
sudo chown redis:redis /var/lib/redis
sudo chmod 770 /var/lib/redis
# to start redis
sudo systemctl start redis
# to enable redis at start boot
sudo systemctl enable redis

Installing Gems

In this article I assume that you’ve already known at least basic Ruby on Rails. You will need to add these gems to your Gemfile

gem 'sidekiq' 
gem 'whenever'

Then, as usual, you need to run bundle install

Run sidekiq web

Before writing any Sidekiq worker, you can do some minor extra jobs to make its management board available on your website on url/sidekiq

require'sidekiq/web' 
Rails.application.routes.draw do 
  mount Sidekiq::Web => '/sidekiq' 
  # .... 
end

Create background jobs

By default, your Sidekiq background jobs will be managed in app/workers folder. Each job will have a separated worker class lying in a worker file. You can manually create workers folder then create a worker class, or use worker generator

rails g sidekiq:worker Hard

The above command will generate HardWorker class for you

class HardWorker 
  include Sidekiq::Worker 
  def perform(*args) 
    # do something 
  end 
end

In case you have a rake task, and you want to run the task in your background job

class HardWorker 
  include Sidekiq::Worker 
  def perform(*args)
    YourAppName::Application.load_tasks
    Rake::Task['YOUR_RAKE_TASK'].invoke
  end 
end

Schedule your job

Now, You already know how to setup your background job. It’s time to start scheduling your job with whenever.

After installing the gem, you must run wheneverize . to initialize whenever for your application. This command will generate the file config/schedule.rb

It’s time to start writing your scheduler job

job_type :sidekiq, "cd :path && :environment_variable=:environment bundle exec sidekiq-client push :task :output"
every 30.minutes, :roles => [:app] do
  sidekiq "HardWorker"
end

It’s all about writing scheduler job. Now, you need to update the scheduled jobs to system

whenever --update-crontab

You can see all cron jobs by crontab -l or remove jobs by
crontab -r

Last but not least, you need to start you sidekiq in order to run background jobs

bundle exec sidekiq -d -L log/sidekiq.log

Happy Coding!

Published by

Colin Dao

I am a hardworking Rubyist in Hanoi, Vietnam

Leave a comment