Active Job: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(52 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Introduction ==
== '''Introduction''' ==
Active Job is a framework help developers writing codes and run them on the background automatically under different scenarios. Jobs can vary from schedule newsletter, follow-up emails to database housekeeping. It’s a interface that adapts different queueing backends like Backburner[https://github.com/nesquena/backburner], Delayed Job[https://github.com/collectiveidea/delayed_job], Qu[https://github.com/bkeepers/qu] and so on. <ref>http://guides.rubyonrails.org/active_job_basics.html</ref> Overall, Active Job is a interface which you can work with common queues.
Active Job is a framework that helps developers to write codes and run them on the background automatically under different scenarios. It’s an interface that adapts various queueing backends like [https://github.com/nesquena/backburner Backburner], [https://github.com/collectiveidea/delayed_job Delayed Job], [https://github.com/bkeepers/qu Qu] and so on. Jobs can vary from schedule newsletters, follow-up emails to database housekeeping. <ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” ]</ref> Overall, Active Job is an interface which you can work with common queueing backends.  
The reason to have Active Job in place is to make sure Rails apps can have a job infrastructure. Other existing gems can build on this framework without the limitation of API difference between different job runners such as Delayed Job and Resque. With this feature choosing queueing backends can become an operational concern. Also, switching between those queueing backends without rewrite jobs become possible.<ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” ]</ref>


__TOC__
__TOC__


====Active Job adapters<ref>http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html</ref>====
====Ruby On Rails versions support Active Job====
{| class="wikitable sortable" style="float:left;"
|+ Version history
|-
! Version !! Date
|-
| 4.2 || 2014/12/19
|-
| 4.2.5 || 2015/11/13
|-
|}
<br><br><br><br><br><br>
====Active Job adapters<ref name="Active-Job-Adapter">Active Job Adapter[http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html"Active Job Adapter" ]</ref>====
List of queueing backends Active Job support:
*Backburner[https://github.com/nesquena/backburner]
*Backburner[https://github.com/nesquena/backburner]
*Delayed Job[https://github.com/collectiveidea/delayed_job]
*Delayed Job[https://github.com/collectiveidea/delayed_job]
Line 18: Line 32:


=='''How to use <ref>http://guides.rubyonrails.org/active_job_basics.html</ref>'''==
=='''How to use <ref>http://guides.rubyonrails.org/active_job_basics.html</ref>'''==
We will introduce how to creating a job and and how to add the job into a queue. <ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” 2014]</ref> <br>
This chapter is an introduction on how to create a job and and how to add the job into a queue. <ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” 2014]</ref> <br>
=== Download ===
=== Download ===
Active Job can be installed with latest version using RubyGems:
With RubyGems[https://en.wikipedia.org/wiki/RubyGems] you can install Active Job:
<pre>
<pre>
$ gem install activejob
$ gem install activejob
</pre>
</pre>


[https://github.com/rails/rails/tree/master/activejob Souce code of Active Job] available on GitHub, as part of Rails.<ref> GitHub [https://github.com/rails/rails/tree/master/activejob “Active Job -- Make work happen later” 2015] </ref>
[https://github.com/rails/rails/tree/master/activejob Souce code of Active Job] available on GitHub[https://en.wikipedia.org/wiki/GitHub], as part of Rails.<ref> GitHub [https://github.com/rails/rails/tree/master/activejob “Active Job -- Make work happen later” 2015] </ref>


=== Create a Job ===
=== Create a Job ===
In Active Job, a process which is inserted in a queue and waiting for carry out is called “Job”. It’s possible to generate a Job using the Generator provided by Rails. The following will create a job in app/jobs, with the name “update_wiki”.<br>
In Active Job, a process inserted in a queue and waiting to carry out is called “Job”. It’s possible to generate a Job using the Generator provided by Rails. You can create a Job in app/jobs. By doing the following, we created a Job called “update_wiki”.<br>
<pre>
<pre>
$ bin/rails generate job update_wiki
$ bin/rails generate job update_wiki
Line 35: Line 49:
   create  app/jobs/update_wiki_job.rb
   create  app/jobs/update_wiki_job.rb
</pre>
</pre>
You can also create a job that will run on a specific queue:<br>
Active Job provides the ability to run your Job on a specific queue by creating a job:<br>
<pre>
<pre>
$ bin/rails generate job update_wiki --queue urgent
$ bin/rails generate job update_wiki --queue urgent
</pre>
</pre>
You could create your own file inside of app/jobs, without using a generator. In Rails 4.2 an ActiveJob inherits from ActiveJob::Base. In Rails 5.0 this behavior has changed to now inherit from ApplicationJob. When upgrading from Rails 4.2 to Rails 5.0 you need to create an application_job.rb file in app/jobs/ and add the following content:<ref> Rails Guides [http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-4-1-to-rails-4-2 “A Guide for Upgrading Ruby on Rails” 2015] </ref>
Files inside of app/jobs can be created manually, instead of using a generator. In Rails 4.2 an ActiveJob class inherits from ActiveJob::Base. In Rails 5.0, it has changed to now inherit from ApplicationJob. When upgrading from Rails 4.2 to Rails 5.0, an application_job.rb file is needed to be created in app/jobs/ and add the following content:<ref> Rails Guides [http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-4-1-to-rails-4-2 “A Guide for Upgrading Ruby on Rails” 2015] </ref>
<pre>
<pre>
class ApplicationJob < ActiveJob::Base
class ApplicationJob < ActiveJob::Base
end
end
</pre>
</pre>
In Rails 4.2 a Job class looks like:
In Rails 4.2 a Job class defined a perform method and set a “queue_as” value:
<pre>
<pre>
class UpdateWikiJob < ActiveJob::Base
class UpdateWikiJob < ActiveJob::Base
Line 55: Line 69:
end
end
</pre>
</pre>
There is a perform method which is called when the job was first enqueued. You can define perform with as many arguments as you want. <br>
There is a perform method to be called when the Job was first enqueued. <br>


=== Adding a Job to the queue ===
=== Adding a Job to the queue ===
If you wish your Job be processed as soon as the queuing system is free, you can enqueue a Job like:
Enqueue the Job so it can be processed as soon as the queuing system is free:
<pre>
<pre>
UpdateWikiJob.perform_later wiki
UpdateWikiJob.perform_later wiki
</pre>
</pre>
Or you can add a Job be performed tomorrow at noon:
Or add a Job be performed tomorrow at noon:
<pre>
<pre>
UpdateWikiJob.set(wait_until: Date.tomorrow.noon).perform_later(wiki)
UpdateWikiJob.set(wait_until: Date.tomorrow.noon).perform_later(wiki)
</pre>
</pre>
If you want your Job be performed a week from now, some queueing backends allow you to set a delay time.
Most of the queueing backends ( Sidekiq
, Delayed Job, etc. ) allow you to set a delay time.
<pre>
<pre>
UpdateWikiJob.set(wait: 1.week).perform_later(wiki)
UpdateWikiJob.set(wait: 1.week).perform_later(wiki)
</pre>
</pre>
=== Execution of Job ===
=== Execution of Job ===
Active Job has built-in adapters for multiple queueing backends ([https://github.com/mperham/sidekiq/wiki Sidekiq], [https://github.com/resque/resque Resque], [https://github.com/collectiveidea/delayed_job Delayed Job] and [http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html others]).<ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” 2014]</ref> If no adapter is set, the job is immediately executed.<br>
Active Job provides adapters for multiple queueing backends ([https://github.com/mperham/sidekiq/wiki Sidekiq], [https://github.com/resque/resque Resque], [https://github.com/collectiveidea/delayed_job Delayed Job] and [http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html others]).<ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” 2014]</ref> Without setting any adapter, the job would be performed immediately.<br>
You can set your queueing backend at: /config/application.rb, in this example we use the Sidekiq.
Queueing backend can be set at: /config/application.rb, this example uses the Sidekiq.
<pre>
<pre>
module YourApp
module YourApp
Line 90: Line 105:
end
end
</pre>
</pre>
You can prefix the queue name for all your jobs using config.active_job.queue_name_prefixin application.rb:
Queue name can be prefixed for all jobs using config.active_job.queue_name_prefixin application.rb:
<pre>
<pre>
# config/application.rb
# config/application.rb
Line 99: Line 114:
end
end
   
   
# app/jobs/guests_cleanup.rb
# app/jobs/update_wiki_job.rb
class UpdateWikiJob < ActiveJob::Base
class UpdateWikiJob < ActiveJob::Base
   queue_as :low_priority
   queue_as :low_priority
Line 111: Line 126:




The default queue name prefix delimiter is '_'. This can be changed by setting config.active_job.queue_name_delimiter in application.rb:
Control a job to run on a queue by passing a :queue option to #set :
<pre>
<pre>
# config/application.rb
MyJob.set(queue: :another_queue).perform_later(record)
module YourApp
</pre>
   class Application < Rails::Application
 
     config.active_job.queue_name_prefix = Rails.env
All the code snippets are referred from the source<ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” 2014]</ref>
    config.active_job.queue_name_delimiter = '.'
 
== Examples ==
In this section, a example is provided to demonstrate how to use ActiveJob in practice.
=== Background Mail Sender ===
Send emails asynchronously with Action Mailer which Active Job is already integrated in.<ref name= "Action-Mailer-Basics">Rails Guides [http://guides.rubyonrails.org/action_mailer_basics.html “Action Mailer Basics” 2014]</ref> Here in this example, we try to use Active Job with Action Mailer.<br>
==== 1. Getting started with Rails<ref name= "Welcome_to_Rails">GitHub [https://github.com/rails/rails “Welcome to Rails” 2015]</ref> ====
<pre>
# Install Rails if you haven’t done it yet:
$ gem install rails
 
# Create a new Rails application, “myapp_activejob”
# is the name of the application:
$ rails new myapp_activejob
 
# Change your directory to myapp_activejob
$ cd myapp_activejob
</pre>
Edit the Gemfile in the folder, add following into it:
<pre>
gem 'responders'
</pre>
Run “ $ bundle update “ and make sure “$ rails server” works.
 
==== 2. Resque setup<ref name= "Download_Redis">Redis [http://redis.io/download “Download Redis” 2016]</ref>====
This example uses [https://github.com/resque/resque Resque] as the enqueuing backend. It'll need  [http://redis.io/ Redis] before running Resque. Redis can be installed using [http://brew.sh/ Homebrew]:
<pre>
$ brew install redis
</pre>
Or  download, extract and compile Redis using:<ref name= "Download_Redis">Redis [http://redis.io/download “Download Redis” 2016]</ref>
<pre>
$ wget http://download.redis.io/releases/redis-3.0.7.tar.gz
$ tar xzf redis-3.0.7.tar.gz
$ cd redis-3.0.7
$ make
</pre>
Redis does not officially support Microsoft [https://en.wikipedia.org/wiki/Microsoft_Windows Windows] platform, but it can be found  [https://github.com/MSOpenTech/redis Redis on Windows] by Microsoft Open Tech group.<br>
Next get Resque be installed. To use resque with Active Job, we also need resque-scheduler.
Add the following into Gemfile, and run “$ bundle install”.
<pre>
gem 'resque'
gem 'resque-scheduler'
</pre>
After the installation, create a Resque configuration file resque.rb in config/initializers/
<pre>
#config/initializers/resque.rb
 
Resque.redis = Redis.new(host: 'localhost', post: 6379)
Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection }
</pre>
 
As the Resque tasks and Resque Scheduler rake tasks are needed in this example, we need to create a resque.rake file in lib/tasks/:
 
<pre>
#lib/tasks/resque.rake
 
require 'resque/tasks'
require 'resque/scheduler/tasks'
 
namespace :resque do
   task setup: :environment do
     ENV['TERM_CHILD'] ||= '1'
    ENV['QUEUE'] ||= '*'
    require 'resque'
    require 'resque-scheduler'
  end
end
</pre>
 
==== 3. Creating a Mailer<ref name= "Action-Mailer-Basics">Rails Guides [http://guides.rubyonrails.org/action_mailer_basics.html “Action Mailer Basics” 2014]</ref> ====
By doing the things above, we already have our Rails project and the Resque for queuing get set. Next we will create a Mailer.
 
<pre>
$ bin/rails generate mailer user_mailer
</pre>
 
Create a method and a view for sending the email.<br>
In app/mailer/user_mailer.rb:
 
<pre>
#app/mailers/user_mailer.rb
 
class UserMailer < ActionMailer::Base
  default from: 'from@example.com'
 
  def test_email(email)
    mail(
      to: email,
      subject: 'We are testing Active Job!'
    )
   end
   end
end
end
</pre>
# app/jobs/guests_cleanup.rb
In app/views/user_mailer/test_email.text
class UpdateWikiJob < ActiveJob::Base
<pre>
   queue_as :low_priority
#app/views/user_mailer/test_email.text
   #....
 
Hey, we are testing Active Job!
</pre>
 
==== 4. Active Job<ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” 2014]</ref>====
Create a configuration file active_job.rb in config/initializers/ , to set Resque as queue_adapter.
<pre>
#config/initializers/active_job.rb
 
ActiveJob::Base.queue_adapter = :resque
</pre>
 
Create a Job with generator.
<pre>
$ bin/rails generate job test_email
</pre>
 
In the generated file app/jobs/test_email_job.rb, define the perform method and set it’s queue_as.
 
<pre>
#app/jobs/test_email_job.rb
 
class TestEmailJob < ActiveJob::Base
   queue_as :email
 
   def perform(email)
    UserMailer.test_email(email).deliver_now
  end
end
end
# Now your job will run on queue production.low_priority on your
# production environment and on staging.low_priority on your staging
# environment
</pre>
</pre>
If you want more control on what queue a job will be run you can pass a :queue option to #set:
 
Now a UserController is in place to put the job into the queue for later execution. Set the email to be sent one minute later for testing.
<pre>
<pre>
MyJob.set(queue: :another_queue).perform_later(record)
$ bin/rails generate job test_email
</pre>
</pre>
To control the queue from the job level you can pass a block to #queue_as. The block will be executed in the job context (so you can access self.arguments) and you must return the queue name:
 
<pre>
<pre>
class ProcessVideoJob < ActiveJob::Base
#app/controllers/users_controller.rb
   queue_as do
 
     video = self.arguments.first
class UsersController < ApplicationController
    if video.owner.premium?
   def new
      :premium_videojobs
     @user = User.new
    else
      :videojobs
    end
   end
   end
 
   def perform(video)
   def create
     # do process video
    @user = User.create(user_params)
    TestEmailJob.new(@user.email).deliver_later!(wait: 1.minute)
     # redirect somewhere
   end
   end
end
end
</pre>
ProcessVideoJob.perform_later(Video.last)
 
Routes and views need to be set in order to make it work.
<pre>
#config/routes.rb
 
Rails.application.routes.draw do
  resources :users, only: [:new, :create]
end
</pre>
 
<pre>
#app/views/users/new.html.erb
 
<%= form_for @user do |f| %>
  <%= f.email_field :email %>
  <%= f.submit %>
<% end %>
</pre>
 
==== 5. Try execution ====
Before trying the Mailer, MailCatcher[https://rubygems.org/gems/mailcatcher/versions/0.6.1] is needed for the test. Add following into Gemfile and “$ bundle install”
<pre>
gem 'mailcatcher'
</pre>
 
To set the environment, one need to add the following into config/environments/development.rb.
<pre>
#config/environments/development.rb
 
Rails.application.configure do
  ...
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
end
</pre>
 
Run it!
<pre>
# Start mailcatcher
$ mailcatcher
 
# Start redis-server
$ redis-server
 
# Start resque:work
$ bundle exec rake resque:work
 
# Start resque:scheduler
$ rake environment resque:scheduler
 
# Finally start rails server
$ rails server
</pre>
 
Open the browser and visit localhost:3000/users/new. Then sign up as a new user. One minute later Resque scheduler has following output:


<pre>
resque-scheduler: [INFO] 2016-02-05T22:53:15+09:00: Processing Delayed Items
</pre>
And in MailCatcher:
<pre>
==> SMTP: Received message from '<from@example.com>' (315 bytes)
</pre>
</pre>


All the code snippets are referred from the source<ref name= "Active-Job-Basics">Rails Guides [http://guides.rubyonrails.org/active_job_basics.html “Active Job Basics” 2014]</ref>
=='''External links'''==
 
*[http://www.rubyonrails.org/ Ruby on Rails official website] – rubyonrails.org
*[http://railscasts.com/ Railscasts.com] – (defunct) Short Screencasts that focus on Ruby on Rails technique
*[http://rubycasts.io/ Rubycasts.io] – Weekly 15 minute screencasts on the whole Ruby/Rails development stack
*[http://www.railstutorial.org/ The Rails Tutorial] – The Ruby on Rails Tutorial book and screencast series teach you how to develop and deploy Ruby on Rails apps
*[https://github.com/rails/rails Rails source code]


=='''References'''==
=='''References'''==
<references/>
<references/>

Latest revision as of 22:27, 28 March 2016

Introduction

Active Job is a framework that helps developers to write codes and run them on the background automatically under different scenarios. It’s an interface that adapts various queueing backends like Backburner, Delayed Job, Qu and so on. Jobs can vary from schedule newsletters, follow-up emails to database housekeeping. <ref name= "Active-Job-Basics">Rails Guides “Active Job Basics” </ref> Overall, Active Job is an interface which you can work with common queueing backends. The reason to have Active Job in place is to make sure Rails apps can have a job infrastructure. Other existing gems can build on this framework without the limitation of API difference between different job runners such as Delayed Job and Resque. With this feature choosing queueing backends can become an operational concern. Also, switching between those queueing backends without rewrite jobs become possible.<ref name= "Active-Job-Basics">Rails Guides “Active Job Basics” </ref>

Ruby On Rails versions support Active Job

Version history
Version Date
4.2 2014/12/19
4.2.5 2015/11/13







Active Job adapters<ref name="Active-Job-Adapter">Active Job Adapter"Active Job Adapter" </ref>

List of queueing backends Active Job support:

How to use <ref>http://guides.rubyonrails.org/active_job_basics.html</ref>

This chapter is an introduction on how to create a job and and how to add the job into a queue. <ref name= "Active-Job-Basics">Rails Guides “Active Job Basics” 2014</ref>

Download

With RubyGems[11] you can install Active Job:

$ gem install activejob

Souce code of Active Job available on GitHub[12], as part of Rails.<ref> GitHub “Active Job -- Make work happen later” 2015 </ref>

Create a Job

In Active Job, a process inserted in a queue and waiting to carry out is called “Job”. It’s possible to generate a Job using the Generator provided by Rails. You can create a Job in app/jobs. By doing the following, we created a Job called “update_wiki”.

$ bin/rails generate job update_wiki
  invoke  test_unit
  create  test/jobs/update_wiki_job_test.rb
  create  app/jobs/update_wiki_job.rb

Active Job provides the ability to run your Job on a specific queue by creating a job:

$ bin/rails generate job update_wiki --queue urgent

Files inside of app/jobs can be created manually, instead of using a generator. In Rails 4.2 an ActiveJob class inherits from ActiveJob::Base. In Rails 5.0, it has changed to now inherit from ApplicationJob. When upgrading from Rails 4.2 to Rails 5.0, an application_job.rb file is needed to be created in app/jobs/ and add the following content:<ref> Rails Guides “A Guide for Upgrading Ruby on Rails” 2015 </ref>

class ApplicationJob < ActiveJob::Base
end

In Rails 4.2 a Job class defined a perform method and set a “queue_as” value:

class UpdateWikiJob < ActiveJob::Base
  queue_as :default
 
  def perform(*wiki)
   # Do something later
  wiki.update_contents
  end
end

There is a perform method to be called when the Job was first enqueued.

Adding a Job to the queue

Enqueue the Job so it can be processed as soon as the queuing system is free:

UpdateWikiJob.perform_later wiki

Or add a Job be performed tomorrow at noon:

UpdateWikiJob.set(wait_until: Date.tomorrow.noon).perform_later(wiki)

Most of the queueing backends ( Sidekiq , Delayed Job, etc. ) allow you to set a delay time.

UpdateWikiJob.set(wait: 1.week).perform_later(wiki)

Execution of Job

Active Job provides adapters for multiple queueing backends (Sidekiq, Resque, Delayed Job and others).<ref name= "Active-Job-Basics">Rails Guides “Active Job Basics” 2014</ref> Without setting any adapter, the job would be performed immediately.
Queueing backend can be set at: /config/application.rb, this example uses the Sidekiq.

module YourApp
  class Application < Rails::Application
    # Be sure to have the adapter's gem in your Gemfile and follow
    # the adapter's specific installation and deployment instructions.
    config.active_job.queue_adapter = :sidekiq
  end
end

Play with Queues

Active Job allows to schedule the job to be processed on a specific queue, this became helpful as common adapters support multiple queues.

class UpdateWikiJob < ActiveJob::Base
  queue_as :low_priority
  #....
end

Queue name can be prefixed for all jobs using config.active_job.queue_name_prefixin application.rb:

# config/application.rb
module YourApp
  class Application < Rails::Application
    config.active_job.queue_name_prefix = Rails.env
  end
end
 
# app/jobs/update_wiki_job.rb
class UpdateWikiJob < ActiveJob::Base
  queue_as :low_priority
  #....
end
 
# Now your job will run on queue production_low_priority on your
# production environment and on staging_low_priority on your staging
# environment


Control a job to run on a queue by passing a :queue option to #set :

MyJob.set(queue: :another_queue).perform_later(record)

All the code snippets are referred from the source<ref name= "Active-Job-Basics">Rails Guides “Active Job Basics” 2014</ref>

Examples

In this section, a example is provided to demonstrate how to use ActiveJob in practice.

Background Mail Sender

Send emails asynchronously with Action Mailer which Active Job is already integrated in.<ref name= "Action-Mailer-Basics">Rails Guides “Action Mailer Basics” 2014</ref> Here in this example, we try to use Active Job with Action Mailer.

1. Getting started with Rails<ref name= "Welcome_to_Rails">GitHub “Welcome to Rails” 2015</ref>

# Install Rails if you haven’t done it yet:
$ gem install rails

# Create a new Rails application, “myapp_activejob”
# is the name of the application:
$ rails new myapp_activejob

# Change your directory to myapp_activejob
$ cd myapp_activejob

Edit the Gemfile in the folder, add following into it:

gem 'responders'

Run “ $ bundle update “ and make sure “$ rails server” works.

2. Resque setup<ref name= "Download_Redis">Redis “Download Redis” 2016</ref>

This example uses Resque as the enqueuing backend. It'll need Redis before running Resque. Redis can be installed using Homebrew:

$ brew install redis

Or download, extract and compile Redis using:<ref name= "Download_Redis">Redis “Download Redis” 2016</ref>

$ wget http://download.redis.io/releases/redis-3.0.7.tar.gz
$ tar xzf redis-3.0.7.tar.gz
$ cd redis-3.0.7
$ make

Redis does not officially support Microsoft Windows platform, but it can be found Redis on Windows by Microsoft Open Tech group.
Next get Resque be installed. To use resque with Active Job, we also need resque-scheduler. Add the following into Gemfile, and run “$ bundle install”.

gem 'resque'
gem 'resque-scheduler'

After the installation, create a Resque configuration file resque.rb in config/initializers/

#config/initializers/resque.rb

Resque.redis = Redis.new(host: 'localhost', post: 6379)
Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection }

As the Resque tasks and Resque Scheduler rake tasks are needed in this example, we need to create a resque.rake file in lib/tasks/:

#lib/tasks/resque.rake

require 'resque/tasks'
require 'resque/scheduler/tasks'

namespace :resque do
  task setup: :environment do
    ENV['TERM_CHILD'] ||= '1'
    ENV['QUEUE'] ||= '*'
    require 'resque'
    require 'resque-scheduler'
  end
end

3. Creating a Mailer<ref name= "Action-Mailer-Basics">Rails Guides “Action Mailer Basics” 2014</ref>

By doing the things above, we already have our Rails project and the Resque for queuing get set. Next we will create a Mailer.

$ bin/rails generate mailer user_mailer

Create a method and a view for sending the email.
In app/mailer/user_mailer.rb:

#app/mailers/user_mailer.rb

class UserMailer < ActionMailer::Base
  default from: 'from@example.com'

  def test_email(email)
    mail(
      to: email,
      subject: 'We are testing Active Job!'
    )
  end
end

In app/views/user_mailer/test_email.text

#app/views/user_mailer/test_email.text

Hey, we are testing Active Job!

4. Active Job<ref name= "Active-Job-Basics">Rails Guides “Active Job Basics” 2014</ref>

Create a configuration file active_job.rb in config/initializers/ , to set Resque as queue_adapter.

#config/initializers/active_job.rb

ActiveJob::Base.queue_adapter = :resque

Create a Job with generator.

$ bin/rails generate job test_email

In the generated file app/jobs/test_email_job.rb, define the perform method and set it’s queue_as.

#app/jobs/test_email_job.rb

class TestEmailJob < ActiveJob::Base
  queue_as :email

  def perform(email)
    UserMailer.test_email(email).deliver_now
  end
end

Now a UserController is in place to put the job into the queue for later execution. Set the email to be sent one minute later for testing.

$ bin/rails generate job test_email
#app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.create(user_params)
    TestEmailJob.new(@user.email).deliver_later!(wait: 1.minute)
    # redirect somewhere
  end
end

Routes and views need to be set in order to make it work.

#config/routes.rb

Rails.application.routes.draw do
  resources :users, only: [:new, :create]
end
#app/views/users/new.html.erb

<%= form_for @user do |f| %>
  <%= f.email_field :email %>
  <%= f.submit %>
<% end %>

5. Try execution

Before trying the Mailer, MailCatcher[13] is needed for the test. Add following into Gemfile and “$ bundle install”

gem 'mailcatcher'

To set the environment, one need to add the following into config/environments/development.rb.

#config/environments/development.rb

Rails.application.configure do
  ...
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
end

Run it!

# Start mailcatcher
$ mailcatcher

# Start redis-server
$ redis-server

# Start resque:work
$ bundle exec rake resque:work

# Start resque:scheduler
$ rake environment resque:scheduler

# Finally start rails server
$ rails server

Open the browser and visit localhost:3000/users/new. Then sign up as a new user. One minute later Resque scheduler has following output:

resque-scheduler: [INFO] 2016-02-05T22:53:15+09:00: Processing Delayed Items

And in MailCatcher:

==> SMTP: Received message from '<from@example.com>' (315 bytes)

External links

References

<references/>