Module: Resque

Extended by:
Resque
Includes:
ResqueUnit::Helpers
Included in:
Resque
Defined in:
lib/resque_unit/errors.rb,
lib/resque_unit/plugin.rb,
lib/resque_unit/plugin.rb,
lib/resque_unit/resque.rb

Overview

The fake Resque class. This needs to be loaded after the real Resque for the assertions in ResqueUnit::Assertions to work.

Defined Under Namespace

Modules: Plugin Classes: DirtyExit, Job, NoClassError, NoQueueError

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ResqueUnit::Helpers

#classify, #constantize, #decode, #encode

Class Method Details

.queuesObject

Returns a hash of all the queue names and jobs that have been queued. The format is {queue_name => [job, ..]}.



22
23
24
# File 'lib/resque_unit/resque.rb', line 22

def self.queues
  @queue || reset!
end

Instance Method Details

#all(queue_name) ⇒ Object

Return an array of all jobs’ payloads for queue Elements are decoded



36
37
38
39
# File 'lib/resque_unit/resque.rb', line 36

def all(queue_name)
  result = list_range(queue_name, 0, size(queue_name))
  result.is_a?(Array) ? result : [ result ]
end

#disable_hooks!Object



68
69
70
# File 'lib/resque_unit/resque.rb', line 68

def disable_hooks!
  @hooks_enabled = nil
end

#empty_queues?Boolean

:nodoc:

Returns:

  • (Boolean)


129
130
131
132
133
# File 'lib/resque_unit/resque.rb', line 129

def empty_queues?
  queues.all? do |k, v|
    v.empty?
  end
end

#enable_hooks!Object

Yes, all Resque hooks!



64
65
66
# File 'lib/resque_unit/resque.rb', line 64

def enable_hooks!
  @hooks_enabled = true
end

#enqueue(klass, *args) ⇒ Object

:nodoc:



111
112
113
# File 'lib/resque_unit/resque.rb', line 111

def enqueue(klass, *args)
  enqueue_to( queue_for(klass), klass, *args)
end

#enqueue_to(queue_name, klass, *args) ⇒ Object

:nodoc:

Raises:



116
117
118
119
120
# File 'lib/resque_unit/resque.rb', line 116

def enqueue_to( queue_name, klass, *args )
  # Behaves like Resque, raise if no queue was specifed
  raise NoQueueError.new("Jobs must be placed onto a queue.") unless queue_name
  enqueue_unit(queue_name, {"class" => klass.to_s, "args" => args })
end

#enqueue_unit(queue_name, hash) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/resque_unit/resque.rb', line 135

def enqueue_unit(queue_name, hash)
  klass = constantize(hash["class"])
  if @hooks_enabled
    before_hooks = Plugin.before_enqueue_hooks(klass).map do |hook|
      klass.send(hook, *hash["args"])
    end
    return nil if before_hooks.any? { |result| result == false }
  end
  queue(queue_name) << encode(hash)
  if @hooks_enabled
    Plugin.after_enqueue_hooks(klass).each do |hook|
      klass.send(hook, *hash["args"])
    end
  end
  queue(queue_name).size
end

#full_run!Object

  1. Execute all jobs in all queues in an undefined order,

  2. Check if new jobs were announced, and execute them.

  3. Repeat 3



97
98
99
# File 'lib/resque_unit/resque.rb', line 97

def full_run!
  run! until empty_queues?
end

#list_range(key, start = 0, count = 1) ⇒ Object

Gets a range of jobs’ payloads from queue. Returns single element if count equal 1 Elements are decoded



55
56
57
58
59
60
61
# File 'lib/resque_unit/resque.rb', line 55

def list_range(key, start = 0, count = 1)
  data = if count == 1
    decode(queues[key][start])
  else
    (queues[key][start...start + count] || []).map { |entry| decode(entry) }
  end
end

#peek(queue_name, start = 0, count = 1) ⇒ Object

Returns an array of jobs’ payloads for queue.

start and count should be integer and can be used for pagination. start is the item to begin, count is how many items to return.

To get the 3rd page of a 30 item, paginatied list one would use:

Resque.peek('my_list', 59, 30)


48
49
50
# File 'lib/resque_unit/resque.rb', line 48

def peek(queue_name, start = 0, count = 1)
  list_range(queue_name, start, count)
end

#perform_with_hooks(job_payload) ⇒ Object

Call perform on the job class, and adds support for Resque hooks.



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/resque_unit/resque.rb', line 158

def perform_with_hooks(job_payload)
  job_class = constantize(job_payload["class"])
  before_hooks  = Resque::Plugin.before_hooks(job_class)
  around_hooks  = Resque::Plugin.around_hooks(job_class)
  after_hooks   = Resque::Plugin.after_hooks(job_class)
  failure_hooks = Resque::Plugin.failure_hooks(job_class)
  
  begin
    # Execute before_perform hook. Abort the job gracefully if
    # Resque::DontPerform is raised.
    begin
      before_hooks.each do |hook|
        job_class.send(hook, *job_payload["args"])
      end
    rescue Resque::Job::DontPerform
      return false
    end
    
    # Execute the job. Do it in an around_perform hook if available.
    if around_hooks.empty?
      perform_without_hooks(job_payload)
      job_was_performed = true
    else
      # We want to nest all around_perform plugins, with the last one
      # finally calling perform
      stack = around_hooks.reverse.inject(nil) do |last_hook, hook|
        if last_hook
          lambda do
            job_class.send(hook, *job_payload["args"]) { last_hook.call }
          end
        else
          lambda do
            job_class.send(hook, *job_payload["args"]) do
              result = perform_without_hooks(job_payload)
              job_was_performed = true
              result
            end
          end
        end
      end
      stack.call
    end
    
    # Execute after_perform hook
    after_hooks.each do |hook|
      job_class.send(hook, *job_payload["args"])
    end
    
    # Return true if the job was performed
    return job_was_performed
    
  # If an exception occurs during the job execution, look for an
  # on_failure hook then re-raise.
  rescue Object => e
    failure_hooks.each { |hook| job_class.send(hook, e, *job_payload["args"]) }
    raise e
  end
end

#perform_without_hooks(job_payload) ⇒ Object

Call perform on the job class



153
154
155
# File 'lib/resque_unit/resque.rb', line 153

def perform_without_hooks(job_payload)
  constantize(job_payload["class"]).perform(*job_payload["args"])
end

#queue(queue_name) ⇒ Object

Returns an array of all the jobs that have been queued. Each element is of the form {“class” => klass, “args” => args} where klass is the job’s class and args is an array of the arguments passed to the job.



30
31
32
# File 'lib/resque_unit/resque.rb', line 30

def queue(queue_name)
  queues[queue_name]
end

#queue_for(klass) ⇒ Object Also known as: queue_from_class

:nodoc:



123
124
125
# File 'lib/resque_unit/resque.rb', line 123

def queue_for(klass)
  klass.instance_variable_get(:@queue) || (klass.respond_to?(:queue) && klass.queue)
end

#reset!(queue_name = nil) ⇒ Object

Resets all the queues to the empty state. This should be called in your test’s setup method until I can figure out a way for it to automatically be called.

If queue_name is given, then resets only that queue.



12
13
14
15
16
17
18
# File 'lib/resque_unit/resque.rb', line 12

def reset!(queue_name = nil)
  if @queue && queue_name
    @queue[queue_name] = []
  else
    @queue = Hash.new { |h, k| h[k] = [] }
  end
end

#run!Object

Executes all jobs in all queues in an undefined order.



73
74
75
76
77
78
79
# File 'lib/resque_unit/resque.rb', line 73

def run!
  payloads = []
  @queue.each do |queue_name, queue|
    payloads.concat queue.slice!(0, queue.size)
  end
  exec_payloads payloads.shuffle
end

#run_for!(queue_name, limit = false) ⇒ Object



81
82
83
84
# File 'lib/resque_unit/resque.rb', line 81

def run_for!(queue_name, limit=false)
  queue = @queue[queue_name]
  exec_payloads queue.slice!(0, ( limit ? limit : queue.size) ).shuffle
end

#size(queue_name = nil) ⇒ Object

Returns the size of the given queue



102
103
104
105
106
107
108
# File 'lib/resque_unit/resque.rb', line 102

def size(queue_name = nil)
  if queue_name
    queues[queue_name].length
  else
    queues.values.flatten.length
  end
end