Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 97 lines (82 sloc) 3.25 KB
#!/usr/bin/env ruby
#
# This wraps the Resque process with a thin HTTP API which enables you to manipulate jobs using HTTP requests
# and run jobs synchronously, for the purposes of integration testing background jobs. See the README for
# more details of why this is awesome.
#
# Usage:
# QUEUE=* http_resque
# Options:
# -p: the port to listen on. Defaults to the $PORT environment variable, or 4568.
# --rakefile: the location of your Rakefile. The default is "./Rakefile".
#
# Once it's started, you can access these URLs to manipulate jobs:
# GET /queues/:queue_name/jobs
# DELETE /queues/:queue_name/jobs
# POST /queues/:queue_name/jobs
# GET /queues/:queue_name/result_of_oldest_job
require "sinatra/base"
require "thin"
require "resque"
require "rake"
require "json"
require "trollop"
class HttpResqueServer < Sinatra::Base
cli_options = Trollop::options do
opt :rakefile, "The location of your Rakefile which loads your Resque workers.", :default => "./Rakefile"
opt :port, "The port this server should listen on.", :type => :int
end
unless ENV["QUEUE"]
puts "You must set the QUEUE env var, just as you would when running `QUEUE=* rake resque:work`."
exit 1
end
STDOUT.sync = STDERR.sync = true
begin
# Load their Rakefile, which should in turn require all of their Resque job classes.
load cli_options[:rakefile]
rescue LoadError
puts "Error loading Rakefile: #{cli_options[:rakefile]}. Give the path to your Rakefile using --rakefile."
exit 1
end
# Run rake resque:work in a background process. It will exit when this process exits.
fork { Rake::Task["resque:work"].invoke }
settings.port = cli_options[:port] || ENV["PORT"] || 4568
settings.server = "thin"
get "/" do
"http_resque is here."
end
# The Resque representation of up to 25 jobs in this queue, *oldest* first. Resque jobs look like this:
# { "class"=>"DeployBuild", "args"=>["my_embed_code", "my_youtube_synd_id"] }
get "/queues/:queue/jobs" do
(Resque.peek(params[:queue], 0, 25) || []).to_json
end
delete "/queues/:queue/jobs" do
Resque.remove_queue(params[:queue])
nil
end
# Create a new job.
# - queue: the queue to enqueue this job into.
# - arguments: optional; an array of arguments for the Resque job.
post "/queues/:queue/jobs" do
halt(400, "Provide a valid JSON body.") unless json_body
halt(400, "Specify a class.") unless json_body["class"]
klass = Object.const_get(json_body["class"])
Resque.enqueue_to(params[:queue], klass, *json_body["arguments"])
nil
end
# Executes the job at the head of this queue (the oldest job), and blocks until it's finished.
# This is useful for scripting integration tests which verify that a background job is working correctly.
get "/queues/:queue/result_of_oldest_job" do
job = Resque::Job.reserve(params[:queue])
halt(404, "No jobs left in #{params[:queue]}") unless job
begin
job.perform
rescue => error
halt(500, "This job raised an exception when run: " +
"#{job.inspect}\n#{error.class}: #{error.message}\n#{error.backtrace.join("\n")}")
end
nil
end
def json_body() @json_body ||= JSON.parse(request.body.read) rescue nil end
run! if File.basename(app_file) == File.basename($0)
end