resque-loner 1.2.1 → 1.3.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.
@@ -1,14 +1,30 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
+
4
+ require 'codeclimate-test-reporter'
5
+ CodeClimate::TestReporter.start
6
+
7
+ require 'English'
8
+ require 'simplecov'
9
+
3
10
  require 'rspec'
4
11
 
5
- require 'ruby-debug'
6
- require 'mock_redis'
7
12
  require 'resque'
8
13
  require 'resque-loner'
9
14
 
15
+ module Support
16
+ class << self
17
+ attr_accessor :redis_pid
18
+ end
19
+ end
20
+
10
21
  RSpec.configure do |config|
11
22
  config.before(:suite) do
12
- Resque.redis = MockRedis.new
23
+ unless ENV['RESQUE_LONER_DISABLE_TEST_REDIS_SERVER']
24
+ # Start our own Redis when the tests start. RedisInstance will take care of
25
+ # starting and stopping.
26
+ require File.expand_path('../support/redis_instance', __FILE__)
27
+ RedisInstance.run!
28
+ end
13
29
  end
14
30
  end
@@ -0,0 +1,133 @@
1
+ # vim:fileencoding=utf-8
2
+ require 'socket'
3
+ require 'timeout'
4
+ require 'fileutils'
5
+
6
+ class RedisInstance # rubocop:disable ClassLength
7
+ class << self
8
+ @running = false
9
+ @port = nil
10
+ @pid = nil
11
+ @waiting = false
12
+
13
+ def run_if_needed!
14
+ run! unless @running
15
+ end
16
+
17
+ def run!
18
+ ensure_redis_server_present!
19
+ ensure_pid_directory
20
+ reassign_redis_clients
21
+ start_redis_server
22
+ post_boot_waiting_and_such
23
+
24
+ @running = true
25
+ end
26
+
27
+ def stop!
28
+ $stdout.puts "Sending TERM to Redis (#{pid})..."
29
+ Process.kill('TERM', pid)
30
+
31
+ @port = nil
32
+ @running = false
33
+ @pid = nil
34
+ end
35
+
36
+ private
37
+
38
+ def post_boot_waiting_and_such
39
+ wait_for_pid
40
+ puts "Booted isolated Redis on #{port} with PID #{pid}."
41
+
42
+ wait_for_redis_boot
43
+
44
+ # Ensure we tear down Redis on Ctrl+C / test failure.
45
+ at_exit { stop! }
46
+ end
47
+
48
+ def ensure_redis_server_present!
49
+ unless system('redis-server -v')
50
+ fail "** can't find `redis-server` in your path"
51
+ end
52
+ end
53
+
54
+ def wait_for_redis_boot
55
+ Timeout.timeout(10) do
56
+ loop do
57
+ begin
58
+ break if Resque.redis.ping == 'PONG'
59
+ rescue Redis::CannotConnectError
60
+ @waiting = true
61
+ end
62
+ end
63
+ @waiting = false
64
+ end
65
+ end
66
+
67
+ def ensure_pid_directory
68
+ FileUtils.mkdir_p(File.dirname(pid_file))
69
+ end
70
+
71
+ def reassign_redis_clients
72
+ Resque.redis = Redis.new(
73
+ hostname: '127.0.0.1', port: port, thread_safe: true
74
+ )
75
+ end
76
+
77
+ def start_redis_server
78
+ IO.popen('redis-server -', 'w+') do |server|
79
+ server.write(config)
80
+ server.close_write
81
+ end
82
+ end
83
+
84
+ def pid
85
+ @pid ||= File.read(pid_file).to_i
86
+ end
87
+
88
+ def wait_for_pid
89
+ Timeout.timeout(10) do
90
+ loop { break if File.exist?(pid_file) }
91
+ end
92
+ end
93
+
94
+ def port
95
+ @port ||= random_port
96
+ end
97
+
98
+ def pid_file
99
+ '/tmp/redis-loner-test.pid'
100
+ end
101
+
102
+ def config
103
+ <<-EOF
104
+ daemonize yes
105
+ pidfile #{pid_file}
106
+ port #{port}
107
+ EOF
108
+ end
109
+
110
+ # Returns a random port in the upper (10000-65535) range.
111
+ def random_port
112
+ ports = (10_000..65_535).to_a
113
+
114
+ loop do
115
+ port = ports[rand(ports.size)]
116
+ return port if port_available?('127.0.0.1', port)
117
+ end
118
+ end
119
+
120
+ def port_available?(ip, port, seconds = 1)
121
+ Timeout.timeout(seconds) do
122
+ begin
123
+ TCPSocket.new(ip, port).close
124
+ false
125
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
126
+ true
127
+ end
128
+ end
129
+ rescue Timeout::Error
130
+ true
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,27 @@
1
+
2
+ require 'test_helper'
3
+
4
+ begin
5
+ require 'airbrake'
6
+ rescue LoadError
7
+ warn 'Install airbrake gem to run Airbrake tests.'
8
+ end
9
+
10
+ if defined? Airbrake
11
+ require 'resque/failure/airbrake'
12
+ context 'Airbrake' do
13
+ test 'should be notified of an error' do
14
+ exception = StandardError.new('BOOM')
15
+ worker = Resque::Worker.new(:test)
16
+ queue = 'test'
17
+ payload = { 'class' => Object, 'args' => 66 }
18
+
19
+ Airbrake.expects(:notify_or_ignore).with(
20
+ exception,
21
+ parameters: { payload_class: 'Object', payload_args: '66' })
22
+
23
+ backend = Resque::Failure::Airbrake.new(exception, worker, queue, payload)
24
+ backend.save
25
+ end
26
+ end
27
+ end
Binary file
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- context "Resque::Job before_perform" do
3
+ context 'Resque::Job before_perform' do
4
4
  include PerformJob
5
5
 
6
6
  class ::BeforePerformJob
@@ -13,48 +13,48 @@ context "Resque::Job before_perform" do
13
13
  end
14
14
  end
15
15
 
16
- test "it runs before_perform before perform" do
17
- result = perform_job(BeforePerformJob, history=[])
18
- assert_equal true, result, "perform returned true"
16
+ test 'it runs before_perform before perform' do
17
+ result = perform_job(BeforePerformJob, history = [])
18
+ assert_equal true, result, 'perform returned true'
19
19
  assert_equal history, [:before_perform, :perform]
20
20
  end
21
21
 
22
22
  class ::BeforePerformJobFails
23
23
  def self.before_perform_fail_job(history)
24
24
  history << :before_perform
25
- raise StandardError
25
+ fail StandardError
26
26
  end
27
27
  def self.perform(history)
28
28
  history << :perform
29
29
  end
30
30
  end
31
31
 
32
- test "raises an error and does not perform if before_perform fails" do
32
+ test 'raises an error and does not perform if before_perform fails' do
33
33
  history = []
34
34
  assert_raises StandardError do
35
35
  perform_job(BeforePerformJobFails, history)
36
36
  end
37
- assert_equal history, [:before_perform], "Only before_perform was run"
37
+ assert_equal history, [:before_perform], 'Only before_perform was run'
38
38
  end
39
39
 
40
40
  class ::BeforePerformJobAborts
41
41
  def self.before_perform_abort(history)
42
42
  history << :before_perform
43
- raise Resque::Job::DontPerform
43
+ fail Resque::Job::DontPerform
44
44
  end
45
45
  def self.perform(history)
46
46
  history << :perform
47
47
  end
48
48
  end
49
49
 
50
- test "does not perform if before_perform raises Resque::Job::DontPerform" do
51
- result = perform_job(BeforePerformJobAborts, history=[])
52
- assert_equal false, result, "perform returned false"
53
- assert_equal history, [:before_perform], "Only before_perform was run"
50
+ test 'does not perform if before_perform raises Resque::Job::DontPerform' do
51
+ result = perform_job(BeforePerformJobAborts, history = [])
52
+ assert_equal false, result, 'perform returned false'
53
+ assert_equal history, [:before_perform], 'Only before_perform was run'
54
54
  end
55
55
  end
56
56
 
57
- context "Resque::Job after_perform" do
57
+ context 'Resque::Job after_perform' do
58
58
  include PerformJob
59
59
 
60
60
  class ::AfterPerformJob
@@ -66,9 +66,9 @@ context "Resque::Job after_perform" do
66
66
  end
67
67
  end
68
68
 
69
- test "it runs after_perform after perform" do
70
- result = perform_job(AfterPerformJob, history=[])
71
- assert_equal true, result, "perform returned true"
69
+ test 'it runs after_perform after perform' do
70
+ result = perform_job(AfterPerformJob, history = [])
71
+ assert_equal true, result, 'perform returned true'
72
72
  assert_equal history, [:perform, :after_perform]
73
73
  end
74
74
 
@@ -78,20 +78,20 @@ context "Resque::Job after_perform" do
78
78
  end
79
79
  def self.after_perform_fail_job(history)
80
80
  history << :after_perform
81
- raise StandardError
81
+ fail StandardError
82
82
  end
83
83
  end
84
84
 
85
- test "raises an error but has already performed if after_perform fails" do
85
+ test 'raises an error but has already performed if after_perform fails' do
86
86
  history = []
87
87
  assert_raises StandardError do
88
88
  perform_job(AfterPerformJobFails, history)
89
89
  end
90
- assert_equal history, [:perform, :after_perform], "Only after_perform was run"
90
+ assert_equal history, [:perform, :after_perform], 'Only after_perform was run'
91
91
  end
92
92
  end
93
93
 
94
- context "Resque::Job around_perform" do
94
+ context 'Resque::Job around_perform' do
95
95
  include PerformJob
96
96
 
97
97
  class ::AroundPerformJob
@@ -105,9 +105,9 @@ context "Resque::Job around_perform" do
105
105
  end
106
106
  end
107
107
 
108
- test "it runs around_perform then yields in order to perform" do
109
- result = perform_job(AroundPerformJob, history=[])
110
- assert_equal true, result, "perform returned true"
108
+ test 'it runs around_perform then yields in order to perform' do
109
+ result = perform_job(AroundPerformJob, history = [])
110
+ assert_equal true, result, 'perform returned true'
111
111
  assert_equal history, [:start_around_perform, :perform, :finish_around_perform]
112
112
  end
113
113
 
@@ -117,24 +117,24 @@ context "Resque::Job around_perform" do
117
117
  end
118
118
  def self.around_perform_fail(history)
119
119
  history << :start_around_perform
120
- raise StandardError
120
+ fail StandardError
121
121
  yield
122
122
  history << :finish_around_perform
123
123
  end
124
124
  end
125
125
 
126
- test "raises an error and does not perform if around_perform fails before yielding" do
126
+ test 'raises an error and does not perform if around_perform fails before yielding' do
127
127
  history = []
128
128
  assert_raises StandardError do
129
129
  perform_job(AroundPerformJobFailsBeforePerforming, history)
130
130
  end
131
- assert_equal history, [:start_around_perform], "Only part of around_perform was run"
131
+ assert_equal history, [:start_around_perform], 'Only part of around_perform was run'
132
132
  end
133
133
 
134
134
  class ::AroundPerformJobFailsWhilePerforming
135
135
  def self.perform(history)
136
136
  history << :perform
137
- raise StandardError
137
+ fail StandardError
138
138
  end
139
139
  def self.around_perform_fail_in_yield(history)
140
140
  history << :start_around_perform
@@ -147,12 +147,12 @@ context "Resque::Job around_perform" do
147
147
  end
148
148
  end
149
149
 
150
- test "raises an error but may handle exceptions if perform fails" do
150
+ test 'raises an error but may handle exceptions if perform fails' do
151
151
  history = []
152
152
  assert_raises StandardError do
153
153
  perform_job(AroundPerformJobFailsWhilePerforming, history)
154
154
  end
155
- assert_equal history, [:start_around_perform, :perform, :ensure_around_perform], "Only part of around_perform was run"
155
+ assert_equal history, [:start_around_perform, :perform, :ensure_around_perform], 'Only part of around_perform was run'
156
156
  end
157
157
 
158
158
  class ::AroundPerformJobDoesNotHaveToYield
@@ -165,15 +165,15 @@ context "Resque::Job around_perform" do
165
165
  end
166
166
  end
167
167
 
168
- test "around_perform is not required to yield" do
168
+ test 'around_perform is not required to yield' do
169
169
  history = []
170
170
  result = perform_job(AroundPerformJobDoesNotHaveToYield, history)
171
- assert_equal false, result, "perform returns false"
172
- assert_equal history, [:start_around_perform, :finish_around_perform], "perform was not run"
171
+ assert_equal false, result, 'perform returns false'
172
+ assert_equal history, [:start_around_perform, :finish_around_perform], 'perform was not run'
173
173
  end
174
174
  end
175
175
 
176
- context "Resque::Job on_failure" do
176
+ context 'Resque::Job on_failure' do
177
177
  include PerformJob
178
178
 
179
179
  class ::FailureJobThatDoesNotFail
@@ -185,50 +185,50 @@ context "Resque::Job on_failure" do
185
185
  end
186
186
  end
187
187
 
188
- test "it does not call on_failure if no failures occur" do
189
- result = perform_job(FailureJobThatDoesNotFail, history=[])
190
- assert_equal true, result, "perform returned true"
188
+ test 'it does not call on_failure if no failures occur' do
189
+ result = perform_job(FailureJobThatDoesNotFail, history = [])
190
+ assert_equal true, result, 'perform returned true'
191
191
  assert_equal history, [:perform]
192
192
  end
193
193
 
194
194
  class ::FailureJobThatFails
195
195
  def self.perform(history)
196
196
  history << :perform
197
- raise StandardError, "oh no"
197
+ fail StandardError, 'oh no'
198
198
  end
199
199
  def self.on_failure_record_failure(exception, history)
200
200
  history << exception.message
201
201
  end
202
202
  end
203
203
 
204
- test "it calls on_failure with the exception and then re-raises the exception" do
204
+ test 'it calls on_failure with the exception and then re-raises the exception' do
205
205
  history = []
206
206
  assert_raises StandardError do
207
207
  perform_job(FailureJobThatFails, history)
208
208
  end
209
- assert_equal history, [:perform, "oh no"]
209
+ assert_equal history, [:perform, 'oh no']
210
210
  end
211
211
 
212
212
  class ::FailureJobThatFailsBadly
213
213
  def self.perform(history)
214
214
  history << :perform
215
- raise SyntaxError, "oh no"
215
+ fail SyntaxError, 'oh no'
216
216
  end
217
217
  def self.on_failure_record_failure(exception, history)
218
218
  history << exception.message
219
219
  end
220
220
  end
221
221
 
222
- test "it calls on_failure even with bad exceptions" do
222
+ test 'it calls on_failure even with bad exceptions' do
223
223
  history = []
224
224
  assert_raises SyntaxError do
225
225
  perform_job(FailureJobThatFailsBadly, history)
226
226
  end
227
- assert_equal history, [:perform, "oh no"]
227
+ assert_equal history, [:perform, 'oh no']
228
228
  end
229
229
  end
230
230
 
231
- context "Resque::Job after_enqueue" do
231
+ context 'Resque::Job after_enqueue' do
232
232
  include PerformJob
233
233
 
234
234
  class ::AfterEnqueueJob
@@ -241,16 +241,114 @@ context "Resque::Job after_enqueue" do
241
241
  end
242
242
  end
243
243
 
244
- test "the after enqueue hook should run" do
244
+ test 'the after enqueue hook should run' do
245
245
  history = []
246
246
  @worker = Resque::Worker.new(:jobs)
247
247
  Resque.enqueue(AfterEnqueueJob, history)
248
248
  @worker.work(0)
249
- assert_equal history, [:after_enqueue], "after_enqueue was not run"
249
+ assert_equal history, [:after_enqueue], 'after_enqueue was not run'
250
250
  end
251
251
  end
252
252
 
253
- context "Resque::Job all hooks" do
253
+ context 'Resque::Job before_enqueue' do
254
+ include PerformJob
255
+
256
+ class ::BeforeEnqueueJob
257
+ @queue = :jobs
258
+ def self.before_enqueue_record_history(history)
259
+ history << :before_enqueue
260
+ end
261
+
262
+ def self.perform(history)
263
+ end
264
+ end
265
+
266
+ class ::BeforeEnqueueJobAbort
267
+ @queue = :jobs
268
+ def self.before_enqueue_abort(history)
269
+ false
270
+ end
271
+
272
+ def self.perform(history)
273
+ end
274
+ end
275
+
276
+ test 'the before enqueue hook should run' do
277
+ history = []
278
+ @worker = Resque::Worker.new(:jobs)
279
+ assert Resque.enqueue(BeforeEnqueueJob, history)
280
+ @worker.work(0)
281
+ assert_equal history, [:before_enqueue], 'before_enqueue was not run'
282
+ end
283
+
284
+ test 'a before enqueue hook that returns false should prevent the job from getting queued' do
285
+ history = []
286
+ @worker = Resque::Worker.new(:jobs)
287
+ assert_nil Resque.enqueue(BeforeEnqueueJobAbort, history)
288
+ assert_equal 0, Resque.size(:jobs)
289
+ end
290
+ end
291
+
292
+ context 'Resque::Job after_dequeue' do
293
+ include PerformJob
294
+
295
+ class ::AfterDequeueJob
296
+ @queue = :jobs
297
+ def self.after_dequeue_record_history(history)
298
+ history << :after_dequeue
299
+ end
300
+
301
+ def self.perform(history)
302
+ end
303
+ end
304
+
305
+ test 'the after dequeue hook should run' do
306
+ history = []
307
+ @worker = Resque::Worker.new(:jobs)
308
+ Resque.dequeue(AfterDequeueJob, history)
309
+ @worker.work(0)
310
+ assert_equal history, [:after_dequeue], 'after_dequeue was not run'
311
+ end
312
+ end
313
+
314
+ context 'Resque::Job before_dequeue' do
315
+ include PerformJob
316
+
317
+ class ::BeforeDequeueJob
318
+ @queue = :jobs
319
+ def self.before_dequeue_record_history(history)
320
+ history << :before_dequeue
321
+ end
322
+
323
+ def self.perform(history)
324
+ end
325
+ end
326
+
327
+ class ::BeforeDequeueJobAbort
328
+ @queue = :jobs
329
+ def self.before_dequeue_abort(history)
330
+ false
331
+ end
332
+
333
+ def self.perform(history)
334
+ end
335
+ end
336
+
337
+ test 'the before dequeue hook should run' do
338
+ history = []
339
+ @worker = Resque::Worker.new(:jobs)
340
+ Resque.dequeue(BeforeDequeueJob, history)
341
+ @worker.work(0)
342
+ assert_equal history, [:before_dequeue], 'before_dequeue was not run'
343
+ end
344
+
345
+ test 'a before dequeue hook that returns false should prevent the job from getting dequeued' do
346
+ history = []
347
+ assert_equal nil, Resque.dequeue(BeforeDequeueJobAbort, history)
348
+ end
349
+ end
350
+
351
+ context 'Resque::Job all hooks' do
254
352
  include PerformJob
255
353
 
256
354
  class ::VeryHookyJob
@@ -273,9 +371,9 @@ context "Resque::Job all hooks" do
273
371
  end
274
372
  end
275
373
 
276
- test "the complete hook order" do
277
- result = perform_job(VeryHookyJob, history=[])
278
- assert_equal true, result, "perform returned true"
374
+ test 'the complete hook order' do
375
+ result = perform_job(VeryHookyJob, history = [])
376
+ assert_equal true, result, 'perform returned true'
279
377
  assert_equal history, [
280
378
  :before_perform,
281
379
  :start_around_perform,
@@ -299,14 +397,14 @@ context "Resque::Job all hooks" do
299
397
  end
300
398
  def self.after_perform_record_history(history)
301
399
  history << :after_perform
302
- raise StandardError, "oh no"
400
+ fail StandardError, 'oh no'
303
401
  end
304
402
  def self.on_failure_record_history(exception, history)
305
403
  history << exception.message
306
404
  end
307
405
  end
308
406
 
309
- test "the complete hook order with a failure at the last minute" do
407
+ test 'the complete hook order with a failure at the last minute' do
310
408
  history = []
311
409
  assert_raises StandardError do
312
410
  perform_job(VeryHookyJobThatFails, history)
@@ -317,7 +415,48 @@ context "Resque::Job all hooks" do
317
415
  :perform,
318
416
  :finish_around_perform,
319
417
  :after_perform,
320
- "oh no"
418
+ 'oh no'
321
419
  ]
322
420
  end
421
+
422
+ class ::CallbacksInline
423
+ @queue = :callbacks_inline
424
+
425
+ def self.before_perform_record_history(history, count)
426
+ history << :before_perform
427
+ count['count'] += 1
428
+ end
429
+
430
+ def self.after_perform_record_history(history, count)
431
+ history << :after_perform
432
+ count['count'] += 1
433
+ end
434
+
435
+ def self.around_perform_record_history(history, count)
436
+ history << :start_around_perform
437
+ count['count'] += 1
438
+ yield
439
+ history << :finish_around_perform
440
+ count['count'] += 1
441
+ end
442
+
443
+ def self.perform(history, count)
444
+ history << :perform
445
+ $history = history
446
+ $count = count
447
+ end
448
+ end
449
+
450
+ test 'it runs callbacks when inline is true' do
451
+ begin
452
+ Resque.inline = true
453
+ # Sending down two parameters that can be passed and updated by reference
454
+ result = Resque.enqueue(CallbacksInline, [], 'count' => 0)
455
+ assert_equal true, result, 'perform returned true'
456
+ assert_equal $history, [:before_perform, :start_around_perform, :perform, :finish_around_perform, :after_perform]
457
+ assert_equal 4, $count['count']
458
+ ensure
459
+ Resque.inline = false
460
+ end
461
+ end
323
462
  end