Git Product home page Git Product logo

active_waiter's Introduction

ActiveWaiter

Build Status

A simple mechanism allowing your users to wait for the completion of your ActiveJob

Scenario

You have an export PDF feature that you've implemented directly in the controller action.

As data grows, your HTTP request takes longer and starts timing out. So you decide to move the PDF generating code into a background job.

def index
  respond_to do |format|
    format.html
    format.pdf {
      ExportPdfJob.perform_later(@things, current_user)
      redirect_to :back, notice: "We'll email your PDF when it's done!"
    }
  end
end

But how do you get that PDF into the hands of your users now? Email? Push notification? Manual reload?

You have no PDF ready for download (yet). Please reload.

Solution

Let ActiveWaiter enqueue that job instead and redirect to its progress tracking page.

def index
  respond_to do |format|
    format.html
    format.pdf {
      uid = ActiveWaiter.enqueue(ExportPdfJob, @things, current_user)
      redirect_to active_waiter_path(id: uid)
    }
  end
end
# routes.rb
mount ActiveWaiter::Engine => "/active_waiter"

When the job completes, the user will be redirected to the url returned by the job. However, if you want the user to be presented with a download link, add download: 1 params instead

redirect_to active_waiter_path(id: uid, download: 1)

active_waiter mov

And we need to add a bit of code into your ActiveJob class

    1. add include ActiveWaiter::Job
    1. return a url from your perform method to link to the result page (or file)
class ExportPdfJob < ActiveJob::Base
  queue_as :default

  # (1)
  include ActiveWaiter::Job

  def perform(things, current_user)
    count = things.count.to_f
    files = []
    things.each_with_index do |thing, index|
      files << generate_pdf(thing)

      # (a)
      update_active_waiter percentage: (100 * (index+1) / count)
    end

    # (2)
    upload(combine(files)).s3_url
  rescue Exception => e

    # (b)
    update_active_waiter error: e.to_s
  end
end

Optionally, you can also

  • a) report progress while your job runs, using update_active_waiter(percentage:)
  • b) report if there were any errors, using update_active_waiter(error:)

Configuration

By default, ActiveWaiter uses a simple Bootstrap layout. To use your application's layout, configure:

ActiveWaiter.configure do |config|
  config.layout = "layouts/application"
end

Next, prefix any routes used in your application's layout with main_app., e.g. main_app.sign_in_path.

This is required because ActiveWaiter is a Rails Engine mounted into your application, and it doesn't know about the routes declared within your application.

Exceptions

When your job gets an exception, the error message will be written in the error message and passed along to the user. If your job has a method suppress_exceptions that returns a truthy value (default false), ActiveWaiter::Job will swallow the exception and not raise it - this means there will be no retry by ActiveJob.

Common Jobs

ActiveWaiter::EnumerableJob

If you need to wait, you're likely doing one thing slowly or many things. For the latter case, you can just include ActiveWaiter::EnumerableJob and add a few interface methods

def before(*args); end # called once with arguments of `perform`
def enumerable; [] end # an Enumerable interface
def items_count; 1 end # called 0-n times, depending on enumerable
def foreach(item); end # called 0-n times, depending on enumerable
def after;         end # called once
def result;        end # called once

Here's an example from our test code, that will generate an array of range 0...count and return the sum of all the numbers

class LoopJob < ActiveJob::Base
  include ActiveWaiter::EnumerableJob

  attr_accessor :items_count, :enumerable, :result

  def before(count)
    @items_count = count
    @enumerable = count.times
    @result = 0
  end

  def foreach(item)
    @result += item
  end
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.