GoodJob is a multithreaded, Postgres-based ActiveJob backend for Ruby on Rails.
Inspired by Delayed::Job and Que, GoodJob’s design principles are:
- Stand on the shoulders of ActiveJob. For example, exception and retry behavior.
- Stand on the shoulders of Ruby on Rails. For example, ActiveRecord ORM, connection pools, and multithreaded support with Concurrent-Ruby.
- Stand on the shoulders of Postgres. For example, Advisory Locks.
- Convention over simplicity over performance.
Add this line to your application's Gemfile:
gem 'good_job'
And then execute:
$ bundle install
-
Create a database migration:
$ bin/rails g migration CreateGoodJobs
Add to the newly created migration file:
class CreateGoodJobs < ActiveRecord::Migration[6.0] def change enable_extension 'pgcrypto' create_table :good_jobs, id: :uuid do |t| t.timestamps t.text :queue_name t.integer :priority t.jsonb :serialized_params t.timestamp :scheduled_at end end end
Run the migration:
$ bin/rails db:migrate
-
Configure the ActiveJob adapter:
# config/application.rb config.active_job.queue_adapter = :good_job
By default, using
:good_job
is equivalent to manually configuring the adapter:# config/environments/development.rb config.active_job.queue_adapter = GoodJob::Adapter.new(inline: true) # config/environments/test.rb config.active_job.queue_adapter = GoodJob::Adapter.new(inline: true) # config/environments/production.rb config.active_job.queue_adapter = GoodJob::Adapter.new
-
In production, the scheduler is designed to run in its own process:
$ bundle exec good_job
GoodJob executes enqueued jobs using threads. There is a lot than can be said about multithreaded behavior in Ruby on Rails, but briefly:
- Each GoodJob execution thread requires its own database connection, which are automatically checked out from Rails’s connection pool. Allowing GoodJob to schedule more threads than are available in the database connection pool can lead to timeouts and is not recommended.
- The maximum number of GoodJob threads can be configured, in decreasing precedence:
$ bundle exec good_job --max_threads 4
$ GOOD_JOB_MAX_THREADS=4 bundle exec good_job
$ RAILS_MAX_THREADS=4 bundle exec good_job
- Implicitly via Rails's database connection pool size (
ActiveRecord::Base.connection_pool.size
)
To run tests:
# Clone the repository locally
$ git clone git@github.com:bensheldon/good_job.git
# Set up the local environment
$ bin/setup_test
# Run the tests
$ bin/rspec
This gem uses Appraisal to run tests against multiple versions of Rails:
# Install Appraisal(s) gemfiles
$ bundle exec appraisal
# Run tests
$ bundle exec appraisal bin/rspec
For developing locally within another Ruby on Rails project:
# Within Ruby on Rails directory...
$ bundle config local.good_job /path/to/local/git/repository
# Confirm that the local copy is used
$ bundle install
# => Using good_job 0.1.0 from https://github.com/bensheldon/good_job.git (at /Users/You/Projects/good_job@dc57fb0)
Package maintainers can release this gem with the following gem-release command:
# Sign into rubygems
$ gem signin
# Update version number, changelog, and create git commit:
$ bundle exec rake commit_version
# ..and follow subsequent directions.
Contribution directions go here.
The gem is available as open source under the terms of the MIT License.