Skip to content

Instantly share code, notes, and snippets.

@rcarver
Created September 11, 2009 23:27
Show Gist options
  • Save rcarver/185656 to your computer and use it in GitHub Desktop.
Save rcarver/185656 to your computer and use it in GitHub Desktop.
module Job
extend self
def low(klass, *args)
queue.enqueue(:low, klass, *args)
end
def high(klass, *args)
queue.enqueue(:high, klass, *args)
end
def live_queue?
Merb.env =~ /production/
end
def queue
@queue ||= live_queue? ? Resque : MemoryQueue.new
end
class MemoryQueue
def initialize
@jobs = []
@job_results = []
end
attr_reader :job_results, :jobs_performed
def clear!
@jobs = []
@job_results = []
@jobs_performed = []
end
def enqueue(queue, klass, *args)
@jobs << [queue, klass, args]
end
def results_of(klass, queue=nil)
results = job_matches(klass, queue)
raise "#{klass} was run multiple times" if results.any? && results.size > 1
results.first
end
def has_performed?(klass, queue=nil)
job_matches(klass, queue).any?
end
def perform_all
@job_results = []
@jobs_performed = []
@jobs.each do |queue, klass, args|
results = klass.perform(*args)
@job_results << results
@jobs_performed << [klass, queue, results]
end
@jobs = []
end
def job_matches(klass, queue=nil)
@jobs_performed.collect do |job_klass, job_queue, results|
if queue
results if queue == job_queue && klass == job_klass
else
results if klass == job_klass
end
end.compact
end
end
end
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
describe "The job queue" do
module TestJob
def self.perform(name)
"#{name} was run"
end
end
class JobQueueingController < Application
def queue_no_jobs
render "ok"
end
def queue_one_job
Job.low TestJob, "from queue_one_job"
render "ok"
end
def queue_two_jobs
Job.low TestJob, "one from queue_two_jobs"
Job.high TestJob, "two from queue_two_jobs"
render "ok"
end
end
before(:all) do
@old_routes = Merb::Router.routes
Merb::Router.prepare(@old_routes) do
to(:controller => "job_queueing_controller") do
match('/none').to(:action => "queue_no_jobs")
match('/one').to(:action => "queue_one_job")
match('/two').to(:action => "queue_two_jobs")
end
end
end
after(:all) do
Merb::Router.prepare(@old_routes) { }
end
it "is run after every request" do
lambda { request("/one") }.should change(Job.queue, :job_results).from([]).to(["from queue_one_job was run"])
Job.queue.should have_performed(TestJob)
Job.queue.should have_performed(TestJob, :low)
Job.queue.should_not have_performed(TestJob, :high)
Job.queue.results_of(TestJob).should == "from queue_one_job was run"
Job.queue.results_of(TestJob, :low).should == "from queue_one_job was run"
Job.queue.results_of(TestJob, :high).should be_nil
end
it "is cleared after every request" do
lambda { request("/one") }.should change(Job.queue, :job_results).from([]).to(["from queue_one_job was run"])
lambda { request("/none") }.should change(Job.queue, :job_results).from(["from queue_one_job was run"]).to([])
Job.queue.should_not have_performed(TestJob)
Job.queue.results_of(TestJob).should be_nil
end
it "runs all queued jobs" do
lambda { request("/two") }.should change(Job.queue, :job_results).from([]).to(["one from queue_two_jobs was run", "two from queue_two_jobs was run"])
Job.queue.should have_performed(TestJob)
Job.queue.should have_performed(TestJob, :low)
Job.queue.should have_performed(TestJob, :high)
lambda { Job.queue.results_of(TestJob) }.should raise_error("#{TestJob} was run multiple times")
Job.queue.results_of(TestJob, :low).should == "one from queue_two_jobs was run"
Job.queue.results_of(TestJob, :high).should == "two from queue_two_jobs was run"
end
end
class Application < Merb::Controller
protected
after :run_job_queue_unless_live_queue
def run_job_queue_unless_live_queue
Job.queue.perform_all unless Job.live_queue?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment