Module: Roundhouse::Worker::ClassMethods

Defined in:
lib/roundhouse/testing.rb,
lib/roundhouse/worker.rb

Overview

The Roundhouse testing infrastructure overrides perform_async so that it does not actually touch the network. Instead it stores the asynchronous jobs in a per-class array so that their presence/absence can be asserted by your tests.

This is similar to ActionMailer’s :test delivery_method and its ActionMailer::Base.deliveries array.

Example:

require 'roundhouse/testing'

assert_equal 0, HardWorker.jobs.size
HardWorker.perform_async(:something)
assert_equal 1, HardWorker.jobs.size
assert_equal :something, HardWorker.jobs[0]['args'][0]

assert_equal 0, Roundhouse::Extensions::DelayedMailer.jobs.size
MyMailer.delay.send_welcome_email('[email protected]')
assert_equal 1, Roundhouse::Extensions::DelayedMailer.jobs.size

You can also clear and drain all workers’ jobs:

assert_equal 0, Roundhouse::Extensions::DelayedMailer.jobs.size
assert_equal 0, Roundhouse::Extensions::DelayedModel.jobs.size

MyMailer.delay.send_welcome_email('[email protected]')
MyModel.delay.do_something_hard

assert_equal 1, Roundhouse::Extensions::DelayedMailer.jobs.size
assert_equal 1, Roundhouse::Extensions::DelayedModel.jobs.size

Roundhouse::Worker.clear_all # or .drain_all

assert_equal 0, Roundhouse::Extensions::DelayedMailer.jobs.size
assert_equal 0, Roundhouse::Extensions::DelayedModel.jobs.size

This can be useful to make sure jobs don’t linger between tests:

RSpec.configure do |config|
  config.before(:each) do
    Roundhouse::Worker.clear_all
  end
end

or for acceptance testing, i.e. with cucumber:

AfterStep do
  Roundhouse::Worker.drain_all
end

When I sign up as "[email protected]"
Then I should receive a welcome email to "[email protected]"

Instance Method Summary collapse

Instance Method Details

#clearObject

Clear all jobs for this worker



146
147
148
# File 'lib/roundhouse/testing.rb', line 146

def clear
  jobs.clear
end

#client_push(item) ⇒ Object

:nodoc:



83
84
85
86
# File 'lib/roundhouse/worker.rb', line 83

def client_push(item) # :nodoc:
  pool = Thread.current[:roundhouse_via_pool] || get_roundhouse_options['pool'] || Roundhouse.redis_pool
  Roundhouse::Client.new(pool).push(item.stringify_keys)
end

#drainObject

Drain and run all jobs for this worker



151
152
153
154
155
156
157
158
# File 'lib/roundhouse/testing.rb', line 151

def drain
  while job = jobs.shift do
    worker = new
    worker.jid = job['jid']
    worker.bid = job['bid'] if worker.respond_to?(:bid=)
    execute_job(worker, job['args'])
  end
end

#execute_job(worker, args) ⇒ Object



170
171
172
# File 'lib/roundhouse/testing.rb', line 170

def execute_job(worker, args)
  worker.perform(*args)
end

#get_roundhouse_optionsObject

:nodoc:



79
80
81
# File 'lib/roundhouse/worker.rb', line 79

def get_roundhouse_options # :nodoc:
  self.roundhouse_options_hash ||= Roundhouse.default_worker_options
end

#jobsObject

Jobs queued for this worker



141
142
143
# File 'lib/roundhouse/testing.rb', line 141

def jobs
  Worker.jobs[self]
end

#perform_async(queue_id, *args) ⇒ Object



41
42
43
# File 'lib/roundhouse/worker.rb', line 41

def perform_async(queue_id, *args)
  client_push('queue_id' => queue_id, 'class' => self, 'args' => args)
end

#perform_in(queue_id, interval, *args) ⇒ Object Also known as: perform_at



45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/roundhouse/worker.rb', line 45

def perform_in(queue_id, interval, *args)
  int = interval.to_f
  now = Time.now
  ts = (int < 1_000_000_000 ? (now + interval).to_f : int)

  item = { 'queue_id' => queue_id, 'class' => self, 'args' => args, 'at' => ts }

  # Optimization to enqueue something now that is scheduled to go out now or in the past
  item.delete('at'.freeze) if ts <= now.to_f

  client_push(item)
end

#perform_oneObject

Pop out a single job and perform it

Raises:



161
162
163
164
165
166
167
168
# File 'lib/roundhouse/testing.rb', line 161

def perform_one
  raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
  job = jobs.shift
  worker = new
  worker.jid = job['jid']
  worker.bid = job['bid'] if worker.respond_to?(:bid=)
  execute_job(worker, job['args'])
end

#roundhouse_options(opts = {}) ⇒ Object

Allows customization for this type of Worker. Legal options:

:retry - enable the RetryJobs middleware for this Worker, default *true*
:backtrace - whether to save any error backtrace in the retry payload to display in web UI,
   can be true, false or an integer number of lines to save, default *false*
:pool - use the given Redis connection pool to push this type of job to a given shard.


67
68
69
# File 'lib/roundhouse/worker.rb', line 67

def roundhouse_options(opts={})
  self.roundhouse_options_hash = get_roundhouse_options.merge(opts.stringify_keys)
end

#roundhouse_retries_exhausted(&block) ⇒ Object



75
76
77
# File 'lib/roundhouse/worker.rb', line 75

def roundhouse_retries_exhausted(&block)
  self.roundhouse_retries_exhausted_block = block
end

#roundhouse_retry_in(&block) ⇒ Object



71
72
73
# File 'lib/roundhouse/worker.rb', line 71

def roundhouse_retry_in(&block)
  self.roundhouse_retry_in_block = block
end