Module: Resqutils::Spec::ResqueHelpers
- Defined in:
- lib/resqutils/spec/resque_helpers.rb
Overview
Mix this into your tests to get helpful methods to manipulate a live resque queue.
Instance Method Summary collapse
-
#clear_queue(queue_name) ⇒ Object
Clear the queue.
-
#delayed_jobs ⇒ Object
Return all jobs in a delayed queue, with each job augmented with the key
scheduler_timestamp
to represent what time the job was schedule to run for. -
#jobs_matching(queue_name, expected_job_hash) ⇒ Object
Get jobs from
queue_name
that match the given hash. -
#process_multiple_resque_jobs(number, expected_class, queue = nil, &block) ⇒ Object
- block
-
if provided, will be given each popped job right before it is processed.
-
#process_resque_job(expected_class, queue = nil, &block) ⇒ Object
- block
-
if provided, will be given the popped job right before it is processed.
-
#queue_size(queue) ⇒ Object
Get the size of the given queue.
Instance Method Details
#clear_queue(queue_name) ⇒ Object
Clear the queue. Useful in before blocks to make sure there’s nothing hanging around in your queue from a previous test run.
- queue_name
-
If a Class, the ivar @queue is used to determine which queue to clear. Otherwise, assumes it’s a string or symbol and will clear that queue.
:delayed
is a special queue that represents the delayed queue provided byresque-scheduler
.
67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/resqutils/spec/resque_helpers.rb', line 67 def clear_queue(queue_name) if queue_name.kind_of?(Class) queue_name = queue_name.instance_variable_get("@queue") end if queue_name == :delayed Resque.reset_delayed_queue else Resque.redis.del("queue:#{queue_name}") Resque.redis.del("resque:queue:#{queue_name}") end end |
#delayed_jobs ⇒ Object
Return all jobs in a delayed queue, with each job augmented with the key scheduler_timestamp
to represent what time the job was schedule to run for.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/resqutils/spec/resque_helpers.rb', line 129 def delayed_jobs # The double-checks here are so that we won't blow up if the config stops using redis-namespace = (Array(Resque.redis.zrange("resque:delayed_queue_schedule",0,-1)) + Array(Resque.redis.zrange("delayed_queue_schedule",0,-1))) raise "Nothing on delayed schedule" if .empty? .map { || [ Array(Resque.redis.lrange("resque:delayed:#{}",0,-1)) + Array(Resque.redis.lrange("delayed:#{}",0,-1)), , ] }.map { |(job_strings,)| job_strings.map { |job_string| JSON.parse(job_string).merge('scheduler_timestamp' => .to_i) } }.flatten end |
#jobs_matching(queue_name, expected_job_hash) ⇒ Object
Get jobs from queue_name
that match the given hash. This returns both the jobs that matched and all jobs from the queue, so you can create a useful error message in your tests.
- queue_name
-
A String or Symbol representing the name of the queue, where
:delayed
is special and will cause the code to look in the delayed queue as provided by resque-scheduler. - expected_job_hash
-
Criteria for matching, typically a two-element hash containing the class and args of the job you are looking for.
Returns an array of size 2, where the first element is an Array of jobs matching the given criteria, and the second element is an Array of all jobs.
Example
Consider the queue “foo” has these jobs in it:
-
{ “class” => “WarmCaches”, “args” => [ 1234 ] }
-
{ “class” => “WarmCaches”, “args” => [ 4567 ] }
-
{ “class” => “IndexPurchases”, “args” => [ 1234 ] }
jobs_matching(:foo, class: WarmCaches, args: [ 1234 ]) # => matching jobs is the first job above jobs_matching(:foo, class: IndexPurchases, args: [ 1234 ]) # => matching jobs is the third job above jobs_matching(:foo, class: IndexPurchases, args: [ 9999 ]) # => matching jobs is nothing
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/resqutils/spec/resque_helpers.rb', line 103 def jobs_matching(queue_name,expected_job_hash) jobs = if queue_name == :delayed delayed_jobs else (0...Resque.size(queue_name)).map { |index| [Resque.peek(queue_name,index),index] } end matching_jobs = jobs.select { |(job,index)| raise "No job at index #{index}" if job.nil? expected_job_hash.all? do |k,v| k = k.to_s v = v.to_s if v.kind_of?(Class) raise "Job #{job} at index #{index} was missing key #{k}" if job[k].nil? if k == 'scheduler_timestamp' ((v.to_i - 60000)..(v.to_i + 60000)).cover?(job[k]) else job[k] == v end end }.map(&:first) [matching_jobs,jobs] end |
#process_multiple_resque_jobs(number, expected_class, queue = nil, &block) ⇒ Object
- block
-
if provided, will be given each popped job right before it is processed.
47 48 49 50 51 |
# File 'lib/resqutils/spec/resque_helpers.rb', line 47 def process_multiple_resque_jobs(number, expected_class, queue=nil, &block) number.times do process_resque_job(expected_class, queue, &block) end end |
#process_resque_job(expected_class, queue = nil, &block) ⇒ Object
- block
-
if provided, will be given the popped job right before it is processed.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/resqutils/spec/resque_helpers.rb', line 17 def process_resque_job(expected_class, queue=nil, &block) block ||= ->(payload) {} queue ||= expected_class.instance_variable_get("@queue") job = if queue == :delayed delayed_jobs.select { |job| job["class"] == expected_class.name }.first else job = Resque.pop(queue) end raise "No jobs on #{queue}" if job.nil? klass = job["class"].constantize if Gem.loaded_specs['rspec'].version >= Gem::Version.new('3') expect(klass).to eq(expected_class) else klass.should == expected_class end block.call(job) klass.perform(*job["args"]) end |
#queue_size(queue) ⇒ Object
Get the size of the given queue. This mostly prevents your test from having direct coupling to resque’s (crappy) internal API.
- queue
-
name of the queue, as a Symbol or String
57 58 59 |
# File 'lib/resqutils/spec/resque_helpers.rb', line 57 def queue_size(queue) Resque.size(queue) end |