ActiveJobMetadata

ActiveJobMetadata lets you store and retrieve metadata associated with ActiveJob jobs regardless of the queue processing library you use.

Primary use cases include:

  • Providing job status clients
  • Tracking job performance

Installation

Add this line to your application's Gemfile:

gem 'active_job_metadata'

Usage

You can use as much or as little of ActiveJobMetadata as you need.

Use Lifecyle to track the current status of your job:

class MyJob < ActiveJob::Base
  include ActiveJobMetadata::Lifecycle

  def perform
    #...
  end
end

job = MyJob.new
job.enque
job.status #=> "enqueued"
ActiveJobMetadata.find(job.job_id) #=> {status: "enqueued"}

You can use this in RESTful controllers to let clients query for a job's status:

class JobsController
  def create
    job = MyJob.new
    job.enque

    render json: {id: job.job_id}
  end

  def show
     = ActiveJobMetadata.find(params[:id])

    if 
      render json: 
    else
      render json: {message: "Not Found"}, status: 404
    end
  end
end

Use the Timing module to track and report on execution times:

class TimedJob < ActiveJob::Base
  include ActiveJobMetadata::Timing
  after_peform :report_timing

  def perform
    #...
  end

  def report_timing
    Rails.logger.info "Queue Duration: #{queue_duration}"
    Rails.logger.info "Processing Duration: #{working_duration}"
    Rails.logger.info "Total Duration: #{total_duration}"
  end
end

Of course you could hook this up to statsd, or any other place you collect metrics.

Use the Metadata module to track custom information. For instance a long running job might report the percent complete and the name of the last file it processed:

class LongRunningJob < ActiveJob::Base
  include ActiveJobMetadata::Metadata
   :percent_complete, :current_file

  def perform(files)
    files.each_with_index do |file, i|
      self.percent_complete = (files.length / i.to_f)
      self.current_file = file

      IO.open(file) do |io|
        #...
      end
    end
  end

end

Use this approach to enrich metadata you send back to your client.

Configuration

Although ActiveJobMetadata should mostly work out of the box in a development environment, you will probably want to customize the backing store. ActiveJobMetadata reads and writes to an ActiveSupport::Cache::Store. If you use more than one web server, which is likely, you will probably want to use something like Readthis which provides a shared interface via Redis. If you want to use a different backend for ActiveJobMetadata than Rails, create an initializer with your custom store:

# initializers/active_job_metadata.rb

# Configure ActiveJobMetadata to use Readthis:
ActiveJobMetadata.store = Readthis::Cache.new(
  expires_in: 2.days.to_i
)

Currently ActiveJobMetadata only uses the read and write methods, so you can easily store your metadata wherever all your servers can easily access it if you don't mind implementing something that quacks like a ActiveSupport::Cache::Store.

Alternatives

It is always wise to consider your alternatives:

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/adamsanderson/active_job_metadata.