-
Notifications
You must be signed in to change notification settings - Fork 9
Running async ActiveJob jobs and displaying their progress to the user
Para comes with a simple API to easily create interfaces that allow admin users to run long running tasks in the background and follow its progress.
This is an API used in the Para system to handle imports asynchronously, but available for anyone to use in their own admin controllers.
This works by letting your start a job and then delegating all the rest of the interface to Para.
Here are the few steps to implement such an interface :
- Create your job
- Create your controller
- Configure your view
First, create your job, in app/jobs/admin/my_job.rb
.
To allow the job's progress to be shown to the admin, you need to define the total_progress
method and use the #progress!
method when a sub-step has been complete.
Let's imagine we want to export all the users of the database to an Excel file, we'll set the total_pogress
to User.count
and use the #progress!
method each time we write a user to the file :
module Admin
class UsersExporter < Para::Job::Base
def perform
spreadsheet = ...
User.find_each do |user|
write_user_to(spreadsheet)
# Here we tell the job that we wrote a user
progress!
end
end
private
# Here we tell the job how many users we'll export
def total_progress
User.count
end
end
end
Now that your users are ready to be exported, you need to create your controller that will allow that job to run.
You'll create a controller inheriting from Para::Admin::JobsController
, start the job and pass it to the #track_job(job)
method, which will start progress tracking and render the appropriate modal window to the admin user.
# app/controllers/admin/users_exporter_controller.rb
module Admin
class UsersExporterController < Para::Admin::JobsController
def run
job = UsersExportJob.perform_later
track_job(job)
end
end
end
You can now create the route and add a link to the controller action you just defined.
First define the route in the para_at
block and in an admin
namespace.
# config/routes.rb
para_at '/' do
namespace :admin do
get 'export-users' => 'users_exporter#run', as: :users_export
end
end
Then add a remote link to your app, using the track-job
javascript plugin :
= link_to fa_icon(:download, text: 'Export users'), admin_export_users_path, remote: true, data: { :'track-job-button' => true }
Now when you click this link, the job is started and the user informed of the progress.
Now you file has been generated, but there's nowhere for the user to retrieve it easily since he just gets a message telling him that the job has completed successfully.