sidekiq 3.1.3 → 3.1.4
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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/3.0-Upgrade.md +6 -1
- data/Changes.md +9 -0
- data/Rakefile +1 -0
- data/lib/sidekiq.rb +1 -17
- data/lib/sidekiq/api.rb +56 -17
- data/lib/sidekiq/cli.rb +16 -1
- data/lib/sidekiq/launcher.rb +4 -1
- data/lib/sidekiq/processor.rb +1 -1
- data/lib/sidekiq/scheduled.rb +26 -6
- data/lib/sidekiq/version.rb +1 -1
- data/test/helper.rb +3 -3
- data/test/test_api.rb +18 -1
- data/test/test_fetch.rb +1 -1
- data/test/test_manager.rb +1 -1
- data/test/test_redis_connection.rb +8 -0
- data/web/assets/stylesheets/application.css +0 -12
- data/web/views/morgue.erb +1 -1
- data/web/views/retries.erb +2 -2
- data/web/views/scheduled.erb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 842995b5a36bd3651ba6ed63d3f0c2c5f99a2c1b
|
4
|
+
data.tar.gz: 4f362b15d3748d3df41dad8ba1364d967a5e37cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc001192b00a22ad94893693543234b2542a6f91af74abc0a9963bf19bfd96c33babe084efcad2ce454f26bd78bdbbb356364fc86ba7d63bc5e0fb441a514a09
|
7
|
+
data.tar.gz: 7ea2ab5908163f70dc386b9ab89ce84321f3e93bf5bc4d20f0152ecc3a1ae67dba100abf088bcea4c9c163cf904623208877c16b993127d3e927038a0dafbfde
|
data/.travis.yml
CHANGED
data/3.0-Upgrade.md
CHANGED
@@ -29,7 +29,10 @@ changes a few data elements in Redis. To upgrade cleanly:
|
|
29
29
|
* Redis-to-Go is no longer transparently activated on Heroku so as to not play
|
30
30
|
favorites with any particular Redis service. You need to set a config option
|
31
31
|
for your app:
|
32
|
-
`heroku config:set REDIS_PROVIDER=REDISTOGO_URL
|
32
|
+
`heroku config:set REDIS_PROVIDER=REDISTOGO_URL`. You may also use
|
33
|
+
the generic `REDIS_URL`. See
|
34
|
+
[Advanced Options: Setting the Location of your Redis server][1]
|
35
|
+
for details.
|
33
36
|
* Anyone using Airbrake, Honeybadger, Exceptional or ExceptionNotifier
|
34
37
|
will need to update their error gem version to the latest to pull in
|
35
38
|
Sidekiq support. Sidekiq will not provide explicit support for these
|
@@ -63,3 +66,5 @@ end
|
|
63
66
|
```
|
64
67
|
|
65
68
|
Your error handler must respond to `call(exception, context_hash)`.
|
69
|
+
|
70
|
+
[1]: https://github.com/mperham/sidekiq/wiki/Advanced-Options#via-env-variable
|
data/Changes.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
3.1.4
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Happy π release!
|
5
|
+
- Self-tuning Scheduler polling, we use heartbeat info to better tune poll\_interval [#1630]
|
6
|
+
- Remove all table column width rules, hopefully get better column formatting [#1747]
|
7
|
+
- Handle edge case where YAML can't be decoded in dev mode [#1761]
|
8
|
+
- Fix lingering jobs in Busy page on Heroku [#1764]
|
9
|
+
|
1
10
|
3.1.3
|
2
11
|
-----------
|
3
12
|
|
data/Rakefile
CHANGED
data/lib/sidekiq.rb
CHANGED
@@ -118,9 +118,7 @@ module Sidekiq
|
|
118
118
|
Sidekiq::Logging.logger = log
|
119
119
|
end
|
120
120
|
|
121
|
-
#
|
122
|
-
# (Sidekiq process count * 5). So if you have a dozen Sidekiq processes, set
|
123
|
-
# poll_interval to 60.
|
121
|
+
# See sidekiq/scheduled.rb for an in-depth explanation of this value
|
124
122
|
def self.poll_interval=(interval)
|
125
123
|
self.options[:poll_interval] = interval
|
126
124
|
end
|
@@ -149,20 +147,6 @@ module Sidekiq
|
|
149
147
|
raise ArgumentError, "Invalid event name: #{event}" if !options[:lifecycle_events].keys.include?(event)
|
150
148
|
options[:lifecycle_events][event] << block
|
151
149
|
end
|
152
|
-
|
153
|
-
BANNER = %q{ s
|
154
|
-
ss
|
155
|
-
sss sss ss
|
156
|
-
s sss s ssss sss ____ _ _ _ _
|
157
|
-
s sssss ssss / ___|(_) __| | ___| | _(_) __ _
|
158
|
-
s sss \___ \| |/ _` |/ _ \ |/ / |/ _` |
|
159
|
-
s sssss s ___) | | (_| | __/ <| | (_| |
|
160
|
-
ss s s |____/|_|\__,_|\___|_|\_\_|\__, |
|
161
|
-
s s s |_|
|
162
|
-
s s
|
163
|
-
sss
|
164
|
-
sss }
|
165
|
-
|
166
150
|
end
|
167
151
|
|
168
152
|
require 'sidekiq/extensions/class_methods'
|
data/lib/sidekiq/api.rb
CHANGED
@@ -206,8 +206,9 @@ module Sidekiq
|
|
206
206
|
# Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
|
207
207
|
@klass ||= case klass
|
208
208
|
when /\ASidekiq::Extensions::Delayed/
|
209
|
-
(target, method, _
|
210
|
-
|
209
|
+
safe_load(args[0], klass) do |target, method, _|
|
210
|
+
"#{target}.#{method}"
|
211
|
+
end
|
211
212
|
when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
212
213
|
args[0]
|
213
214
|
else
|
@@ -219,8 +220,9 @@ module Sidekiq
|
|
219
220
|
# Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
|
220
221
|
@args ||= case klass
|
221
222
|
when /\ASidekiq::Extensions::Delayed/
|
222
|
-
(_, _, arg
|
223
|
-
|
223
|
+
safe_load(args[0], args) do |_, _, arg|
|
224
|
+
arg
|
225
|
+
end
|
224
226
|
when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
225
227
|
args[1..-1]
|
226
228
|
else
|
@@ -260,6 +262,19 @@ module Sidekiq
|
|
260
262
|
def [](name)
|
261
263
|
@item.__send__(:[], name)
|
262
264
|
end
|
265
|
+
|
266
|
+
private
|
267
|
+
|
268
|
+
def safe_load(content, default)
|
269
|
+
begin
|
270
|
+
yield *YAML.load(content)
|
271
|
+
rescue ::ArgumentError => ex
|
272
|
+
# #1761 in dev mode, it's possible to have jobs enqueued which haven't been loaded into
|
273
|
+
# memory yet so the YAML can't be loaded.
|
274
|
+
Sidekiq.logger.warn "Unable to load YAML: #{ex.message}" unless Sidekiq.options[:environment] == 'development'
|
275
|
+
default
|
276
|
+
end
|
277
|
+
end
|
263
278
|
end
|
264
279
|
|
265
280
|
class SortedEntry < Job
|
@@ -286,32 +301,56 @@ module Sidekiq
|
|
286
301
|
end
|
287
302
|
|
288
303
|
def add_to_queue
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
conn.zremrangebyscore('schedule', score, score)
|
293
|
-
end.first
|
294
|
-
results.map do |message|
|
295
|
-
msg = Sidekiq.load_json(message)
|
296
|
-
Sidekiq::Client.push(msg)
|
297
|
-
end
|
304
|
+
remove_job do |message|
|
305
|
+
msg = Sidekiq.load_json(message)
|
306
|
+
Sidekiq::Client.push(msg)
|
298
307
|
end
|
299
308
|
end
|
300
309
|
|
301
310
|
def retry
|
302
311
|
raise "Retry not available on jobs which have not failed" unless item["failed_at"]
|
312
|
+
remove_job do |message|
|
313
|
+
msg = Sidekiq.load_json(message)
|
314
|
+
msg['retry_count'] = msg['retry_count'] - 1
|
315
|
+
Sidekiq::Client.push(msg)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
private
|
320
|
+
|
321
|
+
def remove_job
|
303
322
|
Sidekiq.redis do |conn|
|
304
323
|
results = conn.multi do
|
305
324
|
conn.zrangebyscore(parent.name, score, score)
|
306
325
|
conn.zremrangebyscore(parent.name, score, score)
|
307
326
|
end.first
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
327
|
+
|
328
|
+
if results.size == 1
|
329
|
+
yield results.first
|
330
|
+
else
|
331
|
+
# multiple jobs with the same score
|
332
|
+
# find the one with the right JID and push it
|
333
|
+
hash = results.group_by do |message|
|
334
|
+
if message.index(jid)
|
335
|
+
msg = Sidekiq.load_json(message)
|
336
|
+
msg['jid'] == jid
|
337
|
+
else
|
338
|
+
false
|
339
|
+
end
|
340
|
+
end
|
341
|
+
message = hash[true].first
|
342
|
+
yield message
|
343
|
+
|
344
|
+
# push the rest back onto the sorted set
|
345
|
+
conn.multi do
|
346
|
+
hash[false].each do |message|
|
347
|
+
conn.zadd(parent.name, score.to_f.to_s, message)
|
348
|
+
end
|
349
|
+
end
|
312
350
|
end
|
313
351
|
end
|
314
352
|
end
|
353
|
+
|
315
354
|
end
|
316
355
|
|
317
356
|
class SortedSet
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -91,13 +91,28 @@ module Sidekiq
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
+
def self.banner
|
95
|
+
%q{ s
|
96
|
+
ss
|
97
|
+
sss sss ss
|
98
|
+
s sss s ssss sss ____ _ _ _ _
|
99
|
+
s sssss ssss / ___|(_) __| | ___| | _(_) __ _
|
100
|
+
s sss \___ \| |/ _` |/ _ \ |/ / |/ _` |
|
101
|
+
s sssss s ___) | | (_| | __/ <| | (_| |
|
102
|
+
ss s s |____/|_|\__,_|\___|_|\_\_|\__, |
|
103
|
+
s s s |_|
|
104
|
+
s s
|
105
|
+
sss
|
106
|
+
sss }
|
107
|
+
end
|
108
|
+
|
94
109
|
private
|
95
110
|
|
96
111
|
def print_banner
|
97
112
|
# Print logo and banner for development
|
98
113
|
if environment == 'development' && $stdout.tty?
|
99
114
|
puts "\e[#{31}m"
|
100
|
-
puts Sidekiq::
|
115
|
+
puts Sidekiq::CLI.banner
|
101
116
|
puts "\e[0m"
|
102
117
|
end
|
103
118
|
end
|
data/lib/sidekiq/launcher.rb
CHANGED
data/lib/sidekiq/processor.rb
CHANGED
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -5,7 +5,7 @@ require 'sidekiq/actor'
|
|
5
5
|
module Sidekiq
|
6
6
|
module Scheduled
|
7
7
|
|
8
|
-
|
8
|
+
INITIAL_WAIT = 10
|
9
9
|
|
10
10
|
##
|
11
11
|
# The Poller checks Redis every N seconds for messages in the retry or scheduled
|
@@ -20,7 +20,7 @@ module Sidekiq
|
|
20
20
|
|
21
21
|
def poll(first_time=false)
|
22
22
|
watchdog('scheduling poller thread died!') do
|
23
|
-
|
23
|
+
initial_wait if first_time
|
24
24
|
|
25
25
|
begin
|
26
26
|
# A message's "score" in Redis is the time at which it should be processed.
|
@@ -51,19 +51,39 @@ module Sidekiq
|
|
51
51
|
logger.error ex.backtrace.first
|
52
52
|
end
|
53
53
|
|
54
|
-
after(poll_interval) { poll }
|
54
|
+
after(poll_interval * rand) { poll }
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
private
|
59
59
|
|
60
|
+
# We do our best to tune poll_interval to the size of the active Sidekiq
|
61
|
+
# cluster. If you have 30 processes and poll every 15 seconds, that means one
|
62
|
+
# Sidekiq is checking Redis every 0.5 seconds - way too often for most people
|
63
|
+
# and really bad if the retry or scheduled sets are large.
|
64
|
+
#
|
65
|
+
# Instead try to avoid polling more than once every 15 seconds. If you have
|
66
|
+
# 30 Sidekiq processes, we'll set poll_interval to 30 * 15 * 2 or 900 seconds.
|
67
|
+
# To keep things statistically random, we'll sleep a random amount between
|
68
|
+
# 0 and 900 seconds for each poll or 450 seconds on average. Otherwise restarting
|
69
|
+
# all your Sidekiq processes at the same time will lead to them all polling at
|
70
|
+
# the same time: the thundering herd problem.
|
71
|
+
#
|
72
|
+
# We only do this if poll_interval is unset (the default).
|
60
73
|
def poll_interval
|
61
|
-
Sidekiq.options[:poll_interval]
|
74
|
+
Sidekiq.options[:poll_interval] ||= begin
|
75
|
+
pcount = Sidekiq.redis {|c| c.scard('processes') } || 1
|
76
|
+
pcount * 15 * 2
|
77
|
+
end
|
62
78
|
end
|
63
79
|
|
64
|
-
def
|
80
|
+
def initial_wait
|
65
81
|
begin
|
66
|
-
sleep
|
82
|
+
# Have all processes sleep between 10-15 seconds. 10 seconds
|
83
|
+
# to give time for the heartbeat to register and 5 random seconds
|
84
|
+
# to ensure they don't all hit Redis at the same time.
|
85
|
+
sleep(INITIAL_WAIT)
|
86
|
+
sleep(5 * rand)
|
67
87
|
rescue Celluloid::Task::TerminatedError
|
68
88
|
# Hit Ctrl-C when Sidekiq is finished booting and we have a chance
|
69
89
|
# to get here.
|
data/lib/sidekiq/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -31,9 +31,9 @@ Sidekiq.logger.level = Logger::ERROR
|
|
31
31
|
Sidekiq::Test = Minitest::Test
|
32
32
|
|
33
33
|
require 'sidekiq/redis_connection'
|
34
|
-
|
35
|
-
REDIS = Sidekiq::RedisConnection.create(:url =>
|
34
|
+
REDIS_URL = ENV['REDIS_URL'] || 'redis://localhost/15'
|
35
|
+
REDIS = Sidekiq::RedisConnection.create(:url => REDIS_URL, :namespace => 'testy')
|
36
36
|
|
37
37
|
Sidekiq.configure_client do |config|
|
38
|
-
config.redis = { :url =>
|
38
|
+
config.redis = { :url => REDIS_URL, :namespace => 'testy' }
|
39
39
|
end
|
data/test/test_api.rb
CHANGED
@@ -219,6 +219,7 @@ class TestApi < Sidekiq::Test
|
|
219
219
|
end
|
220
220
|
|
221
221
|
it "can move scheduled job to queue" do
|
222
|
+
remain_id = ApiWorker.perform_in(100, 1, 'jason')
|
222
223
|
job_id = ApiWorker.perform_in(100, 1, 'jason')
|
223
224
|
job = Sidekiq::ScheduledSet.new.find_job(job_id)
|
224
225
|
q = Sidekiq::Queue.new
|
@@ -226,8 +227,24 @@ class TestApi < Sidekiq::Test
|
|
226
227
|
queued_job = q.find_job(job_id)
|
227
228
|
refute_nil queued_job
|
228
229
|
assert_equal queued_job.jid, job_id
|
230
|
+
assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
|
231
|
+
refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
|
232
|
+
end
|
233
|
+
|
234
|
+
it "handles multiple scheduled jobs when moving to queue" do
|
235
|
+
jids = Sidekiq::Client.push_bulk('class' => ApiWorker,
|
236
|
+
'args' => [[1, 'jason'], [2, 'jason']],
|
237
|
+
'at' => Time.now.to_f)
|
238
|
+
assert_equal 2, jids.size
|
239
|
+
(remain_id, job_id) = jids
|
229
240
|
job = Sidekiq::ScheduledSet.new.find_job(job_id)
|
230
|
-
|
241
|
+
q = Sidekiq::Queue.new
|
242
|
+
job.add_to_queue
|
243
|
+
queued_job = q.find_job(job_id)
|
244
|
+
refute_nil queued_job
|
245
|
+
assert_equal queued_job.jid, job_id
|
246
|
+
assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
|
247
|
+
refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
|
231
248
|
end
|
232
249
|
|
233
250
|
it 'can find job by id in sorted sets' do
|
data/test/test_fetch.rb
CHANGED
@@ -4,7 +4,7 @@ require 'sidekiq/fetch'
|
|
4
4
|
class TestFetcher < Sidekiq::Test
|
5
5
|
describe 'fetcher' do
|
6
6
|
before do
|
7
|
-
Sidekiq.redis = { :namespace => 'fuzzy' }
|
7
|
+
Sidekiq.redis = { :url => REDIS_URL, :namespace => 'fuzzy' }
|
8
8
|
Sidekiq.redis do |conn|
|
9
9
|
conn.flushdb
|
10
10
|
conn.rpush('queue:basic', 'msg')
|
data/test/test_manager.rb
CHANGED
@@ -115,7 +115,7 @@ class TestManager < Sidekiq::Test
|
|
115
115
|
info = Sidekiq.redis { |c| c.hmget('identity', 'busy') }
|
116
116
|
assert_equal ["1"], info
|
117
117
|
expires = Sidekiq.redis { |c| c.pttl('identity') }
|
118
|
-
assert_in_delta 60000, expires,
|
118
|
+
assert_in_delta 60000, expires, 10
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -70,6 +70,14 @@ class TestRedisConnection < Sidekiq::Test
|
|
70
70
|
|
71
71
|
describe ".determine_redis_provider" do
|
72
72
|
|
73
|
+
before do
|
74
|
+
@old_env = ENV.to_hash
|
75
|
+
end
|
76
|
+
|
77
|
+
after do
|
78
|
+
ENV.update(@old_env)
|
79
|
+
end
|
80
|
+
|
73
81
|
def with_env_var(var, uri, skip_provider=false)
|
74
82
|
vars = ['REDISTOGO_URL', 'REDIS_PROVIDER', 'REDIS_URL'] - [var]
|
75
83
|
vars.each do |v|
|
@@ -197,18 +197,6 @@ td form {
|
|
197
197
|
padding: 0px;
|
198
198
|
}
|
199
199
|
|
200
|
-
.table td {
|
201
|
-
/* Non standard for webkit */
|
202
|
-
word-break: break-word;
|
203
|
-
|
204
|
-
-webkit-hyphens: auto;
|
205
|
-
-moz-hyphens: auto;
|
206
|
-
hyphens: auto;
|
207
|
-
|
208
|
-
-ms-word-break: break-all;
|
209
|
-
word-break: break-all;
|
210
|
-
}
|
211
|
-
|
212
200
|
table .table-checkbox label {
|
213
201
|
height: 100%;
|
214
202
|
width: 100%;
|
data/web/views/morgue.erb
CHANGED
data/web/views/retries.erb
CHANGED
@@ -20,8 +20,8 @@
|
|
20
20
|
<input type="checkbox" class="check_all" />
|
21
21
|
</label>
|
22
22
|
</th>
|
23
|
-
<th
|
24
|
-
<th
|
23
|
+
<th><%= t('NextRetry') %></th>
|
24
|
+
<th><%= t('RetryCount') %></th>
|
25
25
|
<th><%= t('Queue') %></th>
|
26
26
|
<th><%= t('Job') %></th>
|
27
27
|
<th><%= t('Arguments') %></th>
|
data/web/views/scheduled.erb
CHANGED
@@ -19,8 +19,8 @@
|
|
19
19
|
<th width="20px">
|
20
20
|
<input type="checkbox" class="check_all" />
|
21
21
|
</th>
|
22
|
-
<th
|
23
|
-
<th
|
22
|
+
<th><%= t('When') %></th>
|
23
|
+
<th><%= t('Queue') %></th>
|
24
24
|
<th><%= t('Job') %></th>
|
25
25
|
<th><%= t('Arguments') %></th>
|
26
26
|
</tr>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|