It's a Rails engine built on top of Active Job in order to improve user experience related to background processes. To achieve this goal, the gem allows us to:
- Relate jobs with entities
Using Active Job, you can perform background jobs but, you can not relate them with, for example, a logged user. Job Notifier allows you to connect an entity with a job easily.
- Persist job results
Using Active Job, you can run jobs in background but, you are not be able to store the result of those jobs. This is a desired behavior if you, for example, want to provide validation feedback to users.
- Notify users when their jobs change state.
Using Active Job, you can run jobs in background but, you lose a real time response. To bring a solution to this issue, Job Notifier, through polling technique, gives you a way to know what's happening with your jobs.
Add to your Gemfile:
gem "job_notifier"
bundle install
Run the installer:
rails generate job_notifier:install
The installer will copy
/config/initializers/job_notifier.rb
. There, you can change the default configuration.
Then, include notifier.js
where you go to use it. For example, in: /app/assets/javascripts/application.js
//= require job_notifier/notifier
- An entity (
current_user
for example), creates a job. - The job related to the
current_user
is queued with"pending"
status. - The
js
code stored onnotifier.js
executes, using the polling technique, a request asking for the jobs related to thecurrent_user
. The result is an array containing the created job with"pending"
status. - After a few seconds, a new request is performed but, this time, it returns an empty array. This occurs because the created job didn't change its status.
- After a couple of request with empty arrays, an object its returned with
"finished"
or"failed"
status and aresult
attribute containing feedback.
First, relate jobs with an entity (User
for example). To do this, include the JobNotifier::Identifier
mixin
in your entity class and execute the identify_job_through
method, passing the attributes you want to use to build the key to identify jobs for the entity. For example, if you have defined the User
class like this,
class User < ActiveRecord::Base
include JobNotifier::Identifier
identify_job_through :id, :email
end
user = User.create!(email: "leandro@platan.us")
# => #<User:0x007f877ef5c2a8 id: 1, email: "leandro@platan.us">
the jobs for user
will be identified by this code: "1b1bcc253675df5eb91603dbda06af11"
. (This is result of: Digest::MD5.hexdigest("email::leandro@platan.us::id::1")
, if you wanna know)
Second, pass to notifier.js
the identifier for that user. This is because the timed requests (polling) needs to know from what user bring the data. To do this, you can use the helper shipped in the gem:
<body <%= job_identifier_for(@current_user) %>>
<!-- Something like this is what the previous code produces -->
<body data-identifier="1b1bcc253675df5eb91603dbda06af11" data-root-url="/">
I'm assuming you have a
current_user
instance ofUser
class.
The previous code, takes the identifier from @current_user
and sets a data attribute, on body tag, that will be used in somewhere of notifier.js
to perform requests with a valid identifier.
To catch the response of polling requests, you can set a callback function:
JobNotifier.onNotify = function(data) {
console.info('On notify', data);
};
Now, you are be able to get feedback of your jobs but, you don't have any! so, the Third step is to define a job.
class MyJob < ApplicationJob
def perform_with_feedback(param1, param2)
MyService.run(param1, param2)
end
end
As you can see, the only difference with a regular ActiveJob's job is that you have perform_with_feedback
method instead of perform
method. Inside perform_with_feedback
you need to return the "success response" of your job. And, to save the "error response", you need to raise a JobNotifier::Error::Validation
exception. Let's see MyService#run
method definition to make it clear.
class MyService
def self.run(param1, param2)
return "SUCCESS!!!" if param1 == param2
raise JobNotifier::Error::Validation.new(error: "ERROR!!!")
end
end
If you define
perform
instead ofperform_with_feedback
, ActiveJob will work as always do.
The Fourth step is queue a new job. Executing JobNotifier::Job.where(identifier: current_user.job_identifier)
you can see jobs related with the passed identifier. So, according to MyService#run
definition:
The following code: MyJob.perform_later(current_user.job_identifier, "lean", "lean")
will create a new JobNotifier::Job
instance with:
result: nil
state: "pending"
After execution, the job will have:
result: "SUCCESS!!!"
state: "finished"
If this code MyJob.perform_later(current_user.job_identifier, "lean", "leandro")
is executed instead of the previous one, the result will be:
result: "ERROR!!!"
state: "failed"
If you are building an API or your client app is not part of the project you have installed this gem, you will need:
- To include the
notifier.js
using this url:http://your_app.platan.us/job_notifier/adapters/notifier
- To mimic the
job_identifier_for
functionality, passingdata-identifier
anddata-root-url
<body data-identifier="1b1bcc253675df5eb91603dbda06af11" data-root-url="http://your_app.platan.us/">
You can get the identifier executing in server side something like this: @current_user.job_identifier
(Remember, I'm assuming you have a @current_user
instance of User
class that includes the JobNotifier::Identifier
mixin).
The root url is your server url (where Job Notifier gem was installed).
On master/main branch...
- Change
VERSION
inlib/job_notifier/version.rb
. - Change
Unreleased
title to current version inCHANGELOG.md
. - Commit new release. For example:
Releasing v0.1.0
. - Create tag. For example:
git tag v0.1.0
. - Push tag. For example:
git push origin v0.1.0
.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Thank you contributors!
Job Notifier is maintained by platanus.
Job Notifier is © 2016 platanus, spa. It is free software and may be redistributed under the terms specified in the LICENSE file.