sidekiq 3.4.1 → 4.0.0

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.

Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/4.0-Upgrade.md +50 -0
  3. data/COMM-LICENSE +55 -45
  4. data/Changes.md +73 -1
  5. data/Ent-Changes.md +66 -0
  6. data/Gemfile +7 -1
  7. data/Pro-2.0-Upgrade.md +2 -2
  8. data/Pro-3.0-Upgrade.md +46 -0
  9. data/Pro-Changes.md +65 -2
  10. data/README.md +8 -9
  11. data/bin/sidekiq +5 -0
  12. data/bin/sidekiqctl +8 -2
  13. data/bin/sidekiqload +167 -0
  14. data/lib/sidekiq/api.rb +29 -31
  15. data/lib/sidekiq/cli.rb +41 -42
  16. data/lib/sidekiq/client.rb +5 -10
  17. data/lib/sidekiq/fetch.rb +35 -111
  18. data/lib/sidekiq/launcher.rb +102 -42
  19. data/lib/sidekiq/manager.rb +78 -180
  20. data/lib/sidekiq/middleware/server/logging.rb +10 -5
  21. data/lib/sidekiq/middleware/server/retry_jobs.rb +5 -5
  22. data/lib/sidekiq/processor.rb +126 -97
  23. data/lib/sidekiq/redis_connection.rb +23 -5
  24. data/lib/sidekiq/scheduled.rb +47 -26
  25. data/lib/sidekiq/testing.rb +96 -17
  26. data/lib/sidekiq/util.rb +20 -0
  27. data/lib/sidekiq/version.rb +1 -1
  28. data/lib/sidekiq/web.rb +17 -1
  29. data/lib/sidekiq/web_helpers.rb +26 -4
  30. data/lib/sidekiq/worker.rb +14 -0
  31. data/lib/sidekiq.rb +37 -14
  32. data/sidekiq.gemspec +11 -11
  33. data/test/helper.rb +45 -10
  34. data/test/test_actors.rb +137 -0
  35. data/test/test_api.rb +388 -388
  36. data/test/test_cli.rb +29 -59
  37. data/test/test_client.rb +60 -135
  38. data/test/test_extensions.rb +29 -23
  39. data/test/test_fetch.rb +2 -57
  40. data/test/test_launcher.rb +80 -0
  41. data/test/test_logging.rb +1 -1
  42. data/test/test_manager.rb +16 -131
  43. data/test/test_middleware.rb +3 -5
  44. data/test/test_processor.rb +110 -76
  45. data/test/test_rails.rb +21 -0
  46. data/test/test_redis_connection.rb +0 -1
  47. data/test/test_retry.rb +114 -162
  48. data/test/test_scheduled.rb +11 -17
  49. data/test/test_scheduling.rb +20 -42
  50. data/test/test_sidekiq.rb +46 -16
  51. data/test/test_testing.rb +80 -20
  52. data/test/test_testing_fake.rb +68 -8
  53. data/test/test_testing_inline.rb +3 -3
  54. data/test/test_util.rb +16 -0
  55. data/test/test_web.rb +17 -3
  56. data/test/test_web_helpers.rb +3 -2
  57. data/web/assets/images/favicon.ico +0 -0
  58. data/web/assets/javascripts/application.js +6 -1
  59. data/web/assets/javascripts/dashboard.js +2 -8
  60. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +14 -14
  61. data/web/assets/stylesheets/application.css +33 -56
  62. data/web/locales/de.yml +1 -1
  63. data/web/locales/en.yml +1 -0
  64. data/web/locales/{no.yml → nb.yml} +10 -2
  65. data/web/locales/uk.yml +76 -0
  66. data/web/views/_footer.erb +2 -7
  67. data/web/views/_job_info.erb +1 -1
  68. data/web/views/_nav.erb +2 -2
  69. data/web/views/_poll_js.erb +5 -0
  70. data/web/views/{_poll.erb → _poll_link.erb} +0 -3
  71. data/web/views/busy.erb +2 -1
  72. data/web/views/dead.erb +1 -0
  73. data/web/views/layout.erb +2 -0
  74. data/web/views/morgue.erb +3 -0
  75. data/web/views/queue.erb +1 -0
  76. data/web/views/queues.erb +1 -0
  77. data/web/views/retries.erb +3 -0
  78. data/web/views/retry.erb +1 -0
  79. data/web/views/scheduled.erb +1 -0
  80. data/web/views/scheduled_job_info.erb +1 -0
  81. metadata +81 -47
  82. data/lib/sidekiq/actor.rb +0 -39
  83. data/test/test_worker_generator.rb +0 -17
data/test/test_api.rb CHANGED
@@ -1,493 +1,493 @@
1
1
  require_relative 'helper'
2
+ require 'sidekiq/api'
2
3
 
3
4
  class TestApi < Sidekiq::Test
4
-
5
- describe "stats" do
5
+ describe 'api' do
6
6
  before do
7
- Sidekiq.redis = REDIS
8
7
  Sidekiq.redis {|c| c.flushdb }
9
8
  end
10
9
 
11
- describe "processed" do
10
+ describe "stats" do
12
11
  it "is initially zero" do
13
12
  s = Sidekiq::Stats.new
14
13
  assert_equal 0, s.processed
14
+ assert_equal 0, s.failed
15
+ assert_equal 0, s.enqueued
15
16
  end
16
17
 
17
- it "returns number of processed jobs" do
18
- Sidekiq.redis { |conn| conn.set("stat:processed", 5) }
19
- s = Sidekiq::Stats.new
20
- assert_equal 5, s.processed
18
+ describe "processed" do
19
+ it "returns number of processed jobs" do
20
+ Sidekiq.redis { |conn| conn.set("stat:processed", 5) }
21
+ s = Sidekiq::Stats.new
22
+ assert_equal 5, s.processed
23
+ end
21
24
  end
22
- end
23
25
 
24
- describe "failed" do
25
- it "is initially zero" do
26
- s = Sidekiq::Stats.new
27
- assert_equal 0, s.failed
26
+ describe "failed" do
27
+ it "returns number of failed jobs" do
28
+ Sidekiq.redis { |conn| conn.set("stat:failed", 5) }
29
+ s = Sidekiq::Stats.new
30
+ assert_equal 5, s.failed
31
+ end
28
32
  end
29
33
 
30
- it "returns number of failed jobs" do
31
- Sidekiq.redis { |conn| conn.set("stat:failed", 5) }
32
- s = Sidekiq::Stats.new
33
- assert_equal 5, s.failed
34
- end
35
- end
34
+ describe "reset" do
35
+ before do
36
+ Sidekiq.redis do |conn|
37
+ conn.set('stat:processed', 5)
38
+ conn.set('stat:failed', 10)
39
+ end
40
+ end
36
41
 
37
- describe "reset" do
38
- before do
39
- Sidekiq.redis do |conn|
40
- conn.set('stat:processed', 5)
41
- conn.set('stat:failed', 10)
42
+ it 'will reset all stats by default' do
43
+ Sidekiq::Stats.new.reset
44
+ s = Sidekiq::Stats.new
45
+ assert_equal 0, s.failed
46
+ assert_equal 0, s.processed
42
47
  end
43
- end
44
48
 
45
- it 'will reset all stats by default' do
46
- Sidekiq::Stats.new.reset
47
- Sidekiq.redis do |conn|
48
- assert_equal '0', conn.get('stat:processed')
49
- assert_equal '0', conn.get('stat:failed')
49
+ it 'can reset individual stats' do
50
+ Sidekiq::Stats.new.reset('failed')
51
+ s = Sidekiq::Stats.new
52
+ assert_equal 0, s.failed
53
+ assert_equal 5, s.processed
50
54
  end
51
- end
52
55
 
53
- it 'can reset individual stats' do
54
- Sidekiq::Stats.new.reset('failed')
55
- Sidekiq.redis do |conn|
56
- assert_equal '5', conn.get('stat:processed')
57
- assert_equal '0', conn.get('stat:failed')
56
+ it 'can accept anything that responds to #to_s' do
57
+ Sidekiq::Stats.new.reset(:failed)
58
+ s = Sidekiq::Stats.new
59
+ assert_equal 0, s.failed
60
+ assert_equal 5, s.processed
58
61
  end
59
- end
60
62
 
61
- it 'can accept anything that responds to #to_s' do
62
- Sidekiq::Stats.new.reset(:failed)
63
- Sidekiq.redis do |conn|
64
- assert_equal '5', conn.get('stat:processed')
65
- assert_equal '0', conn.get('stat:failed')
63
+ it 'ignores anything other than "failed" or "processed"' do
64
+ Sidekiq::Stats.new.reset((1..10).to_a, ['failed'])
65
+ s = Sidekiq::Stats.new
66
+ assert_equal 0, s.failed
67
+ assert_equal 5, s.processed
66
68
  end
67
69
  end
68
70
 
69
- it 'ignores anything other than "failed" or "processed"' do
70
- Sidekiq::Stats.new.reset((1..10).to_a, ['failed'])
71
- Sidekiq.redis do |conn|
72
- assert_equal '5', conn.get('stat:processed')
73
- assert_equal '0', conn.get('stat:failed')
71
+ describe "queues" do
72
+ it "is initially empty" do
73
+ s = Sidekiq::Stats::Queues.new
74
+ assert_equal 0, s.lengths.size
74
75
  end
75
- end
76
- end
77
76
 
78
- describe "queues" do
79
- it "returns all queues" do
80
- assert_equal Sidekiq::Stats.new.queues, Sidekiq::Stats::Queues.new.lengths
81
- end
77
+ it "returns a hash of queue and size in order" do
78
+ Sidekiq.redis do |conn|
79
+ conn.rpush 'queue:foo', '{}'
80
+ conn.sadd 'queues', 'foo'
82
81
 
83
- it "is initially empty" do
84
- s = Sidekiq::Stats::Queues.new
85
- assert_equal 0, s.lengths.size
86
- end
82
+ 3.times { conn.rpush 'queue:bar', '{}' }
83
+ conn.sadd 'queues', 'bar'
84
+ end
87
85
 
88
- it "returns a hash of queue and size in order" do
89
- Sidekiq.redis do |conn|
90
- conn.rpush 'queue:foo', '{}'
91
- conn.sadd 'queues', 'foo'
86
+ s = Sidekiq::Stats::Queues.new
87
+ assert_equal ({ "foo" => 1, "bar" => 3 }), s.lengths
88
+ assert_equal "bar", s.lengths.first.first
92
89
 
93
- 3.times { conn.rpush 'queue:bar', '{}' }
94
- conn.sadd 'queues', 'bar'
90
+ assert_equal Sidekiq::Stats.new.queues, Sidekiq::Stats::Queues.new.lengths
95
91
  end
96
-
97
- s = Sidekiq::Stats::Queues.new
98
- assert_equal ({ "foo" => 1, "bar" => 3 }), s.lengths
99
- assert_equal "bar", s.lengths.first.first
100
92
  end
101
- end
102
93
 
103
- describe "enqueued" do
104
- it "is initially empty" do
105
- s = Sidekiq::Stats.new
106
- assert_equal 0, s.enqueued
107
- end
94
+ describe "enqueued" do
95
+ it "returns total enqueued jobs" do
96
+ Sidekiq.redis do |conn|
97
+ conn.rpush 'queue:foo', '{}'
98
+ conn.sadd 'queues', 'foo'
108
99
 
109
- it "returns total enqueued jobs" do
110
- Sidekiq.redis do |conn|
111
- conn.rpush 'queue:foo', '{}'
112
- conn.sadd 'queues', 'foo'
100
+ 3.times { conn.rpush 'queue:bar', '{}' }
101
+ conn.sadd 'queues', 'bar'
102
+ end
113
103
 
114
- 3.times { conn.rpush 'queue:bar', '{}' }
115
- conn.sadd 'queues', 'bar'
104
+ s = Sidekiq::Stats.new
105
+ assert_equal 4, s.enqueued
116
106
  end
117
-
118
- s = Sidekiq::Stats.new
119
- assert_equal 4, s.enqueued
120
107
  end
121
- end
122
108
 
123
- describe "over time" do
124
- describe "processed" do
125
- it 'retrieves hash of dates' do
126
- Sidekiq.redis do |c|
127
- c.incrby("stat:processed:2012-12-24", 4)
128
- c.incrby("stat:processed:2012-12-25", 1)
129
- c.incrby("stat:processed:2012-12-26", 6)
130
- c.incrby("stat:processed:2012-12-27", 2)
131
- end
132
- Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
133
- s = Sidekiq::Stats::History.new(2)
134
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1 }), s.processed
135
-
136
- s = Sidekiq::Stats::History.new(3)
137
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }), s.processed
109
+ describe "over time" do
110
+ before do
111
+ require 'active_support/core_ext/time/conversions'
112
+ @before = Time::DATE_FORMATS[:default]
113
+ Time::DATE_FORMATS[:default] = "%d/%m/%Y %H:%M:%S"
114
+ end
138
115
 
139
- s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
140
- assert_equal ({ "2012-12-25" => 1, "2012-12-24" => 4 }), s.processed
141
- end
116
+ after do
117
+ Time::DATE_FORMATS[:default] = @before
142
118
  end
143
- end
144
119
 
145
- describe "failed" do
146
- it 'retrieves hash of dates' do
147
- Sidekiq.redis do |c|
148
- c.incrby("stat:failed:2012-12-24", 4)
149
- c.incrby("stat:failed:2012-12-25", 1)
150
- c.incrby("stat:failed:2012-12-26", 6)
151
- c.incrby("stat:failed:2012-12-27", 2)
120
+ describe "processed" do
121
+ it 'retrieves hash of dates' do
122
+ Sidekiq.redis do |c|
123
+ c.incrby("stat:processed:2012-12-24", 4)
124
+ c.incrby("stat:processed:2012-12-25", 1)
125
+ c.incrby("stat:processed:2012-12-26", 6)
126
+ c.incrby("stat:processed:2012-12-27", 2)
127
+ end
128
+ Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
129
+ s = Sidekiq::Stats::History.new(2)
130
+ assert_equal({ "2012-12-26" => 6, "2012-12-25" => 1 }, s.processed)
131
+
132
+ s = Sidekiq::Stats::History.new(3)
133
+ assert_equal({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }, s.processed)
134
+
135
+ s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
136
+ assert_equal({ "2012-12-25" => 1, "2012-12-24" => 4 }, s.processed)
137
+ end
152
138
  end
153
- Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
154
- s = Sidekiq::Stats::History.new(2)
155
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1 }), s.failed
156
-
157
- s = Sidekiq::Stats::History.new(3)
158
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
139
+ end
159
140
 
160
- s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
161
- assert_equal ({ "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
141
+ describe "failed" do
142
+ it 'retrieves hash of dates' do
143
+ Sidekiq.redis do |c|
144
+ c.incrby("stat:failed:2012-12-24", 4)
145
+ c.incrby("stat:failed:2012-12-25", 1)
146
+ c.incrby("stat:failed:2012-12-26", 6)
147
+ c.incrby("stat:failed:2012-12-27", 2)
148
+ end
149
+ Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
150
+ s = Sidekiq::Stats::History.new(2)
151
+ assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1 }), s.failed
152
+
153
+ s = Sidekiq::Stats::History.new(3)
154
+ assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
155
+
156
+ s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
157
+ assert_equal ({ "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
158
+ end
162
159
  end
163
160
  end
164
161
  end
165
162
  end
166
- end
167
-
168
- describe 'with an empty database' do
169
- include Sidekiq::Util
170
-
171
- before do
172
- Sidekiq.redis = REDIS
173
- Sidekiq.redis {|c| c.flushdb }
174
- end
175
-
176
- it 'shows queue as empty' do
177
- q = Sidekiq::Queue.new
178
- assert_equal 0, q.size
179
- assert_equal 0, q.latency
180
- end
181
-
182
- class ApiWorker
183
- include Sidekiq::Worker
184
- end
185
-
186
- it 'can enumerate jobs' do
187
- q = Sidekiq::Queue.new
188
- Time.stub(:now, Time.new(2012, 12, 26)) do
189
- ApiWorker.perform_async(1, 'mike')
190
- assert_equal ['TestApi::ApiWorker'], q.map(&:klass)
191
163
 
192
- job = q.first
193
- assert_equal 24, job.jid.size
194
- assert_equal [1, 'mike'], job.args
195
- assert_equal Time.new(2012, 12, 26), job.enqueued_at
164
+ describe 'with an empty database' do
165
+ it 'shows queue as empty' do
166
+ q = Sidekiq::Queue.new
167
+ assert_equal 0, q.size
168
+ assert_equal 0, q.latency
196
169
  end
197
170
 
198
- assert q.latency > 10_000_000
171
+ class ApiWorker
172
+ include Sidekiq::Worker
173
+ end
199
174
 
200
- q = Sidekiq::Queue.new('other')
201
- assert_equal 0, q.size
202
- end
175
+ it 'can enumerate jobs' do
176
+ q = Sidekiq::Queue.new
177
+ Time.stub(:now, Time.new(2012, 12, 26)) do
178
+ ApiWorker.perform_async(1, 'mike')
179
+ assert_equal ['TestApi::ApiWorker'], q.map(&:klass)
203
180
 
204
- it 'unwraps delayed jobs' do
205
- ApiWorker.delay.foo(1,2,3)
206
- q = Sidekiq::Queue.new
207
- x = q.first
208
- assert_equal "TestApi::ApiWorker.foo", x.display_class
209
- assert_equal [1,2,3], x.display_args
210
- end
181
+ job = q.first
182
+ assert_equal 24, job.jid.size
183
+ assert_equal [1, 'mike'], job.args
184
+ assert_equal Time.new(2012, 12, 26), job.enqueued_at
185
+ end
186
+ assert q.latency > 10_000_000
211
187
 
212
- it 'can delete jobs' do
213
- q = Sidekiq::Queue.new
214
- ApiWorker.perform_async(1, 'mike')
215
- assert_equal 1, q.size
188
+ q = Sidekiq::Queue.new('other')
189
+ assert_equal 0, q.size
190
+ end
216
191
 
217
- x = q.first
218
- assert_equal "TestApi::ApiWorker", x.display_class
219
- assert_equal [1,'mike'], x.display_args
192
+ it 'has no enqueued_at time for jobs enqueued in the future' do
193
+ job_id = ApiWorker.perform_in(100, 1, 'foo')
194
+ job = Sidekiq::ScheduledSet.new.find_job(job_id)
195
+ assert_nil job.enqueued_at
196
+ end
220
197
 
221
- assert_equal [true], q.map(&:delete)
222
- assert_equal 0, q.size
223
- end
198
+ it 'unwraps delayed jobs' do
199
+ Sidekiq::Queue.delay.foo(1,2,3)
200
+ q = Sidekiq::Queue.new
201
+ x = q.first
202
+ assert_equal "Sidekiq::Queue.foo", x.display_class
203
+ assert_equal [1,2,3], x.display_args
204
+ end
224
205
 
225
- it "can move scheduled job to queue" do
226
- remain_id = ApiWorker.perform_in(100, 1, 'jason')
227
- job_id = ApiWorker.perform_in(100, 1, 'jason')
228
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
229
- q = Sidekiq::Queue.new
230
- job.add_to_queue
231
- queued_job = q.find_job(job_id)
232
- refute_nil queued_job
233
- assert_equal queued_job.jid, job_id
234
- assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
235
- refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
236
- end
206
+ it 'has no enqueued_at time for jobs enqueued in the future' do
207
+ job_id = ApiWorker.perform_in(100, 1, 'foo')
208
+ job = Sidekiq::ScheduledSet.new.find_job(job_id)
209
+ assert_nil job.enqueued_at
210
+ end
237
211
 
238
- it "handles multiple scheduled jobs when moving to queue" do
239
- jids = Sidekiq::Client.push_bulk('class' => ApiWorker,
240
- 'args' => [[1, 'jason'], [2, 'jason']],
241
- 'at' => Time.now.to_f)
242
- assert_equal 2, jids.size
243
- (remain_id, job_id) = jids
244
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
245
- q = Sidekiq::Queue.new
246
- job.add_to_queue
247
- queued_job = q.find_job(job_id)
248
- refute_nil queued_job
249
- assert_equal queued_job.jid, job_id
250
- assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
251
- refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
252
- end
212
+ it 'can delete jobs' do
213
+ q = Sidekiq::Queue.new
214
+ ApiWorker.perform_async(1, 'mike')
215
+ assert_equal 1, q.size
253
216
 
254
- it 'can find job by id in sorted sets' do
255
- job_id = ApiWorker.perform_in(100, 1, 'jason')
256
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
257
- refute_nil job
258
- assert_equal job_id, job.jid
259
- assert_in_delta job.latency, 0.0, 0.1
260
- end
217
+ x = q.first
218
+ assert_equal "TestApi::ApiWorker", x.display_class
219
+ assert_equal [1,'mike'], x.display_args
261
220
 
262
- it 'can remove jobs when iterating over a sorted set' do
263
- # scheduled jobs must be greater than SortedSet#each underlying page size
264
- 51.times do
265
- ApiWorker.perform_in(100, 'aaron')
221
+ assert_equal [true], q.map(&:delete)
222
+ assert_equal 0, q.size
266
223
  end
267
- set = Sidekiq::ScheduledSet.new
268
- set.map(&:delete)
269
- assert_equal set.size, 0
270
- end
271
224
 
272
- it 'can remove jobs when iterating over a queue' do
273
- # initial queue size must be greater than Queue#each underlying page size
274
- 51.times do
275
- ApiWorker.perform_async(1, 'aaron')
225
+ it "can move scheduled job to queue" do
226
+ remain_id = ApiWorker.perform_in(100, 1, 'jason')
227
+ job_id = ApiWorker.perform_in(100, 1, 'jason')
228
+ job = Sidekiq::ScheduledSet.new.find_job(job_id)
229
+ q = Sidekiq::Queue.new
230
+ job.add_to_queue
231
+ queued_job = q.find_job(job_id)
232
+ refute_nil queued_job
233
+ assert_equal queued_job.jid, job_id
234
+ assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
235
+ refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
276
236
  end
277
- q = Sidekiq::Queue.new
278
- q.map(&:delete)
279
- assert_equal q.size, 0
280
- end
281
237
 
282
- it 'can find job by id in queues' do
283
- q = Sidekiq::Queue.new
284
- job_id = ApiWorker.perform_async(1, 'jason')
285
- job = q.find_job(job_id)
286
- refute_nil job
287
- assert_equal job_id, job.jid
288
- end
238
+ it "handles multiple scheduled jobs when moving to queue" do
239
+ jids = Sidekiq::Client.push_bulk('class' => ApiWorker,
240
+ 'args' => [[1, 'jason'], [2, 'jason']],
241
+ 'at' => Time.now.to_f)
242
+ assert_equal 2, jids.size
243
+ (remain_id, job_id) = jids
244
+ job = Sidekiq::ScheduledSet.new.find_job(job_id)
245
+ q = Sidekiq::Queue.new
246
+ job.add_to_queue
247
+ queued_job = q.find_job(job_id)
248
+ refute_nil queued_job
249
+ assert_equal queued_job.jid, job_id
250
+ assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
251
+ refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
252
+ end
289
253
 
290
- it 'can clear a queue' do
291
- q = Sidekiq::Queue.new
292
- 2.times { ApiWorker.perform_async(1, 'mike') }
293
- q.clear
254
+ it 'can find job by id in sorted sets' do
255
+ job_id = ApiWorker.perform_in(100, 1, 'jason')
256
+ job = Sidekiq::ScheduledSet.new.find_job(job_id)
257
+ refute_nil job
258
+ assert_equal job_id, job.jid
259
+ assert_in_delta job.latency, 0.0, 0.1
260
+ end
294
261
 
295
- Sidekiq.redis do |conn|
296
- refute conn.smembers('queues').include?('foo')
297
- refute conn.exists('queue:foo')
262
+ it 'can remove jobs when iterating over a sorted set' do
263
+ # scheduled jobs must be greater than SortedSet#each underlying page size
264
+ 51.times do
265
+ ApiWorker.perform_in(100, 'aaron')
266
+ end
267
+ set = Sidekiq::ScheduledSet.new
268
+ set.map(&:delete)
269
+ assert_equal set.size, 0
298
270
  end
299
- end
300
271
 
301
- it 'can fetch by score' do
302
- same_time = Time.now.to_f
303
- add_retry('bob1', same_time)
304
- add_retry('bob2', same_time)
305
- r = Sidekiq::RetrySet.new
306
- assert_equal 2, r.fetch(same_time).size
307
- end
272
+ it 'can remove jobs when iterating over a queue' do
273
+ # initial queue size must be greater than Queue#each underlying page size
274
+ 51.times do
275
+ ApiWorker.perform_async(1, 'aaron')
276
+ end
277
+ q = Sidekiq::Queue.new
278
+ q.map(&:delete)
279
+ assert_equal q.size, 0
280
+ end
308
281
 
309
- it 'can fetch by score and jid' do
310
- same_time = Time.now.to_f
311
- add_retry('bob1', same_time)
312
- add_retry('bob2', same_time)
313
- r = Sidekiq::RetrySet.new
314
- assert_equal 1, r.fetch(same_time, 'bob1').size
315
- end
282
+ it 'can find job by id in queues' do
283
+ q = Sidekiq::Queue.new
284
+ job_id = ApiWorker.perform_async(1, 'jason')
285
+ job = q.find_job(job_id)
286
+ refute_nil job
287
+ assert_equal job_id, job.jid
288
+ end
316
289
 
317
- it 'shows empty retries' do
318
- r = Sidekiq::RetrySet.new
319
- assert_equal 0, r.size
320
- end
290
+ it 'can clear a queue' do
291
+ q = Sidekiq::Queue.new
292
+ 2.times { ApiWorker.perform_async(1, 'mike') }
293
+ q.clear
321
294
 
322
- it 'can enumerate retries' do
323
- add_retry
295
+ Sidekiq.redis do |conn|
296
+ refute conn.smembers('queues').include?('foo')
297
+ refute conn.exists('queue:foo')
298
+ end
299
+ end
324
300
 
325
- r = Sidekiq::RetrySet.new
326
- assert_equal 1, r.size
327
- array = r.to_a
328
- assert_equal 1, array.size
301
+ it 'can fetch by score' do
302
+ same_time = Time.now.to_f
303
+ add_retry('bob1', same_time)
304
+ add_retry('bob2', same_time)
305
+ r = Sidekiq::RetrySet.new
306
+ assert_equal 2, r.fetch(same_time).size
307
+ end
329
308
 
330
- retri = array.first
331
- assert_equal 'ApiWorker', retri.klass
332
- assert_equal 'default', retri.queue
333
- assert_equal 'bob', retri.jid
334
- assert_in_delta Time.now.to_f, retri.at.to_f, 0.02
335
- end
309
+ it 'can fetch by score and jid' do
310
+ same_time = Time.now.to_f
311
+ add_retry('bob1', same_time)
312
+ add_retry('bob2', same_time)
313
+ r = Sidekiq::RetrySet.new
314
+ assert_equal 1, r.fetch(same_time, 'bob1').size
315
+ end
336
316
 
337
- it 'can delete multiple retries from score' do
338
- same_time = Time.now.to_f
339
- add_retry('bob1', same_time)
340
- add_retry('bob2', same_time)
341
- r = Sidekiq::RetrySet.new
342
- assert_equal 2, r.size
343
- Sidekiq::RetrySet.new.delete(same_time)
344
- assert_equal 0, r.size
345
- end
317
+ it 'shows empty retries' do
318
+ r = Sidekiq::RetrySet.new
319
+ assert_equal 0, r.size
320
+ end
346
321
 
347
- it 'can delete a single retry from score and jid' do
348
- same_time = Time.now.to_f
349
- add_retry('bob1', same_time)
350
- add_retry('bob2', same_time)
351
- r = Sidekiq::RetrySet.new
352
- assert_equal 2, r.size
353
- Sidekiq::RetrySet.new.delete(same_time, 'bob1')
354
- assert_equal 1, r.size
355
- end
322
+ it 'can enumerate retries' do
323
+ add_retry
356
324
 
357
- it 'can retry a retry' do
358
- add_retry
359
- r = Sidekiq::RetrySet.new
360
- assert_equal 1, r.size
361
- r.first.retry
362
- assert_equal 0, r.size
363
- assert_equal 1, Sidekiq::Queue.new('default').size
364
- job = Sidekiq::Queue.new('default').first
365
- assert_equal 'bob', job.jid
366
- assert_equal 1, job['retry_count']
367
- end
325
+ r = Sidekiq::RetrySet.new
326
+ assert_equal 1, r.size
327
+ array = r.to_a
328
+ assert_equal 1, array.size
368
329
 
369
- it 'can clear retries' do
370
- add_retry
371
- add_retry('test')
372
- r = Sidekiq::RetrySet.new
373
- assert_equal 2, r.size
374
- r.clear
375
- assert_equal 0, r.size
376
- end
330
+ retri = array.first
331
+ assert_equal 'ApiWorker', retri.klass
332
+ assert_equal 'default', retri.queue
333
+ assert_equal 'bob', retri.jid
334
+ assert_in_delta Time.now.to_f, retri.at.to_f, 0.02
335
+ end
377
336
 
378
- it 'can enumerate processes' do
379
- identity_string = "identity_string"
380
- odata = {
381
- 'pid' => 123,
382
- 'hostname' => hostname,
383
- 'key' => identity_string,
384
- 'identity' => identity_string,
385
- 'started_at' => Time.now.to_f - 15,
386
- }
387
-
388
- time = Time.now.to_f
389
- Sidekiq.redis do |conn|
390
- conn.multi do
391
- conn.sadd('processes', odata['key'])
392
- conn.hmset(odata['key'], 'info', Sidekiq.dump_json(odata), 'busy', 10, 'beat', time)
393
- conn.sadd('processes', 'fake:pid')
337
+ it 'requires a jid to delete an entry' do
338
+ start_time = Time.now.to_f
339
+ add_retry('bob2', Time.now.to_f)
340
+ assert_raises(ArgumentError) do
341
+ Sidekiq::RetrySet.new.delete(start_time)
394
342
  end
395
343
  end
396
344
 
397
- ps = Sidekiq::ProcessSet.new.to_a
398
- assert_equal 1, ps.size
399
- data = ps.first
400
- assert_equal 10, data['busy']
401
- assert_equal time, data['beat']
402
- assert_equal 123, data['pid']
403
- data.quiet!
404
- data.stop!
405
- signals_string = "#{odata['key']}-signals"
406
- assert_equal "TERM", Sidekiq.redis{|c| c.lpop(signals_string) }
407
- assert_equal "USR1", Sidekiq.redis{|c| c.lpop(signals_string) }
408
- end
409
-
410
- it 'can enumerate workers' do
411
- w = Sidekiq::Workers.new
412
- assert_equal 0, w.size
413
- w.each do
414
- assert false
345
+ it 'can delete a single retry from score and jid' do
346
+ same_time = Time.now.to_f
347
+ add_retry('bob1', same_time)
348
+ add_retry('bob2', same_time)
349
+ r = Sidekiq::RetrySet.new
350
+ assert_equal 2, r.size
351
+ Sidekiq::RetrySet.new.delete(same_time, 'bob1')
352
+ assert_equal 1, r.size
415
353
  end
416
354
 
417
- key = "#{hostname}:#{$$}"
418
- pdata = { 'pid' => $$, 'hostname' => hostname, 'started_at' => Time.now.to_i }
419
- Sidekiq.redis do |conn|
420
- conn.sadd('processes', key)
421
- conn.hmset(key, 'info', Sidekiq.dump_json(pdata), 'busy', 0, 'beat', Time.now.to_f)
355
+ it 'can retry a retry' do
356
+ add_retry
357
+ r = Sidekiq::RetrySet.new
358
+ assert_equal 1, r.size
359
+ r.first.retry
360
+ assert_equal 0, r.size
361
+ assert_equal 1, Sidekiq::Queue.new('default').size
362
+ job = Sidekiq::Queue.new('default').first
363
+ assert_equal 'bob', job.jid
364
+ assert_equal 1, job['retry_count']
422
365
  end
423
366
 
424
- s = "#{key}:workers"
425
- data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => Time.now.to_i })
426
- Sidekiq.redis do |c|
427
- c.hmset(s, '1234', data)
367
+ it 'can clear retries' do
368
+ add_retry
369
+ add_retry('test')
370
+ r = Sidekiq::RetrySet.new
371
+ assert_equal 2, r.size
372
+ r.clear
373
+ assert_equal 0, r.size
428
374
  end
429
375
 
430
- w.each do |p, x, y|
431
- assert_equal key, p
432
- assert_equal "1234", x
433
- assert_equal 'default', y['queue']
434
- assert_equal Time.now.year, Time.at(y['run_at']).year
376
+ it 'can enumerate processes' do
377
+ identity_string = "identity_string"
378
+ odata = {
379
+ 'pid' => 123,
380
+ 'hostname' => Socket.gethostname,
381
+ 'key' => identity_string,
382
+ 'identity' => identity_string,
383
+ 'started_at' => Time.now.to_f - 15,
384
+ }
385
+
386
+ time = Time.now.to_f
387
+ Sidekiq.redis do |conn|
388
+ conn.multi do
389
+ conn.sadd('processes', odata['key'])
390
+ conn.hmset(odata['key'], 'info', Sidekiq.dump_json(odata), 'busy', 10, 'beat', time)
391
+ conn.sadd('processes', 'fake:pid')
392
+ end
393
+ end
394
+
395
+ ps = Sidekiq::ProcessSet.new.to_a
396
+ assert_equal 1, ps.size
397
+ data = ps.first
398
+ assert_equal 10, data['busy']
399
+ assert_equal time, data['beat']
400
+ assert_equal 123, data['pid']
401
+ data.quiet!
402
+ data.stop!
403
+ signals_string = "#{odata['key']}-signals"
404
+ assert_equal "TERM", Sidekiq.redis{|c| c.lpop(signals_string) }
405
+ assert_equal "USR1", Sidekiq.redis{|c| c.lpop(signals_string) }
435
406
  end
436
407
 
437
- s = "#{key}:workers"
438
- data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => (Time.now.to_i - 2*60*60) })
439
- Sidekiq.redis do |c|
440
- c.multi do
441
- c.hmset(s, '5678', data)
442
- c.hmset("b#{s}", '5678', data)
408
+ it 'can enumerate workers' do
409
+ w = Sidekiq::Workers.new
410
+ assert_equal 0, w.size
411
+ w.each do
412
+ assert false
443
413
  end
444
- end
445
414
 
446
- assert_equal ['1234', '5678'], w.map { |_, tid, _| tid }
447
- end
415
+ hn = Socket.gethostname
416
+ key = "#{hn}:#{$$}"
417
+ pdata = { 'pid' => $$, 'hostname' => hn, 'started_at' => Time.now.to_i }
418
+ Sidekiq.redis do |conn|
419
+ conn.sadd('processes', key)
420
+ conn.hmset(key, 'info', Sidekiq.dump_json(pdata), 'busy', 0, 'beat', Time.now.to_f)
421
+ end
422
+
423
+ s = "#{key}:workers"
424
+ data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => Time.now.to_i })
425
+ Sidekiq.redis do |c|
426
+ c.hmset(s, '1234', data)
427
+ end
448
428
 
449
- it 'can reschedule jobs' do
450
- add_retry('foo1')
451
- add_retry('foo2')
429
+ w.each do |p, x, y|
430
+ assert_equal key, p
431
+ assert_equal "1234", x
432
+ assert_equal 'default', y['queue']
433
+ assert_equal Time.now.year, Time.at(y['run_at']).year
434
+ end
452
435
 
453
- retries = Sidekiq::RetrySet.new
454
- assert_equal 2, retries.size
455
- refute(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
436
+ s = "#{key}:workers"
437
+ data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => (Time.now.to_i - 2*60*60) })
438
+ Sidekiq.redis do |c|
439
+ c.multi do
440
+ c.hmset(s, '5678', data)
441
+ c.hmset("b#{s}", '5678', data)
442
+ end
443
+ end
456
444
 
457
- retries.each do |retri|
458
- retri.reschedule(Time.now.to_f + 10) if retri.jid == 'foo2'
445
+ assert_equal ['1234', '5678'], w.map { |_, tid, _| tid }
459
446
  end
460
447
 
461
- assert_equal 2, retries.size
462
- assert(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
463
- end
448
+ it 'can reschedule jobs' do
449
+ add_retry('foo1')
450
+ add_retry('foo2')
464
451
 
465
- it 'prunes processes which have died' do
466
- data = { 'pid' => rand(10_000), 'hostname' => "app#{rand(1_000)}", 'started_at' => Time.now.to_f }
467
- key = "#{data['hostname']}:#{data['pid']}"
468
- Sidekiq.redis do |conn|
469
- conn.sadd('processes', key)
470
- conn.hmset(key, 'info', Sidekiq.dump_json(data), 'busy', 0, 'beat', Time.now.to_f)
471
- end
452
+ retries = Sidekiq::RetrySet.new
453
+ assert_equal 2, retries.size
454
+ refute(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
472
455
 
473
- ps = Sidekiq::ProcessSet.new
474
- assert_equal 1, ps.size
475
- assert_equal 1, ps.to_a.size
456
+ retries.each do |retri|
457
+ retri.reschedule(Time.now.to_f + 10) if retri.jid == 'foo2'
458
+ end
476
459
 
477
- Sidekiq.redis do |conn|
478
- conn.sadd('processes', "bar:987")
479
- conn.sadd('processes', "bar:986")
460
+ assert_equal 2, retries.size
461
+ assert(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
480
462
  end
481
463
 
482
- ps = Sidekiq::ProcessSet.new
483
- assert_equal 1, ps.size
484
- assert_equal 1, ps.to_a.size
485
- end
464
+ it 'prunes processes which have died' do
465
+ data = { 'pid' => rand(10_000), 'hostname' => "app#{rand(1_000)}", 'started_at' => Time.now.to_f }
466
+ key = "#{data['hostname']}:#{data['pid']}"
467
+ Sidekiq.redis do |conn|
468
+ conn.sadd('processes', key)
469
+ conn.hmset(key, 'info', Sidekiq.dump_json(data), 'busy', 0, 'beat', Time.now.to_f)
470
+ end
486
471
 
487
- def add_retry(jid = 'bob', at = Time.now.to_f)
488
- payload = Sidekiq.dump_json('class' => 'ApiWorker', 'args' => [1, 'mike'], 'queue' => 'default', 'jid' => jid, 'retry_count' => 2, 'failed_at' => Time.now.to_f)
489
- Sidekiq.redis do |conn|
490
- conn.zadd('retry', at.to_s, payload)
472
+ ps = Sidekiq::ProcessSet.new
473
+ assert_equal 1, ps.size
474
+ assert_equal 1, ps.to_a.size
475
+
476
+ Sidekiq.redis do |conn|
477
+ conn.sadd('processes', "bar:987")
478
+ conn.sadd('processes', "bar:986")
479
+ end
480
+
481
+ ps = Sidekiq::ProcessSet.new
482
+ assert_equal 1, ps.size
483
+ assert_equal 1, ps.to_a.size
484
+ end
485
+
486
+ def add_retry(jid = 'bob', at = Time.now.to_f)
487
+ payload = Sidekiq.dump_json('class' => 'ApiWorker', 'args' => [1, 'mike'], 'queue' => 'default', 'jid' => jid, 'retry_count' => 2, 'failed_at' => Time.now.to_f)
488
+ Sidekiq.redis do |conn|
489
+ conn.zadd('retry', at.to_s, payload)
490
+ end
491
491
  end
492
492
  end
493
493
  end