Skip to content

Running async ActiveJob jobs and displaying their progress to the user

Valentin Ballestrino edited this page Oct 4, 2016 · 3 revisions

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 :

  1. Create your job
  2. Create your controller
  3. Configure your view

1. Create your job

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

2. Create your controller

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

3. Configure your view

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.

Writing and translating modal texts

Every text content in the modal boxes needs to be translated with the following keys :

  • The modal title : activemodel.models.<job_key>(.one|.other), for our users exporter : activemodel.models.users_exporter
  • The progress, success and failure texts with : para.jobs.<job_key>.[progressing|success|error], which would result, for our users exporter in the following 3 keys : para.jobs.users_exporter.progressing, para.jobs.users_exporter.success and para.jobs.users_exporter.error

If you are using the errors handling mechanism, you'll also need to translate the following two keys :

  • para.jobs.users_exporter.success_with_errors
  • para.jobs.users_exporter.other_errors

Overriding the views

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.

You can override the default views

Clone this wiki locally