mongo-resque 1.19.0.1 → 1.20.0

Sign up to get free protection for your applications and to get access to all the features.
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