Project

q

0.02
No commit activity in last 3 years
No release in over 3 years
A universal interface for Ruby queueing backends.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Q

Forget queue boilerplate: focus on your code.

Install

In your Gemfile add:

gem 'q'

Then run $ bundle install

What

Q is an interface for your background queues. Are you using Resque, Sidekiq, delayed_job, queue_classic, or some other queue? Awesome sauce, because with Q you can write your queuing code once and re-use against different backends.

Q.setup do |config|
  config.queue = :resque
end

Now in your code when you need to enqueue something first you need to add the Q::Methods module:

class Poro
  include Q::Methods
end

Now you can define tasks using the queue class method like this:

class Poro
  include Q::Methods

  queue(:send_issues) do |id, state|
    user   = User.find(id)
    issues = user.issues.where(state: state).all
    UserMailer.send_issues(user: user, issues: issues).deliver
  end
end

Here we're building a background task called send_issues that will send out an email when executed.

Now that the task is defined, you can enqueue a send_issues job to be executed later by calling queue and then send_issues like this:

user  = User.last
state = 'open'
Poro.queue.send_issues(user.id, state)

The Q interface expects json-able objects, numbers, arrays, hashes, etc. This is important if you want your code to be re-usable across multiple queue backends.

No Queue? No Problem

The Q library comes with a threaded queue that does not need a backend (such as Redis) by default, so you can write your code today and figure out what queue you want to use tomorrow.

Note: that this threaded queue is very basic and should not be used in production. If you stop your Ruby process while there are jobs in memory you will lose your jobs see threaded_in_memory_queue for more information.

Starting your Queue

Most background queue libraries must be run in a seperate process. The Q library makes starting these background tasks easy.

Make sure there is a Rake task named :environment that loads your app (Rails provides one by default). Then add this line to your Procfile:

worker: bundle exec rake q:work

Now if you are running on Heroku the background task will automatically be run. Locally you can run the task manually by executing:

$ bundle exec rake q:work

Or through your Procfile with foreman:

$ foreman start

If your queueing library supports any custom environment variables or flags you can add them to your rake q:work command and they will be passed to the supporting background queue's task.

Note: the default threaded queue does not need to be started as it runs in your web process

Config

You can configure the behavior of your background queue using Q.queue_config. For example if you are using Resque and want to run commands inline you could execute:

Q.queue_config.inline = true

Now any calls to enqueue will bypass resque and be run immediately. Different queues will have different configuration options so you will need to see their docs for configuration options.

You can access this config in the setup command:

Q.setup do |config|
  config.queue = :resque
  config.queue_config.inline = true
end

It also accepts a block:

Q.queue_config do |config|
  config.inline = true
end

Don't confuse queue_config which will configure your background queue (such as Resque) with setup which configures the Q library itself.

Diverging Backends

As much as we try to make all front end code similar, you'll still need to setup your queue. To make sqitching back and forth easier, we provide a Q.env object that responds to the backend you are using such as Q.env.resque?.

That way you could keep multiple queue configurations in your app and it won't raise any errors if you're running a different backend.

if Q.env.resque?
  # config resque here
end

if Q.env.sidekiq?
  # configure sidekiq here
else

Supported Queue Backends

config.queue = :sidekiq
config.queue = :resque
config.queue = :threaded

Coming soon:

config.queue = :delayed_job

Blocks

You can set default values in blocks like this:

queue(:foo) do |id, state = 'open', username = 'schneems'|
  # ...
end

You can have an unlimited amount of args using a splat:

queue(:foo) do |id, *args|
  # ...
end

Q Authors

Did you write a background queuing library? Want to add support for the Q interface? Check out the QUEUE_AUTHORS.md file to get started.

License

Brought to you by @schneems

MIT