resque 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of resque might be problematic. Click here for more details.

data/HISTORY.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 1.8.0 (2010-04-07)
2
+
3
+ * Jobs that never complete due to killed worker are now failed.
4
+ * Worker "working" state is now maintained by the parent, not the child.
5
+ * Stopped using deprecated redis.rb methods
6
+ * `Worker.working` race condition fixed
7
+ * `Worker#process` has been deprecated.
8
+ * Monit example fixed
9
+ * Redis::Client and Redis::Namespace can be passed to `Resque.redis=`
10
+
1
11
  ## 1.7.1 (2010-04-02)
2
12
 
3
13
  * Bugfix: Make job hook execution order consistent
@@ -86,8 +86,8 @@ Plugins should test compliance to this document using the
86
86
 
87
87
  For example:
88
88
 
89
- def test_lint
90
- assert Resque::Plugin.lint(Resque::Plugins::Lock)
89
+ assert_nothing_raised do
90
+ Resque::Plugin.lint(Resque::Plugins::Lock)
91
91
  end
92
92
 
93
93
  [sv]: http://semver.org/
@@ -1,6 +1,6 @@
1
1
  check process resque_worker_QUEUE
2
2
  with pidfile /data/APP_NAME/current/tmp/pids/resque_worker_QUEUE.pid
3
- start program = "/bin/sh -c 'cd /data/APP_NAME/current; RAILS_ENV=production QUEUE=queue_name VERBOSE=1 nohup rake resque:work &> log/resque_worker_QUEUE.log && echo $! > tmp/pids/resque_worker_QUEUE.pid'" as uid deploy and gid deploy
3
+ start program = "/bin/sh -c 'cd /data/APP_NAME/current; RAILS_ENV=production QUEUE=queue_name VERBOSE=1 nohup rake resque:work& &> log/resque_worker_QUEUE.log && echo $! > tmp/pids/resque_worker_QUEUE.pid'" as uid deploy and gid deploy
4
4
  stop program = "/bin/sh -c 'cd /data/APP_NAME/current && kill -s QUIT `cat tmp/pids/resque_worker_QUEUE.pid` && rm -f tmp/pids/resque_worker_QUEUE.pid; exit 0;'"
5
5
  if totalmem is greater than 300 MB for 10 cycles then restart # eating up memory?
6
6
  group resque_workers
@@ -26,7 +26,7 @@ module Resque
26
26
  # Accepts:
27
27
  # 1. A 'hostname:port' string
28
28
  # 2. A 'hostname:port:db' string (to select the Redis db)
29
- # 3. An instance of `Redis`
29
+ # 3. An instance of `Redis`, `Redis::Client`, or `Redis::Namespace`.
30
30
  def redis=(server)
31
31
  case server
32
32
  when String
@@ -34,8 +34,10 @@ module Resque
34
34
  redis = Redis.new(:host => host, :port => port,
35
35
  :thread_safe => true, :db => db)
36
36
  @redis = Redis::Namespace.new(:resque, :redis => redis)
37
- when Redis
37
+ when Redis, Redis::Client
38
38
  @redis = Redis::Namespace.new(:resque, :redis => server)
39
+ when Redis::Namespace
40
+ @redis = server
39
41
  else
40
42
  raise "I don't know what to do with #{server.inspect}"
41
43
  end
@@ -4,4 +4,7 @@ module Resque
4
4
 
5
5
  # Raised when trying to create a job without a class
6
6
  class NoClassError < RuntimeError; end
7
+
8
+ # Raised when a worker was killed while processing a job.
9
+ class DirtyExit < RuntimeError; end
7
10
  end
@@ -24,7 +24,7 @@ module Resque
24
24
  # Can optionally accept a second int parameter. The stat is then
25
25
  # incremented by that amount.
26
26
  def incr(stat, by = 1)
27
- redis.incr("stat:#{stat}", by)
27
+ redis.incrby("stat:#{stat}", by)
28
28
  end
29
29
 
30
30
  # Increments a stat by one.
@@ -37,7 +37,7 @@ module Resque
37
37
  # Can optionally accept a second int parameter. The stat is then
38
38
  # decremented by that amount.
39
39
  def decr(stat, by = 1)
40
- redis.decr("stat:#{stat}", by)
40
+ redis.decrby("stat:#{stat}", by)
41
41
  end
42
42
 
43
43
  # Decrements a stat by one.
@@ -1,3 +1,3 @@
1
1
  module Resque
2
- Version = '1.7.1'
2
+ Version = '1.8.0'
3
3
  end
@@ -35,7 +35,7 @@ module Resque
35
35
  names.map! { |name| "worker:#{name}" }
36
36
  redis.mapped_mget(*names).keys.map do |key|
37
37
  find key.sub("worker:", '')
38
- end
38
+ end.compact
39
39
  end
40
40
 
41
41
  # Returns a single worker object. Accepts a string id.
@@ -113,6 +113,7 @@ module Resque
113
113
  if not @paused and job = reserve
114
114
  log "got: #{job.inspect}"
115
115
  run_hook :before_fork
116
+ working_on job
116
117
 
117
118
  if @child = fork
118
119
  rand # Reseeding
@@ -120,10 +121,11 @@ module Resque
120
121
  Process.wait
121
122
  else
122
123
  procline "Processing #{job.queue} since #{Time.now.to_i}"
123
- process(job, &block)
124
+ perform(job, &block)
124
125
  exit! unless @cant_fork
125
126
  end
126
127
 
128
+ done_working
127
129
  @child = nil
128
130
  else
129
131
  break if interval.to_i == 0
@@ -137,15 +139,21 @@ module Resque
137
139
  unregister_worker
138
140
  end
139
141
 
140
- # Processes a single job. If none is given, it will try to produce
141
- # one.
142
- def process(job = nil)
142
+ # DEPRECATED. Processes a single job. If none is given, it will
143
+ # try to produce one. Usually run in the child.
144
+ def process(job = nil, &block)
143
145
  return unless job ||= reserve
144
146
 
147
+ working_on job
148
+ perform(job, &block)
149
+ ensure
150
+ done_working
151
+ end
152
+
153
+ # Processes a given job in the child.
154
+ def perform(job)
145
155
  begin
146
- job.worker = self
147
156
  run_hook :after_fork, job
148
- working_on job
149
157
  job.perform
150
158
  rescue Object => e
151
159
  log "#{job.inspect} failed: #{e.inspect}"
@@ -155,7 +163,6 @@ module Resque
155
163
  log "done: #{job.inspect}"
156
164
  ensure
157
165
  yield job if block_given?
158
- done_working
159
166
  end
160
167
  end
161
168
 
@@ -326,6 +333,16 @@ module Resque
326
333
 
327
334
  # Unregisters ourself as a worker. Useful when shutting down.
328
335
  def unregister_worker
336
+ # If we're still processing a job, make sure it gets logged as a
337
+ # failure.
338
+ if (hash = processing) && !hash.empty?
339
+ job = Job.new(hash['queue'], hash['payload'])
340
+ # Ensure the proper worker is attached to this job, even if
341
+ # it's not the precise instance that died.
342
+ job.worker = self
343
+ job.fail(DirtyExit.new)
344
+ end
345
+
329
346
  redis.srem(:workers, self)
330
347
  redis.del("worker:#{self}")
331
348
  redis.del("worker:#{self}:started")
@@ -337,6 +354,7 @@ module Resque
337
354
  # Given a job, tells Redis we're working on it. Useful for seeing
338
355
  # what workers are doing and when.
339
356
  def working_on(job)
357
+ job.worker = self
340
358
  data = encode \
341
359
  :queue => job.queue,
342
360
  :run_at => Time.now.to_s,
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  context "Resque" do
4
4
  setup do
5
- Resque.redis.flush_all
5
+ Resque.redis.flushall
6
6
 
7
7
  Resque.push(:people, { 'name' => 'chris' })
8
8
  Resque.push(:people, { 'name' => 'bob' })
@@ -166,7 +166,7 @@ context "Resque" do
166
166
  end
167
167
 
168
168
  test "queues are always a list" do
169
- Resque.redis.flush_all
169
+ Resque.redis.flushall
170
170
  assert_equal [], Resque.queues
171
171
  end
172
172
 
@@ -202,6 +202,7 @@ context "Resque" do
202
202
  @worker = Resque::Worker.new(:jobs)
203
203
  @worker.register_worker
204
204
  2.times { @worker.process }
205
+
205
206
  job = @worker.reserve
206
207
  @worker.working_on job
207
208
 
@@ -217,7 +218,7 @@ context "Resque" do
217
218
  assert_equal 1, stats[:failed]
218
219
  assert_equal ['localhost:9736'], stats[:servers]
219
220
  end
220
-
221
+
221
222
  test "decode bad json" do
222
223
  assert_nil Resque.decode("{\"error\":\"Module not found \\u002\"}")
223
224
  end
@@ -108,4 +108,4 @@ class BadJobWithSyntaxError
108
108
  def self.perform
109
109
  raise SyntaxError, "Extra Bad job!"
110
110
  end
111
- end
111
+ end
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  context "Resque::Worker" do
4
4
  setup do
5
- Resque.redis.flush_all
5
+ Resque.redis.flushall
6
6
 
7
7
  Resque.before_first_fork = nil
8
8
  Resque.before_fork = nil
@@ -18,13 +18,20 @@ context "Resque::Worker" do
18
18
  assert_equal 1, Resque::Failure.count
19
19
  end
20
20
 
21
- test "failed jobs report excpetion and message" do
21
+ test "failed jobs report exception and message" do
22
22
  Resque::Job.create(:jobs, BadJobWithSyntaxError)
23
23
  @worker.work(0)
24
24
  assert_equal('SyntaxError', Resque::Failure.all['exception'])
25
25
  assert_equal('Extra Bad job!', Resque::Failure.all['error'])
26
26
  end
27
27
 
28
+ test "fails uncompleted jobs on exit" do
29
+ job = Resque::Job.new(:jobs, [GoodJob, "blah"])
30
+ @worker.working_on(job)
31
+ @worker.unregister_worker
32
+ assert_equal 1, Resque::Failure.count
33
+ end
34
+
28
35
  test "can peek at failed jobs" do
29
36
  10.times { Resque::Job.create(:jobs, BadJob) }
30
37
  @worker.work(0)
@@ -253,7 +260,7 @@ context "Resque::Worker" do
253
260
  end
254
261
 
255
262
  test "Will call a before_first_fork hook only once" do
256
- Resque.redis.flush_all
263
+ Resque.redis.flushall
257
264
  $BEFORE_FORK_CALLED = 0
258
265
  Resque.before_first_fork = Proc.new { $BEFORE_FORK_CALLED += 1 }
259
266
  workerA = Resque::Worker.new(:jobs)
@@ -270,7 +277,7 @@ context "Resque::Worker" do
270
277
  end
271
278
 
272
279
  test "Will call a before_fork hook before forking" do
273
- Resque.redis.flush_all
280
+ Resque.redis.flushall
274
281
  $BEFORE_FORK_CALLED = false
275
282
  Resque.before_fork = Proc.new { $BEFORE_FORK_CALLED = true }
276
283
  workerA = Resque::Worker.new(:jobs)
@@ -282,7 +289,7 @@ context "Resque::Worker" do
282
289
  end
283
290
 
284
291
  test "Will call an after_fork hook after forking" do
285
- Resque.redis.flush_all
292
+ Resque.redis.flushall
286
293
  $AFTER_FORK_CALLED = false
287
294
  Resque.after_fork = Proc.new { $AFTER_FORK_CALLED = true }
288
295
  workerA = Resque::Worker.new(:jobs)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-04-02 00:00:00 -07:00
12
+ date: 2010-04-07 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency