sidekiq 3.5.4 → 4.0.0.pre1

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

Potentially problematic release.


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

@@ -20,7 +20,7 @@ class TestFetcher < Sidekiq::Test
20
20
  uow = fetch.retrieve_work
21
21
  refute_nil uow
22
22
  assert_equal 'basic', uow.queue_name
23
- assert_equal 'msg', uow.message
23
+ assert_equal 'msg', uow.job
24
24
  q = Sidekiq::Queue.new('basic')
25
25
  assert_equal 0, q.size
26
26
  uow.requeue
@@ -31,7 +31,7 @@ class TestFetcher < Sidekiq::Test
31
31
  it 'retrieves with strict setting' do
32
32
  fetch = Sidekiq::BasicFetch.new(:queues => ['basic', 'bar', 'bar'], :strict => true)
33
33
  cmd = fetch.queues_cmd
34
- assert_equal cmd, ['queue:basic', 'queue:bar', 1]
34
+ assert_equal cmd, ['queue:basic', 'queue:bar', Sidekiq::BasicFetch::TIMEOUT]
35
35
  end
36
36
 
37
37
  it 'bulk requeues' do
@@ -45,60 +45,5 @@ class TestFetcher < Sidekiq::Test
45
45
  assert_equal 1, q2.size
46
46
  end
47
47
 
48
- describe 'fetching' do
49
- before do
50
- Sidekiq::Fetcher.reset
51
- end
52
-
53
- it 'instantiates' do
54
- begin
55
- Sidekiq.options[:fetch] = NullFetch
56
- mgr = Minitest::Mock.new
57
- fetch = Sidekiq::Fetcher.new(mgr, {})
58
- fetch.fetch
59
- Sidekiq::Fetcher.done!
60
- ensure
61
- Sidekiq.options[:fetch] = Sidekiq::BasicFetch
62
- end
63
- end
64
-
65
- class NullFetch
66
- def initialize(opts)
67
- end
68
- def retrieve_work
69
- end
70
- def self.bulk_requeue(*args)
71
- end
72
- end
73
-
74
- it 'handles redis network errors' do
75
- begin
76
- Sidekiq.logger.level = Logger::FATAL
77
- Sidekiq.options[:fetch] = ErrorFetch
78
- mgr = Minitest::Mock.new
79
- fetch = Sidekiq::Fetcher.new(mgr, {})
80
- def fetch.pause
81
- end
82
- refute fetch.down
83
- fetch.fetch
84
- Sidekiq::Fetcher.done!
85
- assert fetch.down
86
- ensure
87
- Sidekiq.options[:fetch] = Sidekiq::BasicFetch
88
- Sidekiq.logger.level = Logger::ERROR
89
- end
90
- end
91
-
92
- class ErrorFetch
93
- def initialize(opts)
94
- end
95
- def retrieve_work
96
- raise IOError, "ker-BOOM"
97
- end
98
- def self.bulk_requeue(*args)
99
- end
100
- end
101
- end
102
-
103
48
  end
104
49
  end
@@ -0,0 +1,80 @@
1
+ require_relative 'helper'
2
+ require 'sidekiq/launcher'
3
+
4
+ class TestLauncher < Sidekiq::Test
5
+
6
+ describe 'launcher' do
7
+ before do
8
+ Sidekiq.redis {|c| c.flushdb }
9
+ end
10
+
11
+ def new_manager(opts)
12
+ Sidekiq::Manager.new(opts)
13
+ end
14
+
15
+ describe 'heartbeat' do
16
+ before do
17
+ uow = Object.new
18
+
19
+ @mgr = new_manager(options)
20
+ @launcher = Sidekiq::Launcher.new(options)
21
+ @launcher.manager = @mgr
22
+
23
+ Sidekiq::Processor::WORKER_STATE['a'] = {'b' => 1}
24
+
25
+ @proctitle = $0
26
+ end
27
+
28
+ after do
29
+ Sidekiq::Processor::WORKER_STATE.clear
30
+ $0 = @proctitle
31
+ end
32
+
33
+ describe 'when manager is active' do
34
+ before do
35
+ Sidekiq::CLI::PROCTITLES << proc { "xyz" }
36
+ @launcher.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
37
+ Sidekiq::CLI::PROCTITLES.pop
38
+ end
39
+
40
+ it 'sets useful info to proctitle' do
41
+ assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] xyz", $0
42
+ end
43
+
44
+ it 'stores process info in redis' do
45
+ info = Sidekiq.redis { |c| c.hmget('identity', 'busy') }
46
+ assert_equal ["1"], info
47
+ expires = Sidekiq.redis { |c| c.pttl('identity') }
48
+ assert_in_delta 60000, expires, 500
49
+ end
50
+ end
51
+
52
+ describe 'when manager is stopped' do
53
+ before do
54
+ @launcher.quiet
55
+ @launcher.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
56
+ end
57
+
58
+ it 'indicates stopping status in proctitle' do
59
+ assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] stopping", $0
60
+ end
61
+
62
+ it 'stores process info in redis' do
63
+ info = Sidekiq.redis { |c| c.hmget('identity', 'busy') }
64
+ assert_equal ["1"], info
65
+ expires = Sidekiq.redis { |c| c.pttl('identity') }
66
+ assert_in_delta 60000, expires, 50
67
+ end
68
+ end
69
+ end
70
+
71
+ def options
72
+ { :concurrency => 3, :queues => ['default'] }
73
+ end
74
+
75
+ def heartbeat_data
76
+ { 'concurrency' => 3, 'tag' => 'myapp' }
77
+ end
78
+ end
79
+
80
+ end
@@ -9,82 +9,31 @@ class TestManager < Sidekiq::Test
9
9
  end
10
10
 
11
11
  def new_manager(opts)
12
- condvar = Minitest::Mock.new
13
- condvar.expect(:signal, nil, [])
14
- Sidekiq::Manager.new(condvar, opts)
12
+ Sidekiq::Manager.new(opts)
15
13
  end
16
14
 
17
15
  it 'creates N processor instances' do
18
16
  mgr = new_manager(options)
19
- assert_equal options[:concurrency], mgr.ready.size
20
- assert_equal [], mgr.busy
21
- end
22
-
23
- it 'assigns work to a processor' do
24
- uow = Object.new
25
- processor = Minitest::Mock.new
26
- processor.expect(:async, processor, [])
27
- processor.expect(:process, nil, [uow])
28
-
29
- mgr = new_manager(options)
30
- mgr.ready << processor
31
- mgr.assign(uow)
32
- assert_equal 1, mgr.busy.size
33
-
34
- processor.verify
35
- end
36
-
37
- it 'requeues work if stopping' do
38
- uow = Minitest::Mock.new
39
- uow.expect(:requeue, nil, [])
40
-
41
- mgr = new_manager(options)
42
- mgr.fetcher = Sidekiq::BasicFetch.new({:queues => []})
43
- mgr.stop
44
- mgr.assign(uow)
45
- uow.verify
17
+ assert_equal options[:concurrency], mgr.workers.size
46
18
  end
47
19
 
48
20
  it 'shuts down the system' do
49
21
  mgr = new_manager(options)
50
- mgr.fetcher = Sidekiq::BasicFetch.new({:queues => []})
51
- mgr.stop
52
-
53
- assert mgr.busy.empty?
54
- assert mgr.ready.empty?
55
- end
56
-
57
- it 'returns finished processors to the ready pool' do
58
- fetcher = MiniTest::Mock.new
59
- fetcher.expect :async, fetcher, []
60
- fetcher.expect :fetch, nil, []
61
- mgr = new_manager(options)
62
- mgr.fetcher = fetcher
63
- init_size = mgr.ready.size
64
- processor = mgr.ready.pop
65
- mgr.busy << processor
66
- mgr.processor_done(processor)
67
-
68
- assert_equal 0, mgr.busy.size
69
- assert_equal init_size, mgr.ready.size
70
- fetcher.verify
22
+ mgr.stop(Time.now)
71
23
  end
72
24
 
73
25
  it 'throws away dead processors' do
74
- fetcher = MiniTest::Mock.new
75
- fetcher.expect :async, fetcher, []
76
- fetcher.expect :fetch, nil, []
77
26
  mgr = new_manager(options)
78
- mgr.fetcher = fetcher
79
- init_size = mgr.ready.size
80
- processor = mgr.ready.pop
81
- mgr.busy << processor
82
- mgr.processor_died(processor, 'ignored')
83
-
84
- assert_equal 0, mgr.busy.size
85
- assert_equal init_size, mgr.ready.size
86
- refute mgr.ready.include?(processor)
87
- fetcher.verify
27
+ init_size = mgr.workers.size
28
+ processor = mgr.workers.first
29
+ begin
30
+ mgr.processor_died(processor, 'ignored')
31
+
32
+ assert_equal init_size, mgr.workers.size
33
+ refute mgr.workers.include?(processor)
34
+ ensure
35
+ mgr.workers.each {|p| p.terminate(true) }
36
+ end
88
37
  end
89
38
 
90
39
  it 'does not support invalid concurrency' do
@@ -92,77 +41,9 @@ class TestManager < Sidekiq::Test
92
41
  assert_raises(ArgumentError) { new_manager(concurrency: -1) }
93
42
  end
94
43
 
95
- describe 'heartbeat' do
96
- before do
97
- uow = Object.new
98
-
99
- @processor = Minitest::Mock.new
100
- @processor.expect(:async, @processor, [])
101
- @processor.expect(:process, nil, [uow])
102
-
103
- @mgr = new_manager(options)
104
- @mgr.ready << @processor
105
- @mgr.assign(uow)
106
-
107
- @processor.verify
108
- @proctitle = $0
109
- end
110
-
111
- after do
112
- $0 = @proctitle
113
- end
114
-
115
- describe 'when manager is active' do
116
- before do
117
- Sidekiq::Manager::PROCTITLES << proc { "xyz" }
118
- @mgr.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
119
- Sidekiq::Manager::PROCTITLES.pop
120
- end
121
-
122
- it 'sets useful info to proctitle' do
123
- assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] xyz", $0
124
- end
125
-
126
- it 'stores process info in redis' do
127
- info = Sidekiq.redis { |c| c.hmget('identity', 'busy') }
128
- assert_equal ["1"], info
129
- expires = Sidekiq.redis { |c| c.pttl('identity') }
130
- assert_in_delta 60000, expires, 500
131
- end
132
- end
133
-
134
- describe 'when manager is stopped' do
135
- before do
136
- @processor.expect(:alive?, [])
137
- @processor.expect(:terminate, [])
138
-
139
- @mgr.stop
140
- @mgr.processor_done(@processor)
141
- @mgr.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
142
-
143
- @processor.verify
144
- end
145
-
146
- it 'indicates stopping status in proctitle' do
147
- assert_equal "sidekiq #{Sidekiq::VERSION} myapp [0 of 3 busy] stopping", $0
148
- end
149
-
150
- it 'stores process info in redis' do
151
- info = Sidekiq.redis { |c| c.hmget('identity', 'busy') }
152
- assert_equal ["0"], info
153
- expires = Sidekiq.redis { |c| c.pttl('identity') }
154
- assert_in_delta 60000, expires, 50
155
- end
156
- end
157
- end
158
-
159
44
  def options
160
45
  { :concurrency => 3, :queues => ['default'] }
161
46
  end
162
47
 
163
- def heartbeat_data
164
- { 'concurrency' => 3, 'tag' => 'myapp' }
165
- end
166
48
  end
167
-
168
49
  end
@@ -79,12 +79,10 @@ class TestMiddleware < Sidekiq::Test
79
79
  end
80
80
 
81
81
  boss = Minitest::Mock.new
82
+ boss.expect(:options, {:queues => ['default'] }, [])
83
+ boss.expect(:options, {:queues => ['default'] }, [])
82
84
  processor = Sidekiq::Processor.new(boss)
83
- actor = Minitest::Mock.new
84
- actor.expect(:processor_done, nil, [processor])
85
- actor.expect(:real_thread, nil, [nil, Thread])
86
- boss.expect(:async, actor, [])
87
- boss.expect(:async, actor, [])
85
+ boss.expect(:processor_done, nil, [processor])
88
86
  processor.process(Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg))
89
87
  assert_equal %w(2 before 3 before 1 before work_performed 1 after 3 after 2 after), $recorder.flatten
90
88
  end
@@ -1,15 +1,19 @@
1
1
  require_relative 'helper'
2
+ require 'sidekiq/fetch'
3
+ require 'sidekiq/cli'
2
4
  require 'sidekiq/processor'
3
5
 
4
6
  class TestProcessor < Sidekiq::Test
5
7
  TestException = Class.new(StandardError)
6
8
  TEST_EXCEPTION = TestException.new("kerboom!")
7
9
 
8
- describe 'with mock setup' do
10
+ describe 'processor' do
9
11
  before do
10
12
  $invokes = 0
11
- @boss = Minitest::Mock.new
12
- @processor = ::Sidekiq::Processor.new(@boss)
13
+ @mgr = Minitest::Mock.new
14
+ @mgr.expect(:options, {:queues => ['default']})
15
+ @mgr.expect(:options, {:queues => ['default']})
16
+ @processor = ::Sidekiq::Processor.new(@mgr)
13
17
  end
14
18
 
15
19
  class MockWorker
@@ -27,13 +31,7 @@ class TestProcessor < Sidekiq::Test
27
31
 
28
32
  it 'processes as expected' do
29
33
  msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
30
- actor = Minitest::Mock.new
31
- actor.expect(:processor_done, nil, [@processor])
32
- actor.expect(:real_thread, nil, [nil, Thread])
33
- @boss.expect(:async, actor, [])
34
- @boss.expect(:async, actor, [])
35
34
  @processor.process(work(msg))
36
- @boss.verify
37
35
  assert_equal 1, $invokes
38
36
  end
39
37
 
@@ -43,46 +41,26 @@ class TestProcessor < Sidekiq::Test
43
41
  @processor.execute_job(worker, [1, 2, 3])
44
42
  end
45
43
 
46
- it 'passes exceptions to ExceptionHandler' do
47
- actor = Minitest::Mock.new
48
- actor.expect(:real_thread, nil, [nil, Thread])
49
- @boss.expect(:async, actor, [])
50
- msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
51
- begin
52
- @processor.process(work(msg))
53
- flunk "Expected #process to raise exception"
54
- rescue TestException
55
- end
56
-
57
- assert_equal 0, $invokes
58
- end
59
-
60
44
  it 're-raises exceptions after handling' do
61
45
  msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
62
46
  re_raise = false
63
- actor = Minitest::Mock.new
64
- actor.expect(:real_thread, nil, [nil, Thread])
65
- @boss.expect(:async, actor, [])
66
47
 
67
48
  begin
68
49
  @processor.process(work(msg))
50
+ flunk "Expected exception"
69
51
  rescue TestException
70
52
  re_raise = true
71
53
  end
72
54
 
55
+ assert_equal 0, $invokes
73
56
  assert re_raise, "does not re-raise exceptions after handling"
74
57
  end
75
58
 
76
59
  it 'does not modify original arguments' do
77
60
  msg = { 'class' => MockWorker.to_s, 'args' => [['myarg']] }
78
61
  msgstr = Sidekiq.dump_json(msg)
79
- processor = ::Sidekiq::Processor.new(@boss)
80
- actor = Minitest::Mock.new
81
- actor.expect(:processor_done, nil, [processor])
82
- actor.expect(:real_thread, nil, [nil, Thread])
83
- @boss.expect(:async, actor, [])
84
- @boss.expect(:async, actor, [])
85
- processor.process(work(msgstr))
62
+ @mgr.expect(:processor_done, nil, [@processor])
63
+ @processor.process(work(msgstr))
86
64
  assert_equal [['myarg']], msg['args']
87
65
  end
88
66
 
@@ -106,17 +84,13 @@ class TestProcessor < Sidekiq::Test
106
84
  let(:skip_job) { false }
107
85
  let(:worker_args) { ['myarg'] }
108
86
  let(:work) { MiniTest::Mock.new }
109
- let(:actor) { Minitest::Mock.new }
110
87
 
111
88
  before do
112
- work.expect(:queue_name, 'queues:default')
113
- work.expect(:message, Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => worker_args }))
89
+ work.expect(:queue_name, 'queue:default')
90
+ work.expect(:job, Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => worker_args }))
114
91
  Sidekiq.server_middleware do |chain|
115
92
  chain.prepend ExceptionRaisingMiddleware, raise_before_yield, raise_after_yield, skip_job
116
93
  end
117
-
118
- actor.expect(:real_thread, nil, [nil, Thread])
119
- @boss.expect(:async, actor, [])
120
94
  end
121
95
 
122
96
  after do
@@ -156,8 +130,7 @@ class TestProcessor < Sidekiq::Test
156
130
 
157
131
  it 'acks the job' do
158
132
  work.expect(:acknowledge, nil)
159
- @boss.expect(:async, actor, [])
160
- actor.expect(:processor_done, nil, [@processor])
133
+ @mgr.expect(:processor_done, nil, [@processor])
161
134
  @processor.process(work)
162
135
  end
163
136
  end
@@ -178,8 +151,7 @@ class TestProcessor < Sidekiq::Test
178
151
  describe 'everything goes well' do
179
152
  it 'acks the job' do
180
153
  work.expect(:acknowledge, nil)
181
- @boss.expect(:async, actor, [])
182
- actor.expect(:processor_done, nil, [@processor])
154
+ @mgr.expect(:processor_done, nil, [@processor])
183
155
  @processor.process(work)
184
156
  end
185
157
  end
@@ -195,19 +167,14 @@ class TestProcessor < Sidekiq::Test
195
167
 
196
168
  def successful_job
197
169
  msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
198
- actor = Minitest::Mock.new
199
- actor.expect(:real_thread, nil, [nil, Thread])
200
- actor.expect(:processor_done, nil, [@processor])
201
- @boss.expect(:async, actor, [])
202
- @boss.expect(:async, actor, [])
170
+ @mgr.expect(:processor_done, nil, [@processor])
203
171
  @processor.process(work(msg))
204
172
  end
205
173
 
206
174
  it 'increments processed stat' do
207
- assert_equal 0, Sidekiq::Stats.new.processed
175
+ Sidekiq::Processor::PROCESSED.value = 0
208
176
  successful_job
209
- assert_equal 1, Sidekiq::Stats.new.processed
210
- assert_equal Sidekiq::Processor::STATS_TIMEOUT, Sidekiq.redis { |conn| conn.ttl(processed_today_key) }
177
+ assert_equal 1, Sidekiq::Processor::PROCESSED.value
211
178
  end
212
179
  end
213
180
 
@@ -215,9 +182,6 @@ class TestProcessor < Sidekiq::Test
215
182
  let(:failed_today_key) { "stat:failed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
216
183
 
217
184
  def failed_job
218
- actor = Minitest::Mock.new
219
- actor.expect(:real_thread, nil, [nil, Thread])
220
- @boss.expect(:async, actor, [])
221
185
  msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
222
186
  begin
223
187
  @processor.process(work(msg))
@@ -226,10 +190,9 @@ class TestProcessor < Sidekiq::Test
226
190
  end
227
191
 
228
192
  it 'increments failed stat' do
229
- assert_equal 0, Sidekiq::Stats.new.failed
193
+ Sidekiq::Processor::FAILURE.value = 0
230
194
  failed_job
231
- assert_equal 1, Sidekiq::Stats.new.failed
232
- assert_equal Sidekiq::Processor::STATS_TIMEOUT, Sidekiq.redis { |conn| conn.ttl(failed_today_key) }
195
+ assert_equal 1, Sidekiq::Processor::FAILURE.value
233
196
  end
234
197
  end
235
198
  end