No commit activity in last 3 years
No release in over 3 years
This gem allows you to background any method call without having to write a special job class. Heavily inspired by the Backgroundable module in TorqueBox.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.0
~> 2.4
~> 3.12
~> 3.5

Runtime

 Project Readme

sucker_punch-backgroundable

Build Status

This gem allows you to background any method call with Sucker Punch without having to write a special job class. It provides the same API as the Backgroundable module from TorqueBox, and a large part of the code comes directly from the TorqueBox project.

Installation

Add the following to your Gemfile:

gem 'sucker_punch-backgroundable'

And then execute:

bundle install

Versions

The Sucker Punch API changed when Sucker Punch 2.0 was released. This gem uses the new API and requires Sucker Punch 2.0 (or higher). If for some reason you have to use an older version of Sucker Punch, please use version 0.2.0 of this gem.

Usage

Include the SuckerPunch::Backgroundable module in your class. Then you can use always_background :method1, :method2, ... to cause the supplied methods to run asynchronously in the background ("fire and forget"). Example:

class MyClass
  include SuckerPunch::Backgroundable
  
  always_background :send_email
  def send_email
    # ...
  end
  
  always_background :calculate_statistics
  def self.calculate_statistics
    # ...
  end
end

In this example, calls to instance method send_email and class method calculate_statistics will automatically run in the background:

obj = MyClass.new
obj.send_email  # returns immediately, method runs in the background

Myclass.calculate_statistics  # returns immediately, method runs in the background

Methods that have not been marked with always_background can also be backgrounded when you call them:

class MyClass
  include SuckerPunch::Backgroundable
  
  def notify
    # ...
  end
end

obj = MyClass.new

# This will run in the background (and return immediately)
obj.background.notify

# This will run the method normally (synchronously, returning after the method is finished)
obj.notify

It is also possible to specify a delay in seconds:

# This will return immediately and run the method in the background after a delay of 60 seconds
obj.later(60).notify

Both background and later also work with class methods (e.g. MyClass.background.my_class_method(argument)).

Reloading

When backgrounding an instance method, the method is called on the object, but in a different thread (using SuckerPunch). If you don't use the object anymore in the current thread, this is ok. If the object is still being used in the current thread, it may be better to reload it from the data store (assuming a data store backed object) in the background thread to avoid any threading issues. The gem can do this automatically, although currently only ActiveRecord is supported:

class MyModel < ActiveRecord::Base
  include SuckerPunch::Backgroundable
  
  always_background :send_email, :reload => true
  def send_email
    # ...
  end
end

Or, when using background or later:

obj.background(:reload => true).my_instance_method
obj.later(60, :reload => true).my_instance_method

It is also possible to specify the reload option globally by using an initializer:

SuckerPunch::Backgroundable.configure do |config|
  config.reload = true
end

Configuration

Apart from the reload option described above, there are two other configuration settings:

SuckerPunch::Backgroundable.configure do |config|
  config.reload = true
  config.workers = 4   # default is 2
  config.enabled = true
end

The number of workers sets the number of background threads that SuckerPunch will use. The default (and minimum) is 2.

By setting enabled to false, backgrounding is globally disabled, so all methods will be executed synchronously. This can be useful in tests.

Usage with ActiveRecord

When using this gem with ActiveRecord models, it is recommended to set the reload option to true (see above). If you want sucker_punch-backgroundable to be available in all models you can use the following in an initializer:

ActiveRecord::Base.send(:include, SuckerPunch::Backgroundable)

Switching from TorqueBox Backgroundable

This gem is completely independent from TorqueBox (or JRuby). But if you are already using TorqueBox Backgroundable, you can switch to backgrounding with SuckerPunch by a simple change in an initializer:

# In config/initializers/active_record_backgroundable.rb, replace
if defined?(TorqueBox::Messaging::Backgroundable) && defined?(ActiveRecord::Base)
  ActiveRecord::Base.send(:include, TorqueBox::Messaging::Backgroundable)
end

# by this:
ActiveRecord::Base.send(:include, SuckerPunch::Backgroundable)

Switching from TorqueBox Backgroundable to SuckerPunch will save you RAM (since TorqueBox uses a separate application instance for Backgroundable), but remember that SuckerPunch jobs are not persisted, so you might lose jobs on a server restart.

Contributing to sucker_punch-backgroundable

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright

Copyright (c) 2014 Michaƫl Van Damme. See LICENSE.txt for further details.