mongo-resque 1.19.0.1 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/HISTORY.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 1.20.0 (2012-04-10)
2
+
3
+ * Fixed demos for ruby 1.9 (@BMorearty, #445)
4
+ * Web UI: optional trailing slashes of URLs (@elisehuard, #449)
5
+ * Allow * to appear anywhere in queue list (@tapajos, #405, #407)
6
+ * Wait for child with specific PID (@jacobkg)
7
+ * #decode raise takes a string when re-raising as a different exception class (Trevor Hart)
8
+ * Use Sinatra's `public_folder` if it exists (@defunkt, #420, #421)
9
+ * Assign the job's worker before calling `before_fork` (@quirkey)
10
+ * Fix Resque::Helpers#constantize to work correctly on 1.9.2 (@rtlong)
11
+ * Added before & after hooks for dequeue (@humancopy, #398)
12
+ * daemonize support using `ENV["BACKGROUND"]` (@chrisleishman)
13
+ * Added `Resque.enqueue_to`: allows you to specif the queue and still run hooks (@dan-g)
14
+ * Web UI: Set the default encoding to UTF-8 (@elubow)
15
+ * fix finding worker pids on JRuby (John Andrews + Andrew Grieser)
16
+ * Added better failure hooks (@raykrueger)
17
+ * Added before & after dequeue hooks (@humancopy)
18
+
1
19
  ## 1.19.1 (2011-10-07)
2
20
 
3
21
  * Change mongo gem dependency to include all 1.x versions from 1.3
@@ -18,6 +18,6 @@ Vegas::Runner.new(Resque::Server, 'resque-web', {
18
18
  }) do |runner, opts, app|
19
19
  opts.on('-N NAMESPACE', "--namespace NAMESPACE", "set the Mongo database") {|namespace|
20
20
  runner.logger.info "Using Mongo database '#{namespace}'"
21
- Resque.mongo = Resque.mongo.conn.db(namespace)
21
+ Resque.mongo = Resque.mongo.connection.db(namespace)
22
22
  }
23
23
  end
@@ -86,7 +86,7 @@ The available hooks are:
86
86
  `Resque::Failure` backend.
87
87
 
88
88
  * `on_failure`: Called with the exception and job args if any exception occurs
89
- while performing the job (or hooks).
89
+ while performing the job (or hooks), this includes Resque::DirtyExit.
90
90
 
91
91
  Hooks are easily implemented with superclasses or modules. A superclass could
92
92
  look something like this.
@@ -271,19 +271,37 @@ module Resque
271
271
  #
272
272
  # If no queue can be inferred this method will raise a `Resque::NoQueueError`
273
273
  #
274
+ # Returns true if the job was queued, nil if the job was rejected by a
275
+ # before_enqueue hook.
276
+ #
274
277
  # This method is considered part of the `stable` API.
275
278
  def enqueue(klass, *args)
279
+ enqueue_to(queue_from_class(klass), klass, *args)
280
+ end
281
+
282
+ # Just like `enqueue` but allows you to specify the queue you want to
283
+ # use. Runs hooks.
284
+ #
285
+ # `queue` should be the String name of the queue you're targeting.
286
+ #
287
+ # Returns true if the job was queued, nil if the job was rejected by a
288
+ # before_enqueue hook.
289
+ #
290
+ # This method is considered part of the `stable` API.
291
+ def enqueue_to(queue, klass, *args)
276
292
  # Perform before_enqueue hooks. Don't perform enqueue if any hook returns false
277
293
  before_hooks = Plugin.before_enqueue_hooks(klass).collect do |hook|
278
294
  klass.send(hook, *args)
279
295
  end
280
- return if before_hooks.any? { |result| result == false }
296
+ return nil if before_hooks.any? { |result| result == false }
297
+
298
+ Job.create(queue, klass, *args)
281
299
 
282
- Job.create(queue_from_class(klass), klass, *args)
283
-
284
300
  Plugin.after_enqueue_hooks(klass).each do |hook|
285
301
  klass.send(hook, *args)
286
302
  end
303
+
304
+ return true
287
305
  end
288
306
 
289
307
  def enqueue_delayed(klass, *args)
@@ -318,7 +336,17 @@ module Resque
318
336
  #
319
337
  # This method is considered part of the `stable` API.
320
338
  def dequeue(klass, *args)
339
+ # Perform before_dequeue hooks. Don't perform dequeue if any hook returns false
340
+ before_hooks = Plugin.before_dequeue_hooks(klass).collect do |hook|
341
+ klass.send(hook, *args)
342
+ end
343
+ return if before_hooks.any? { |result| result == false }
344
+
321
345
  Job.destroy(queue_from_class(klass), klass, *args)
346
+
347
+ Plugin.after_dequeue_hooks(klass).each do |hook|
348
+ klass.send(hook, *args)
349
+ end
322
350
  end
323
351
 
324
352
  # Given a class, try to extrapolate an appropriate queue based on a
@@ -37,7 +37,7 @@ module Resque
37
37
  begin
38
38
  ::MultiJson.decode(object)
39
39
  rescue ::MultiJson::DecodeError => e
40
- raise DecodeException, e
40
+ raise DecodeException, e.message, e.backtrace
41
41
  end
42
42
  end
43
43
 
@@ -48,9 +48,23 @@ module Resque
48
48
  dashed_word.split('-').each { |part| part[0] = part[0].chr.upcase }.join
49
49
  end
50
50
 
51
- # Given a camel cased word, returns the constant it represents
51
+ # Tries to find a constant with the name specified in the argument string:
52
52
  #
53
- # constantize('JobName') # => JobName
53
+ # constantize("Module") # => Module
54
+ # constantize("Test::Unit") # => Test::Unit
55
+ #
56
+ # The name is assumed to be the one of a top-level constant, no matter
57
+ # whether it starts with "::" or not. No lexical context is taken into
58
+ # account:
59
+ #
60
+ # C = 'outside'
61
+ # module M
62
+ # C = 'inside'
63
+ # C # => 'inside'
64
+ # constantize("C") # => 'outside', same as ::C
65
+ # end
66
+ #
67
+ # NameError is raised when the constant is unknown.
54
68
  def constantize(camel_cased_word)
55
69
  camel_cased_word = camel_cased_word.to_s
56
70
 
@@ -63,7 +77,13 @@ module Resque
63
77
 
64
78
  constant = Object
65
79
  names.each do |name|
66
- constant = constant.const_get(name) || constant.const_missing(name)
80
+ args = Module.method(:const_get).arity != 1 ? [false] : []
81
+
82
+ if constant.const_defined?(name, *args)
83
+ constant = constant.const_get(name)
84
+ else
85
+ constant = constant.const_missing(name)
86
+ end
67
87
  end
68
88
  constant
69
89
  end
@@ -116,11 +116,6 @@ module Resque
116
116
  job_args = args || []
117
117
  job_was_performed = false
118
118
 
119
- before_hooks = Plugin.before_hooks(job)
120
- around_hooks = Plugin.around_hooks(job)
121
- after_hooks = Plugin.after_hooks(job)
122
- failure_hooks = Plugin.failure_hooks(job)
123
-
124
119
  begin
125
120
  # Execute before_perform hook. Abort the job gracefully if
126
121
  # Resque::DontPerform is raised.
@@ -168,7 +163,7 @@ module Resque
168
163
  # If an exception occurs during the job execution, look for an
169
164
  # on_failure hook then re-raise.
170
165
  rescue Object => e
171
- failure_hooks.each { |hook| job.send(hook, e, *job_args) }
166
+ run_failure_hooks(e)
172
167
  raise e
173
168
  end
174
169
  end
@@ -186,6 +181,7 @@ module Resque
186
181
  # Given an exception object, hands off the needed parameters to
187
182
  # the Failure module.
188
183
  def fail(exception)
184
+ run_failure_hooks(exception)
189
185
  Failure.create \
190
186
  :payload => payload,
191
187
  :exception => exception,
@@ -211,5 +207,27 @@ module Resque
211
207
  payload_class == other.payload_class &&
212
208
  args == other.args
213
209
  end
210
+
211
+ def before_hooks
212
+ @before_hooks ||= Plugin.before_hooks(payload_class)
213
+ end
214
+
215
+ def around_hooks
216
+ @around_hooks ||= Plugin.around_hooks(payload_class)
217
+ end
218
+
219
+ def after_hooks
220
+ @after_hooks ||= Plugin.after_hooks(payload_class)
221
+ end
222
+
223
+ def failure_hooks
224
+ @failure_hooks ||= Plugin.failure_hooks(payload_class)
225
+ end
226
+
227
+ def run_failure_hooks(exception)
228
+ job_args = args || []
229
+ failure_hooks.each { |hook| payload_class.send(hook, exception, *job_args) }
230
+ end
231
+
214
232
  end
215
233
  end
@@ -52,5 +52,15 @@ module Resque
52
52
  def before_enqueue_hooks(job)
53
53
  job.methods.grep(/^before_enqueue/).sort
54
54
  end
55
+
56
+ # Given an object, returns a list `after_dequeue` hook names.
57
+ def after_dequeue_hooks(job)
58
+ job.methods.grep(/^after_dequeue/).sort
59
+ end
60
+
61
+ # Given an object, returns a list `before_dequeue` hook names.
62
+ def before_dequeue_hooks(job)
63
+ job.methods.grep(/^before_dequeue/).sort
64
+ end
55
65
  end
56
66
  end
@@ -4,12 +4,22 @@ require 'resque'
4
4
  require 'resque/version'
5
5
  require 'time'
6
6
 
7
+ if defined? Encoding
8
+ Encoding.default_external = Encoding::UTF_8
9
+ end
10
+
7
11
  module Resque
8
12
  class Server < Sinatra::Base
9
13
  dir = File.dirname(File.expand_path(__FILE__))
10
14
 
11
15
  set :views, "#{dir}/server/views"
12
- set :public, "#{dir}/server/public"
16
+
17
+ if respond_to? :public_folder
18
+ set :public_folder, "#{dir}/server/public"
19
+ else
20
+ set :public, "#{dir}/server/public"
21
+ end
22
+
13
23
  set :static, true
14
24
 
15
25
  helpers do
@@ -177,21 +187,21 @@ module Resque
177
187
  end
178
188
 
179
189
  %w( overview workers ).each do |page|
180
- get "/#{page}.poll" do
190
+ get "/#{page}.poll/?" do
181
191
  show_for_polling(page)
182
192
  end
183
193
 
184
- get "/#{page}/:id.poll" do
194
+ get "/#{page}/:id.poll/?" do
185
195
  show_for_polling(page)
186
196
  end
187
197
  end
188
198
 
189
199
  %w( overview queues working workers key ).each do |page|
190
- get "/#{page}" do
200
+ get "/#{page}/?" do
191
201
  show page
192
202
  end
193
203
 
194
- get "/#{page}/:id" do
204
+ get "/#{page}/:id/?" do
195
205
  show page
196
206
  end
197
207
  end
@@ -201,7 +211,7 @@ module Resque
201
211
  redirect u('queues')
202
212
  end
203
213
 
204
- get "/failed" do
214
+ get "/failed/?" do
205
215
  if Resque::Failure.url
206
216
  redirect Resque::Failure.url
207
217
  else
@@ -221,7 +231,7 @@ module Resque
221
231
  redirect u('failed')
222
232
  end
223
233
 
224
- get "/failed/requeue/:index" do
234
+ get "/failed/requeue/:index/?" do
225
235
  Resque::Failure.requeue(params[:index])
226
236
  if request.xhr?
227
237
  return Resque::Failure.all(params[:index])['retried_at']
@@ -230,24 +240,24 @@ module Resque
230
240
  end
231
241
  end
232
242
 
233
- get "/failed/remove/:index" do
243
+ get "/failed/remove/:index/?" do
234
244
  Resque::Failure.remove(params[:index])
235
245
  redirect u('failed')
236
246
  end
237
247
 
238
- get "/stats" do
248
+ get "/stats/?" do
239
249
  redirect url_path("/stats/resque")
240
250
  end
241
251
 
242
- get "/stats/:id" do
252
+ get "/stats/:id/?" do
243
253
  show :stats
244
254
  end
245
255
 
246
- get "/stats/keys/:key" do
256
+ get "/stats/keys/:key/?" do
247
257
  show :stats
248
258
  end
249
259
 
250
- get "/stats.txt" do
260
+ get "/stats.txt/?" do
251
261
  info = Resque.info
252
262
 
253
263
  stats = []
@@ -48,6 +48,7 @@ body { padding:0; margin:0; }
48
48
 
49
49
 
50
50
  #main table.workers td.icon {width:1%; background:#efefef;text-align:center;}
51
+ #main table.workers td.icon img { height: 16px; width: 16px; }
51
52
  #main table.workers td.where { width:25%;}
52
53
  #main table.workers td.queues { width:35%;}
53
54
  #main .queue-tag { background:#b1d2e9; padding:2px; margin:0 3px; font-size:80%; text-decoration:none; text-transform:uppercase; font-weight:bold; color:#3274a2; -webkit-border-radius:4px; -moz-border-radius:4px;}
@@ -18,6 +18,13 @@ namespace :resque do
18
18
  abort "set QUEUE env var, e.g. $ QUEUE=critical,high rake resque:work"
19
19
  end
20
20
 
21
+ if ENV['BACKGROUND']
22
+ unless Process.respond_to?('daemon')
23
+ abort "env var BACKGROUND is set, which requires ruby >= 1.9"
24
+ end
25
+ Process.daemon(true)
26
+ end
27
+
21
28
  if ENV['PIDFILE']
22
29
  File.open(ENV['PIDFILE'], 'w') { |f| f << worker.pid }
23
30
  end
@@ -1,3 +1,3 @@
1
1
  module Resque
2
- Version = VERSION = '1.19.0.1'
2
+ Version = VERSION = '1.20.0'
3
3
  end
@@ -24,13 +24,13 @@ module Resque
24
24
 
25
25
  # Returns an array of all worker objects.
26
26
  def self.all
27
- mongo_workers.distinct(:worker).map{|worker| find(worker)}.compact
27
+ mongo_workers.distinct(:worker).map { |worker| find(worker) }.compact
28
28
  end
29
29
 
30
30
  # Returns an array of all worker objects currently processing
31
31
  # jobs.
32
32
  def self.working
33
- working = mongo_workers.find({ 'working_on' => { '$exists' => true}}).to_a.map{|w| find(w['worker'])}
33
+ mongo_workers.find('working_on' => { '$exists' => true }).to_a.map { |w| find(w['worker']) }
34
34
  end
35
35
 
36
36
  # Returns a single worker object. Accepts a string id.
@@ -53,7 +53,7 @@ module Resque
53
53
  # Given a string worker id, return a boolean indicating whether the
54
54
  # worker exists
55
55
  def self.exists?(worker_id)
56
- mongo_workers.find({ :worker => worker_id.to_s}).count > 0
56
+ mongo_workers.find(:worker => worker_id.to_s).count > 0
57
57
  end
58
58
 
59
59
  # Workers should be initialized with an array of string queue
@@ -108,13 +108,14 @@ module Resque
108
108
 
109
109
  if not paused? and job = reserve
110
110
  log "got: #{job.inspect}"
111
+ job.worker = self
111
112
  run_hook :before_fork, job
112
113
  working_on job
113
114
 
114
115
  if @child = fork
115
116
  srand # Reseeding
116
117
  procline "Forked #{@child} at #{Time.now.to_i}"
117
- Process.wait
118
+ Process.wait(@child)
118
119
  else
119
120
  procline "Processing #{job.queue} since #{Time.now.to_i}"
120
121
  perform(job, &block)
@@ -140,6 +141,7 @@ module Resque
140
141
  def process(job = nil, &block)
141
142
  return unless job ||= reserve
142
143
 
144
+ job.worker = self
143
145
  working_on job
144
146
  perform(job, &block)
145
147
  ensure
@@ -188,7 +190,7 @@ module Resque
188
190
  # A splat ("*") means you want every queue (in alpha order) - this
189
191
  # can be useful for dynamically adding new queues.
190
192
  def queues
191
- @queues[0] == "*" ? Resque.queues.sort : @queues
193
+ @queues.map {|queue| queue == "*" ? Resque.queues.sort : queue }.flatten.uniq
192
194
  end
193
195
 
194
196
  # Not every platform supports fork. Here we do our magic to
@@ -366,7 +368,6 @@ module Resque
366
368
  # Given a job, tells Mongo we're working on it. Useful for seeing
367
369
  # what workers are doing and when.
368
370
  def working_on(job)
369
- job.worker = self
370
371
  data = { :queue => job.queue,
371
372
  :run_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z"),
372
373
  :payload => job.payload }
@@ -459,7 +460,7 @@ module Resque
459
460
 
460
461
  # Returns Integer PID of running worker
461
462
  def pid
462
- @pid ||= to_s.split(":")[1].to_i
463
+ Process.pid
463
464
  end
464
465
 
465
466
  # Returns an Array of string pids of all the other workers on this
@@ -477,7 +478,7 @@ module Resque
477
478
  # Returns an Array of string pids of all the other workers on this
478
479
  # machine. Useful when pruning dead workers on startup.
479
480
  def linux_worker_pids
480
- `ps -A -o pid,command | grep [r]esque | grep -v "resque-web"`.split("\n").map do |line|
481
+ `ps -A -o pid,command | grep "[r]esque" | grep -v "resque-web"`.split("\n").map do |line|
481
482
  line.split(' ')[0]
482
483
  end
483
484
  end
@@ -487,7 +488,7 @@ module Resque
487
488
  # Returns an Array of string pids of all the other workers on this
488
489
  # machine. Useful when pruning dead workers on startup.
489
490
  def solaris_worker_pids
490
- `ps -A -o pid,comm | grep [r]uby | grep -v "resque-web"`.split("\n").map do |line|
491
+ `ps -A -o pid,comm | grep "[r]uby" | grep -v "resque-web"`.split("\n").map do |line|
491
492
  real_pid = line.split(' ')[0]
492
493
  pargs_command = `pargs -a #{real_pid} 2>/dev/null | grep [r]esque | grep -v "resque-web"`
493
494
  if pargs_command.split(':')[1] == " resque-#{Resque::Version}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo-resque
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.0.1
4
+ version: 1.20.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-07 00:00:00.000000000Z
12
+ date: 2012-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongo
16
- requirement: &2158173220 !ruby/object:Gem::Requirement
16
+ requirement: &70251593593060 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '1.3'
21
+ version: '1.5'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2158173220
24
+ version_requirements: *70251593593060
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: vegas
27
- requirement: &2158172720 !ruby/object:Gem::Requirement
27
+ requirement: &70251593592440 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.1.2
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2158172720
35
+ version_requirements: *70251593592440
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sinatra
38
- requirement: &2158172260 !ruby/object:Gem::Requirement
38
+ requirement: &70251593591880 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.2
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2158172260
46
+ version_requirements: *70251593591880
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: multi_json
49
- requirement: &2158171800 !ruby/object:Gem::Requirement
49
+ requirement: &70251593591240 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '1.0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2158171800
57
+ version_requirements: *70251593591240
58
58
  description: ! " Resque is a Redis-backed Ruby library for creating background
59
59
  jobs,\n placing those jobs on multiple queues, and processing them later.\n\n
60
60
  \ Mongo-Resque is the same thing, but for mongo. It would not exist\n without
@@ -127,15 +127,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
127
  - - ! '>='
128
128
  - !ruby/object:Gem::Version
129
129
  version: '0'
130
+ segments:
131
+ - 0
132
+ hash: -2109137887324305574
130
133
  required_rubygems_version: !ruby/object:Gem::Requirement
131
134
  none: false
132
135
  requirements:
133
136
  - - ! '>='
134
137
  - !ruby/object:Gem::Version
135
138
  version: '0'
139
+ segments:
140
+ - 0
141
+ hash: -2109137887324305574
136
142
  requirements: []
137
143
  rubyforge_project:
138
- rubygems_version: 1.8.6
144
+ rubygems_version: 1.8.17
139
145
  signing_key:
140
146
  specification_version: 3
141
147
  summary: Mongo-Resque is a mongo-backed queueing system