buffered_job

Build Status

Buffering jobs for a certain period and invoke specific method if two or more similer jobs in a buffer.

Scenario

Supposing that you are running sort of social media that has user articles which accept comments on each. You'll probably want to have email notification for incomming comments on a article. If you implement straightforward, the auther of popular article would receive tons of email for an article. That must be bothering. To avoid sending too many mails to a receipient, you can merge multiple notificaiton messages into an array and process it with another specific method.

That mean, if a user gets a comment notification for her blog article as follows:

 @article = Article.create(:user => @user,:text => "my blog article here")
 c = @article.comments.create(:user => @jon, :text => "i love this article!")
 @user.notify(c)

Then. With this module,you can buffer notify method

 c1 = @article.comments.create(:user => @jon, :text => "i love this article!")
 c2 = @article.comments.create(:user => @ken, :text => "i hate this article!")

 @user.buffer.notify(c1)
 @user.buffer.notify(c2)
 # these two methods would be translated to
 @user.merge_notify([c1,c2])
 # So, you can write other notification email template which handles array of comment objects

Install

$ gem install buffered_job

or in Gemfile

gem 'buffered_job'

then, bundle install

Peparation

$ (bundle exec) rails generate buffered_job
$ (bundle exec) rake db:migrate

Dependancies

This module depends on delayed_job_active_record. Set up delayed_job and be sure to run delayed_job worker.

Running jobs

flushing would be triggered by delayed_job. Start worker as follows after migrating the table required.

$ (bundle exec) rake jobs:work

See more details about delayed_job

Usage

With ActiveRecord Object

Every active_record object has buffer method. You can put it between receiver and method and bufferes method along with argument object.

@user.buffer.post_to_twitter(@article1)
@user.buffer.post_to_twitter(@aritcle2)

When flushing buffer,if two methods above is detected, that would
invoke merge_:original_method method insted of original method on that User model,so in this case, you must define merge_post_to_twitter in User model.

  def merge_post_to_twitter(articles)
    ..
  end

With ActionMailer Class

Also, subclasses of ActionMailer::Base have buffer method. You can buffer sending method with buffering keyword. That keyword will be used to determine which methods should be merged.

 YourMailer.buffer("send_to/135").greeting(some_object)
 YourMailer.buffer("send_to/135").greeting(other_object)
 # these two will be merged 
 #  and invoke merge_greeting([some_object,other_object])
 YourMailer.buffer("send_to/222").greeting(yet_another_object)
 # this won't be merged into preceding two.

Current Limitation

Only one argument object can be passed to buffered method.

Configuration

default buffering time is tree munites. To modify,

BufferedJob.delay_time = 30.seconds

Copyright (c) 2012 Masaki Sawamura. See LICENSE.txt for further details.