Skip to content

mvcodeclub/delayed_action

Repository files navigation

Delayed Action

Add asynchronous queuing to your HTTP requests with one line, via a controller concern.

The code:

class ArticlesController < ApplicationController
   include DelayedAction
   
   delayed_action [:show] 
   
   def show
     
   end
end

Sample Project

https://github.com/mvcodeclub/da_test

Who needs this

Many requests (reports, admin requests, data dumps,) often take longer than a typical HTTP timeout, and it is quite tedious to have to queue things up. The code looks identical to a normal page request, the only difference is that it's expected to take a longer time to execute. Right now, you are forced to package things up into ActiveJob or other queuing mechanisms manually, and there's lots of duplicated code.

It should be easy to switch between a queued request and a normal synchronous HTTP request.

Some Scenarios:

  • You are receiving lots of timeouts in your application because your queries run longer than your timeout settings, this is the gem for you.
  • A common scenario is running your app on Heroku, you may receive RackTimeout or Heroku H13 errors.
  • You often send these requests via email to users, even though it's awkward and non-standard. Users are generally fine to wait 30 seconds or even a few minutes, and it's easier to just keep the tab open in your browser than to have to check your email.

Most existing solutions encourage you to package up your request as an ActiveJob or similar, and then do a bunch of boilerplate work to unwrap things and show your request.

Rather than tediously rewriting your controller method as a background job, just add this gem and one statement and it will get packaged up as a background job and will run when it's completed.

Prerequisites

  • Rails 4
  • ActiveJob
  • A queue provider, such as DelayedJob or Resque

NOTE: This will not work and cause bad things to happen if you try to use the default inline ActiveJob provider

How to use:

Add to your gemfile: gem "delayed_action"

Install the Migration rake delayed_action:install:migrations

Run the migration rake db:migrate

Add a delayed_action to your controller

class ArticlesController < ApplicationController
   include DelayedAction
   
   delayed_action [:show] # the show method will be queued
   
   def index
   
   end
   
   def show # use this as normal
   
   end
end

Todo:

  • Better "Refresh the page" UI needed.
  • Conditional (:if / :unless) blocks would be nice to turn it on / off
  • Expiration of requests
  • Test under load

Example:

class AccountController < ApplicationController

  delayed_action [:run_report]

  def run_report
    # this takes a long time and fails!
    @report = @account.run_really_long_report
  end

end

How it works

DelayedAction intercepts calls to actions you specify. If it finds one, it queues up a request to a job which will run the action on a job queue. It then redirects to your page, with the UUID of the result.

The request runs on the thread that services the ActiveJob queue, not the web thread.

If it sees the UUID on the querystring, it loads the resulting HTML from the database.

It uses app.get to call your functions, and passes on most of the cookies and environment variables to the request so it can be authenticated.

Gotchas

Don't use ActiveJob's default (ActiveJobInline) as this will probably cause a deadlock. Queues need to run out of process.

All of your requests are stored in the DelayedActionResults table. This could get large, and there's no cleanup functionality currently. You have to clean it up yourself

You need to think about security.

It only currently works on GET requests (not POST etc)

Features:

  • Works with ActiveRecord
  • Work with DelayedJob / Postgres
  • Supports Rack::Timeout
  • Work with configurable to any queue or ActiveJob
  • Works with any mime-type

How to report bugs

Please use our github issues page to report bugs or feature requests

About

Delay rails controller actions in one line of code

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published