sidekiq 3.2.1 → 3.2.2
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 +0 -1
- data/Changes.md +11 -1
- data/Contributing.md +12 -2
- data/LICENSE +1 -1
- data/Pro-Changes.md +6 -0
- data/README.md +3 -5
- data/lib/sidekiq.rb +6 -4
- data/lib/sidekiq/api.rb +35 -3
- data/lib/sidekiq/launcher.rb +5 -8
- data/lib/sidekiq/manager.rb +7 -6
- data/lib/sidekiq/middleware/server/retry_jobs.rb +32 -21
- data/lib/sidekiq/scheduled.rb +5 -2
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +11 -7
- data/lib/sidekiq/web_helpers.rb +12 -0
- data/test/test_manager.rb +2 -2
- data/test/test_web.rb +11 -0
- data/web/assets/stylesheets/application.css +8 -6
- data/web/locales/de.yml +1 -0
- data/web/locales/en.yml +1 -0
- data/web/locales/es.yml +1 -0
- data/web/locales/fr.yml +1 -0
- data/web/locales/it.yml +1 -0
- data/web/locales/ru.yml +1 -0
- data/web/views/_footer.erb +22 -0
- data/web/views/_nav.erb +30 -26
- data/web/views/_poll.erb +4 -6
- data/web/views/busy.erb +3 -2
- data/web/views/dashboard.erb +16 -11
- data/web/views/layout.erb +3 -28
- data/web/views/retries.erb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac4be785d484b8190a4aeb09fc93d21f4897f2f1
|
4
|
+
data.tar.gz: 9955d71f3356939e2cc06f7287f66d850b18604c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba6263b604d50445ad7582a49870daf4af2105570d0d43fe6702128903bdda651c640435eff1d4f61fdeb828193ed91fc6552b536f87fc8cee3d4b313b7c13f9
|
7
|
+
data.tar.gz: 260002fc92ba5a50aa910402f388ca1f77f2c21aab076fcd59f8e9d04c68e48cbd2b2889f89ef1caee745e9a585af86f1ea9caa65c46af68983d23f66ec0e55c
|
data/.travis.yml
CHANGED
data/Changes.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
3.2.2
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Fix issue which could cause Sidekiq workers to disappear from the Busy
|
5
|
+
tab while still being active [#1884]
|
6
|
+
- Add "Back to App" button in Web UI. You can set the button link via
|
7
|
+
`Sidekiq::Web.app_url = 'http://www.mysite.com'` [#1875, seuros]
|
8
|
+
- Add process tag (`-g tag`) to the Busy page so you can differentiate processes at a glance. [seuros, #1878]
|
9
|
+
- Add "Kill" button to move retries directly to the DJQ so they don't retry. [seuros, #1867]
|
10
|
+
|
1
11
|
3.2.1
|
2
12
|
-----------
|
3
13
|
|
@@ -173,7 +183,7 @@ middleware, see 3.0-Upgrade.md.**
|
|
173
183
|
|
174
184
|
- Automatically use the config file found at `config/sidekiq.yml`, if not passed `-C`. [#1481]
|
175
185
|
- Store 'retried\_at' and 'failed\_at' timestamps as Floats, not Strings. [#1473]
|
176
|
-
- A `USR2` signal will now reopen _all_ logs, using IO#reopen. Thus, instead of creating a new Logger object,
|
186
|
+
- A `USR2` signal will now reopen _all_ logs, using IO#reopen. Thus, instead of creating a new Logger object,
|
177
187
|
Sidekiq will now just update the existing Logger's file descriptor [#1163].
|
178
188
|
- Remove pidfile when shutting down if started with `-P` [#1470]
|
179
189
|
|
data/Contributing.md
CHANGED
@@ -20,6 +20,16 @@ fix or new functionality. Functionality must meet my design goals and
|
|
20
20
|
vision for the project to be accepted; I would be happy to discuss how
|
21
21
|
your idea can best fit into Sidekiq.
|
22
22
|
|
23
|
-
##
|
23
|
+
## Legal
|
24
|
+
|
25
|
+
By submitting a Pull Request, you disavow any rights or
|
26
|
+
claims to any changes submitted to the Sidekiq project and assign the copyright of
|
27
|
+
those changes to Contributed Systems LLC.
|
28
|
+
|
29
|
+
If you cannot or do not want to reassign those rights (your employment
|
30
|
+
contract for your employer may not allow this), you should not submit a PR.
|
31
|
+
Open an issue and someone else can do the work.
|
32
|
+
|
33
|
+
This is a legal way of saying "If you submit a PR to us, that code becomes ours".
|
34
|
+
99.9% of the time that's what you intend anyways; we hope it doesn't scare you away from contributing!
|
24
35
|
|
25
|
-
If you've got more money than time and want to sponsor Sidekiq's continued support, your company can buy [Sidekiq Pro](http://sidekiq.org/pro). You get great functionality, I continue to fix bugs and enhance Sidekiq for years to come.
|
data/LICENSE
CHANGED
data/Pro-Changes.md
CHANGED
data/README.md
CHANGED
@@ -62,11 +62,9 @@ More Information
|
|
62
62
|
|
63
63
|
Please see the [sidekiq wiki](https://github.com/mperham/sidekiq/wiki) for the official documentation.
|
64
64
|
[#sidekiq on irc.freenode.net](irc://irc.freenode.net/#sidekiq) is dedicated to this project,
|
65
|
-
but bug reports or feature requests suggestions should still go through [issues on Github](https://github.com/mperham/sidekiq/issues). Release announcements are made to [@sidekiq](https://twitter.com/sidekiq)
|
65
|
+
but bug reports or feature requests suggestions should still go through [issues on Github](https://github.com/mperham/sidekiq/issues). Release announcements are made to the [@sidekiq](https://twitter.com/sidekiq) Twitter account.
|
66
66
|
|
67
|
-
|
68
|
-
an email to <sidekiq@librelist.org> with a greeting in the body. To unsubscribe, send an email to <sidekiq-unsubscribe@librelist.org> and that's it!
|
69
|
-
Once archiving begins, you'll be able to visit [the archives](http://librelist.com/browser/sidekiq/) to see past threads.
|
67
|
+
You may also find useful a [Google Group](https://groups.google.com/forum/#!forum/sidekiq) dedicated to Sidekiq discussion and [a Sidekiq tag](https://stackoverflow.com/questions/tagged/sidekiq) on Stack Overflow.
|
70
68
|
|
71
69
|
|
72
70
|
Problems?
|
@@ -94,4 +92,4 @@ Please see [LICENSE](https://github.com/mperham/sidekiq/blob/master/LICENSE) for
|
|
94
92
|
Author
|
95
93
|
-----------------
|
96
94
|
|
97
|
-
Mike Perham, [@mperham](https://twitter.com/mperham) / [@sidekiq](https://twitter.com/sidekiq), [http://mikeperham.com](http://mikeperham.com)
|
95
|
+
Mike Perham, [@mperham](https://twitter.com/mperham) / [@sidekiq](https://twitter.com/sidekiq), [http://mikeperham.com](http://mikeperham.com) / [http://www.contribsys.com](http://www.contribsys.com)
|
data/lib/sidekiq.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'sidekiq/version'
|
3
|
+
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby 1.9." if RUBY_PLATFORM != 'java' && RUBY_VERSION < '2.0.0'
|
4
|
+
|
3
5
|
require 'sidekiq/logging'
|
4
6
|
require 'sidekiq/client'
|
5
7
|
require 'sidekiq/worker'
|
@@ -23,7 +25,7 @@ module Sidekiq
|
|
23
25
|
:startup => [],
|
24
26
|
:quiet => [],
|
25
27
|
:shutdown => [],
|
26
|
-
}
|
28
|
+
}
|
27
29
|
}
|
28
30
|
|
29
31
|
def self.❨╯°□°❩╯︵┻━┻
|
@@ -66,7 +68,7 @@ module Sidekiq
|
|
66
68
|
end
|
67
69
|
|
68
70
|
def self.redis(&block)
|
69
|
-
raise ArgumentError, "requires a block"
|
71
|
+
raise ArgumentError, "requires a block" unless block
|
70
72
|
redis_pool.with(&block)
|
71
73
|
end
|
72
74
|
|
@@ -143,8 +145,8 @@ module Sidekiq
|
|
143
145
|
# end
|
144
146
|
# end
|
145
147
|
def self.on(event, &block)
|
146
|
-
raise ArgumentError, "Symbols only please: #{event}"
|
147
|
-
raise ArgumentError, "Invalid event name: #{event}"
|
148
|
+
raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
|
149
|
+
raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].keys.include?(event)
|
148
150
|
options[:lifecycle_events][event] << block
|
149
151
|
end
|
150
152
|
end
|
data/lib/sidekiq/api.rb
CHANGED
@@ -316,6 +316,23 @@ module Sidekiq
|
|
316
316
|
end
|
317
317
|
end
|
318
318
|
|
319
|
+
##
|
320
|
+
# Place job in the dead set
|
321
|
+
def kill
|
322
|
+
raise 'Kill not available on jobs which have not failed' unless item['failed_at']
|
323
|
+
remove_job do |message|
|
324
|
+
Sidekiq.logger.info { "Killing job #{message['jid']}" }
|
325
|
+
now = Time.now.to_f
|
326
|
+
Sidekiq.redis do |conn|
|
327
|
+
conn.multi do
|
328
|
+
conn.zadd('dead', now, message)
|
329
|
+
conn.zremrangebyscore('dead', '-inf', now - DeadSet::DEAD_JOB_TIMEOUT)
|
330
|
+
conn.zremrangebyrank('dead', 0, - DeadSet::MAX_JOBS)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
319
336
|
private
|
320
337
|
|
321
338
|
def remove_job
|
@@ -338,12 +355,13 @@ module Sidekiq
|
|
338
355
|
false
|
339
356
|
end
|
340
357
|
end
|
341
|
-
|
342
|
-
|
358
|
+
|
359
|
+
msg = hash.fetch(true, []).first
|
360
|
+
yield msg if msg
|
343
361
|
|
344
362
|
# push the rest back onto the sorted set
|
345
363
|
conn.multi do
|
346
|
-
hash[
|
364
|
+
hash.fetch(false, []).each do |message|
|
347
365
|
conn.zadd(parent.name, score.to_f.to_s, message)
|
348
366
|
end
|
349
367
|
end
|
@@ -498,7 +516,13 @@ module Sidekiq
|
|
498
516
|
end
|
499
517
|
end
|
500
518
|
|
519
|
+
##
|
520
|
+
# Allows enumeration of dead jobs within Sidekiq.
|
521
|
+
#
|
501
522
|
class DeadSet < JobSet
|
523
|
+
DEAD_JOB_TIMEOUT = 180 * 24 * 60 * 60 # 6 months
|
524
|
+
MAX_JOBS = 10_000
|
525
|
+
|
502
526
|
def initialize
|
503
527
|
super 'dead'
|
504
528
|
end
|
@@ -577,6 +601,14 @@ module Sidekiq
|
|
577
601
|
@attribs = hash
|
578
602
|
end
|
579
603
|
|
604
|
+
def tag
|
605
|
+
self['tag']
|
606
|
+
end
|
607
|
+
|
608
|
+
def labels
|
609
|
+
Array(self['labels'])
|
610
|
+
end
|
611
|
+
|
580
612
|
def [](key)
|
581
613
|
@attribs[key]
|
582
614
|
end
|
data/lib/sidekiq/launcher.rb
CHANGED
@@ -71,14 +71,10 @@ module Sidekiq
|
|
71
71
|
'queues' => @options[:queues].uniq,
|
72
72
|
'labels' => Sidekiq.options[:labels],
|
73
73
|
}
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
conn.expire(key, 60)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
manager.heartbeat(key, data)
|
74
|
+
# this data doesn't change so dump it to a string
|
75
|
+
# now so we don't need to dump it every heartbeat.
|
76
|
+
json = Sidekiq.dump_json(data)
|
77
|
+
manager.heartbeat(key, data, json)
|
82
78
|
end
|
83
79
|
|
84
80
|
def stop_heartbeat
|
@@ -89,5 +85,6 @@ module Sidekiq
|
|
89
85
|
end
|
90
86
|
end
|
91
87
|
end
|
88
|
+
|
92
89
|
end
|
93
90
|
end
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -132,26 +132,27 @@ module Sidekiq
|
|
132
132
|
@threads[proxy_id] = thr
|
133
133
|
end
|
134
134
|
|
135
|
-
def heartbeat(key, data)
|
135
|
+
def heartbeat(key, data, json)
|
136
136
|
proctitle = ['sidekiq', Sidekiq::VERSION]
|
137
137
|
proctitle << data['tag'] unless data['tag'].empty?
|
138
138
|
proctitle << "[#{@busy.size} of #{data['concurrency']} busy]"
|
139
139
|
proctitle << 'stopping' if stopped?
|
140
140
|
$0 = proctitle.join(' ')
|
141
141
|
|
142
|
-
❤(key)
|
142
|
+
❤(key, json)
|
143
143
|
after(5) do
|
144
|
-
heartbeat(key, data)
|
144
|
+
heartbeat(key, data, json)
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
148
|
private
|
149
149
|
|
150
|
-
def ❤(key)
|
150
|
+
def ❤(key, json)
|
151
151
|
begin
|
152
|
-
_, _, msg = Sidekiq.redis do |conn|
|
152
|
+
_, _, _, msg = Sidekiq.redis do |conn|
|
153
153
|
conn.multi do
|
154
|
-
conn.
|
154
|
+
conn.sadd('processes', key)
|
155
|
+
conn.hmset(key, 'info', json, 'busy', @busy.size, 'beat', Time.now.to_f)
|
155
156
|
conn.expire(key, 60)
|
156
157
|
conn.rpop("#{key}-signals")
|
157
158
|
end
|
@@ -6,21 +6,22 @@ module Sidekiq
|
|
6
6
|
##
|
7
7
|
# Automatically retry jobs that fail in Sidekiq.
|
8
8
|
# Sidekiq's retry support assumes a typical development lifecycle:
|
9
|
-
# 0. push some code changes with a bug in it
|
10
|
-
# 1. bug causes message processing to fail, sidekiq's middleware captures
|
11
|
-
# the message and pushes it onto a retry queue
|
12
|
-
# 2. sidekiq retries messages in the retry queue multiple times with
|
13
|
-
# an exponential delay, the message continues to fail
|
14
|
-
# 3. after a few days, a developer deploys a fix. the message is
|
15
|
-
# reprocessed successfully.
|
16
|
-
# 4. if 3 never happens, sidekiq will eventually give up and throw the
|
17
|
-
# message away. If the worker defines a method called 'retries_exhausted',
|
18
|
-
# this will be called before throwing the message away. If the
|
19
|
-
# 'retries_exhausted' method throws an exception, it's dropped and logged.
|
20
9
|
#
|
21
|
-
#
|
10
|
+
# 0. push some code changes with a bug in it
|
11
|
+
# 1. bug causes job processing to fail, sidekiq's middleware captures
|
12
|
+
# the job and pushes it onto a retry queue
|
13
|
+
# 2. sidekiq retries jobs in the retry queue multiple times with
|
14
|
+
# an exponential delay, the job continues to fail
|
15
|
+
# 3. after a few days, a developer deploys a fix. the job is
|
16
|
+
# reprocessed successfully.
|
17
|
+
# 4. once retries are exhausted, sidekiq will give up and move the
|
18
|
+
# job to the Dead Job Queue (aka morgue) where it must be dealt with
|
19
|
+
# manually in the Web UI.
|
20
|
+
# 5. After 6 months on the DJQ, Sidekiq will discard the job.
|
22
21
|
#
|
23
|
-
#
|
22
|
+
# A job looks like:
|
23
|
+
#
|
24
|
+
# { 'class' => 'HardWorker', 'args' => [1, 2, 'foo'], 'retry' => true }
|
24
25
|
#
|
25
26
|
# The 'retry' option also accepts a number (in place of 'true'):
|
26
27
|
#
|
@@ -29,7 +30,7 @@ module Sidekiq
|
|
29
30
|
# The job will be retried this number of times before giving up. (If simply
|
30
31
|
# 'true', Sidekiq retries 25 times)
|
31
32
|
#
|
32
|
-
# We'll add a bit more data to the
|
33
|
+
# We'll add a bit more data to the job to support retries:
|
33
34
|
#
|
34
35
|
# * 'queue' - the queue to use
|
35
36
|
# * 'retry_count' - number of times we've retried so far.
|
@@ -37,18 +38,28 @@ module Sidekiq
|
|
37
38
|
# * 'error_class' - the exception class
|
38
39
|
# * 'failed_at' - the first time it failed
|
39
40
|
# * 'retried_at' - the last time it was retried
|
41
|
+
# * 'backtrace' - the number of lines of error backtrace to store
|
40
42
|
#
|
41
|
-
# We don't store the backtrace as that can add a lot of overhead
|
42
|
-
# to the
|
43
|
+
# We don't store the backtrace by default as that can add a lot of overhead
|
44
|
+
# to the job and everyone is using an error service, right?
|
43
45
|
#
|
44
|
-
# The default number of retry attempts is 25
|
45
|
-
#
|
46
|
+
# The default number of retry attempts is 25 which works out to about 3 weeks
|
47
|
+
# of retries. You can pass a value for the max number of retry attempts when
|
48
|
+
# adding the middleware using the options hash:
|
46
49
|
#
|
47
50
|
# Sidekiq.configure_server do |config|
|
48
51
|
# config.server_middleware do |chain|
|
49
52
|
# chain.add Middleware::Server::RetryJobs, :max_retries => 7
|
50
53
|
# end
|
51
54
|
# end
|
55
|
+
#
|
56
|
+
# or limit the number of retries for a particular worker with:
|
57
|
+
#
|
58
|
+
# class MyWorker
|
59
|
+
# include Sidekiq::Worker
|
60
|
+
# sidekiq_options :retry => 10
|
61
|
+
# end
|
62
|
+
#
|
52
63
|
class RetryJobs
|
53
64
|
include Sidekiq::Util
|
54
65
|
|
@@ -75,7 +86,7 @@ module Sidekiq
|
|
75
86
|
else
|
76
87
|
queue
|
77
88
|
end
|
78
|
-
msg['error_message'] = e.message
|
89
|
+
msg['error_message'] = e.message[0..10_000]
|
79
90
|
msg['error_class'] = e.class.name
|
80
91
|
count = if msg['retry_count']
|
81
92
|
msg['retried_at'] = Time.now.to_f
|
@@ -134,8 +145,8 @@ module Sidekiq
|
|
134
145
|
Sidekiq.redis do |conn|
|
135
146
|
conn.multi do
|
136
147
|
conn.zadd('dead', now, payload)
|
137
|
-
conn.zremrangebyscore('dead', '-inf', now - DEAD_JOB_TIMEOUT)
|
138
|
-
conn.zremrangebyrank('dead', 0, -MAX_JOBS)
|
148
|
+
conn.zremrangebyscore('dead', '-inf', now - DeadSet::DEAD_JOB_TIMEOUT)
|
149
|
+
conn.zremrangebyrank('dead', 0, -DeadSet::MAX_JOBS)
|
139
150
|
end
|
140
151
|
end
|
141
152
|
end
|
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -51,7 +51,10 @@ module Sidekiq
|
|
51
51
|
logger.error ex.backtrace.first
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
# Randomizing scales the interval by half since
|
55
|
+
# on average calling `rand` returns 0.5.
|
56
|
+
# We make up for this by doubling the interval
|
57
|
+
after(poll_interval * 2 * rand) { poll }
|
55
58
|
end
|
56
59
|
end
|
57
60
|
|
@@ -73,7 +76,7 @@ module Sidekiq
|
|
73
76
|
def poll_interval
|
74
77
|
Sidekiq.options[:poll_interval] ||= begin
|
75
78
|
pcount = Sidekiq.redis {|c| c.scard('processes') } || 1
|
76
|
-
pcount * 15
|
79
|
+
pcount * 15
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -36,6 +36,8 @@ module Sidekiq
|
|
36
36
|
@custom_tabs ||= {}
|
37
37
|
end
|
38
38
|
alias_method :tabs, :custom_tabs
|
39
|
+
|
40
|
+
attr_accessor :app_url
|
39
41
|
end
|
40
42
|
|
41
43
|
get "/busy" do
|
@@ -100,7 +102,7 @@ module Sidekiq
|
|
100
102
|
|
101
103
|
params['key'].each do |key|
|
102
104
|
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
103
|
-
|
105
|
+
retry_or_delete_or_kill job, params if job
|
104
106
|
end
|
105
107
|
redirect_with_query("#{root_path}morgue")
|
106
108
|
end
|
@@ -118,7 +120,7 @@ module Sidekiq
|
|
118
120
|
post "/morgue/:key" do
|
119
121
|
halt 404 unless params['key']
|
120
122
|
job = Sidekiq::DeadSet.new.fetch(*parse_params(params['key'])).first
|
121
|
-
|
123
|
+
retry_or_delete_or_kill job, params if job
|
122
124
|
redirect_with_query("#{root_path}morgue")
|
123
125
|
end
|
124
126
|
|
@@ -142,7 +144,7 @@ module Sidekiq
|
|
142
144
|
|
143
145
|
params['key'].each do |key|
|
144
146
|
job = Sidekiq::RetrySet.new.fetch(*parse_params(key)).first
|
145
|
-
|
147
|
+
retry_or_delete_or_kill job, params if job
|
146
148
|
end
|
147
149
|
redirect_with_query("#{root_path}retries")
|
148
150
|
end
|
@@ -160,7 +162,7 @@ module Sidekiq
|
|
160
162
|
post "/retries/:key" do
|
161
163
|
halt 404 unless params['key']
|
162
164
|
job = Sidekiq::RetrySet.new.fetch(*parse_params(params['key'])).first
|
163
|
-
|
165
|
+
retry_or_delete_or_kill job, params if job
|
164
166
|
redirect_with_query("#{root_path}retries")
|
165
167
|
end
|
166
168
|
|
@@ -196,7 +198,7 @@ module Sidekiq
|
|
196
198
|
end
|
197
199
|
|
198
200
|
get '/' do
|
199
|
-
@redis_info =
|
201
|
+
@redis_info = redis_info.select{ |k, v| REDIS_KEYS.include? k }
|
200
202
|
stats_history = Sidekiq::Stats::History.new((params[:days] || 30).to_i)
|
201
203
|
@processed_history = stats_history.processed
|
202
204
|
@failed_history = stats_history.failed
|
@@ -208,7 +210,7 @@ module Sidekiq
|
|
208
210
|
get '/dashboard/stats' do
|
209
211
|
sidekiq_stats = Sidekiq::Stats.new
|
210
212
|
queue = Sidekiq::Queue.new
|
211
|
-
redis_stats =
|
213
|
+
redis_stats = redis_info.select{ |k, v| REDIS_KEYS.include? k }
|
212
214
|
|
213
215
|
content_type :json
|
214
216
|
Sidekiq.dump_json({
|
@@ -227,11 +229,13 @@ module Sidekiq
|
|
227
229
|
|
228
230
|
private
|
229
231
|
|
230
|
-
def
|
232
|
+
def retry_or_delete_or_kill job, params
|
231
233
|
if params['retry']
|
232
234
|
job.retry
|
233
235
|
elsif params['delete']
|
234
236
|
job.delete
|
237
|
+
elsif params['kill']
|
238
|
+
job.kill
|
235
239
|
end
|
236
240
|
end
|
237
241
|
|
data/lib/sidekiq/web_helpers.rb
CHANGED
@@ -68,6 +68,18 @@ module Sidekiq
|
|
68
68
|
@@ns ||= Sidekiq.redis {|conn| conn.respond_to?(:namespace) ? conn.namespace : nil }
|
69
69
|
end
|
70
70
|
|
71
|
+
def redis_info
|
72
|
+
Sidekiq.redis do |conn|
|
73
|
+
# admin commands can't go through redis-namespace starting
|
74
|
+
# in redis-namespace 2.0
|
75
|
+
if conn.respond_to?(:namespace)
|
76
|
+
conn.redis.info
|
77
|
+
else
|
78
|
+
conn.info
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
71
83
|
def root_path
|
72
84
|
"#{env['SCRIPT_NAME']}/"
|
73
85
|
end
|
data/test/test_manager.rb
CHANGED
@@ -104,7 +104,7 @@ class TestManager < Sidekiq::Test
|
|
104
104
|
|
105
105
|
describe 'when manager is active' do
|
106
106
|
before do
|
107
|
-
@mgr.heartbeat('identity', heartbeat_data)
|
107
|
+
@mgr.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
|
108
108
|
end
|
109
109
|
|
110
110
|
it 'sets useful info to proctitle' do
|
@@ -126,7 +126,7 @@ class TestManager < Sidekiq::Test
|
|
126
126
|
|
127
127
|
@mgr.stop
|
128
128
|
@mgr.processor_done(@processor)
|
129
|
-
@mgr.heartbeat('identity', heartbeat_data)
|
129
|
+
@mgr.heartbeat('identity', heartbeat_data, Sidekiq.dump_json(heartbeat_data))
|
130
130
|
|
131
131
|
@processor.verify
|
132
132
|
end
|
data/test/test_web.rb
CHANGED
@@ -173,6 +173,17 @@ class TestWeb < Sidekiq::Test
|
|
173
173
|
assert_match(/#{params.first['args'][2]}/, last_response.body)
|
174
174
|
end
|
175
175
|
|
176
|
+
it 'can kill a single retry now' do
|
177
|
+
params = add_retry
|
178
|
+
post "/retries/#{job_params(*params)}", 'kill' => 'Kill'
|
179
|
+
assert_equal 302, last_response.status
|
180
|
+
assert_equal 'http://example.org/retries', last_response.header['Location']
|
181
|
+
|
182
|
+
get '/morgue'
|
183
|
+
assert_equal 200, last_response.status
|
184
|
+
assert_match(/#{params.first['args'][2]}/, last_response.body)
|
185
|
+
end
|
186
|
+
|
176
187
|
it 'can display scheduled' do
|
177
188
|
get '/scheduled'
|
178
189
|
assert_equal 200, last_response.status
|
@@ -102,7 +102,7 @@ header.row .pagination {
|
|
102
102
|
border-width: 0;
|
103
103
|
}
|
104
104
|
.poll-wrapper {
|
105
|
-
|
105
|
+
margin: 9px;
|
106
106
|
}
|
107
107
|
.nav #live-poll {
|
108
108
|
height: 25px;
|
@@ -604,10 +604,6 @@ div.interval-slider input {
|
|
604
604
|
}
|
605
605
|
|
606
606
|
@media (max-width: 768px) {
|
607
|
-
.navbar .container {
|
608
|
-
text-align: center
|
609
|
-
}
|
610
|
-
|
611
607
|
.navbar .navbar-brand {
|
612
608
|
float: none;
|
613
609
|
display: block;
|
@@ -629,7 +625,13 @@ div.interval-slider input {
|
|
629
625
|
}
|
630
626
|
|
631
627
|
.poll-wrapper {
|
632
|
-
|
628
|
+
width: 100%;
|
629
|
+
text-align: center;
|
630
|
+
}
|
631
|
+
|
632
|
+
.poll-wrapper > a {
|
633
|
+
display: inline-block;
|
634
|
+
margin: 5px;
|
633
635
|
}
|
634
636
|
|
635
637
|
.navbar.navbar-fixed-bottom ul {
|
data/web/locales/de.yml
CHANGED
data/web/locales/en.yml
CHANGED
data/web/locales/es.yml
CHANGED
data/web/locales/fr.yml
CHANGED
data/web/locales/it.yml
CHANGED
data/web/locales/ru.yml
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
<div class="navbar navbar-fixed-bottom navbar-inverse">
|
2
|
+
<div class="navbar-inner">
|
3
|
+
<div class="container text-center">
|
4
|
+
<ul class="nav">
|
5
|
+
<li>
|
6
|
+
<p class="navbar-text" style="color:white;">Sidekiq v<%= Sidekiq::VERSION %></p>
|
7
|
+
</li>
|
8
|
+
<li>
|
9
|
+
<p class="navbar-text">Redis: <%= redis_connection %></p>
|
10
|
+
</li>
|
11
|
+
<li>
|
12
|
+
<p class="navbar-text"><%= t('Time') %>: <%= Time.now.utc.strftime('%H:%M:%S UTC') %></p>
|
13
|
+
</li>
|
14
|
+
<% if namespace %>
|
15
|
+
<li>
|
16
|
+
<p class="navbar-text"><%= t('Namespace') %>: <%= namespace %></p>
|
17
|
+
</li>
|
18
|
+
<% end %>
|
19
|
+
</ul>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
</div>
|
data/web/views/_nav.erb
CHANGED
@@ -1,30 +1,34 @@
|
|
1
|
-
<div class="navbar-
|
2
|
-
<div class="
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
1
|
+
<div class="navbar navbar-default navbar-fixed-top">
|
2
|
+
<div class="navbar-inner">
|
3
|
+
<div class="container-fluid text-center">
|
4
|
+
<a class="navbar-brand" href="<%= root_path %>">
|
5
|
+
<%= Sidekiq::NAME %>
|
6
|
+
<%= erb :_status %>
|
7
|
+
</a>
|
8
|
+
<ul class="nav navbar-nav">
|
9
|
+
<% Sidekiq::Web.default_tabs.each do |title, url| %>
|
10
|
+
<% if url == '' %>
|
11
|
+
<li class="<%= current_path == url ? 'active' : '' %>">
|
12
|
+
<a href="<%= root_path %><%= url %>"><%= t(title) %></a>
|
13
|
+
</li>
|
14
|
+
<% else %>
|
15
|
+
<li class="<%= current_path.start_with?(url) ? 'active' : '' %>">
|
16
|
+
<a href="<%= root_path %><%= url %>"><%= t(title) %></a>
|
17
|
+
</li>
|
18
|
+
<% end %>
|
19
|
+
<% end %>
|
20
|
+
<% Sidekiq::Web.custom_tabs.each do |title, url| %>
|
21
|
+
<li class="<%= current_path.start_with?(url) ? 'active' : '' %>">
|
22
|
+
<a href="<%= root_path %><%= url %>"><%= t(title) %></a>
|
23
|
+
</li>
|
24
|
+
<% end %>
|
25
|
+
</ul>
|
26
|
+
</div>
|
26
27
|
<div class="poll-wrapper pull-right">
|
27
|
-
|
28
|
+
<%= erb :_poll %>
|
29
|
+
<% if Sidekiq::Web.app_url %>
|
30
|
+
<a class="btn btn-inverse" href="<%= Sidekiq::Web.app_url %>">Back to App</a>
|
31
|
+
<% end %>
|
28
32
|
</div>
|
29
33
|
</div>
|
30
34
|
</div>
|
data/web/views/_poll.erb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
<% if
|
2
|
-
<script>
|
3
|
-
setInterval("window.location.reload(true)", parseInt(localStorage.timeInterval) || 2000);
|
4
|
-
</script>
|
5
|
-
<% end %>
|
6
|
-
<% unless current_path == '' %>
|
1
|
+
<% if current_path != '' %>
|
7
2
|
<% if params[:poll] %>
|
3
|
+
<script>
|
4
|
+
setInterval("window.location.reload(true)", parseInt(localStorage.timeInterval) || 2000);
|
5
|
+
</script>
|
8
6
|
<a id="live-poll" class="btn btn-primary active" href="<%= root_path %><%= current_path %>"><%= t('StopPolling') %></a>
|
9
7
|
<% else %>
|
10
8
|
<a id="live-poll" class="btn btn-primary" href="<%= root_path %><%= current_path %>?<%= qparams(poll: true) %>"><%= t('LivePoll') %></a>
|
data/web/views/busy.erb
CHANGED
@@ -21,11 +21,12 @@
|
|
21
21
|
<th><%= t('Busy') %></th>
|
22
22
|
<th> </th>
|
23
23
|
</thead>
|
24
|
-
<% Sidekiq::ProcessSet.new.
|
24
|
+
<% Sidekiq::ProcessSet.new.each do |process| %>
|
25
25
|
<tr>
|
26
26
|
<td>
|
27
27
|
<%= "#{process['hostname']}:#{process['pid']}" %>
|
28
|
-
|
28
|
+
<span class="label label-success"><%= process.tag %></span>
|
29
|
+
<% process.labels.each do |label| %>
|
29
30
|
<span class="label label-info"><%= label %></span>
|
30
31
|
<% end %>
|
31
32
|
</td>
|
data/web/views/dashboard.erb
CHANGED
@@ -15,18 +15,23 @@
|
|
15
15
|
</div>
|
16
16
|
</div>
|
17
17
|
|
18
|
-
<div
|
19
|
-
<div id="realtime-
|
18
|
+
<div class="row">
|
19
|
+
<div id="realtime" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>"></div>
|
20
|
+
<div id="realtime-legend"></div>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div class="row">
|
24
|
+
<h5>
|
25
|
+
<span class="history-heading"><%= t('History') %></span>
|
26
|
+
<a href="<%= root_path %>?days=7" class="history-graph <%= "active" if params[:days] == "7" %>"><%= t('OneWeek') %></a>
|
27
|
+
<a href="<%= root_path %>" class="history-graph <%= "active" if params[:days].nil? || params[:days] == "30" %>"><%= t('OneMonth') %></a>
|
28
|
+
<a href="<%= root_path %>?days=90" class="history-graph <%= "active" if params[:days] == "90" %>"><%= t('ThreeMonths') %></a>
|
29
|
+
<a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
|
30
|
+
</h5>
|
20
31
|
|
21
|
-
<
|
22
|
-
<
|
23
|
-
|
24
|
-
<a href="<%= root_path %>" class="history-graph <%= "active" if params[:days].nil? || params[:days] == "30" %>" ><%= t('OneMonth') %></a>
|
25
|
-
<a href="<%= root_path %>?days=90" class="history-graph <%= "active" if params[:days] == "90" %>"><%= t('ThreeMonths') %></a>
|
26
|
-
<a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
|
27
|
-
</h5>
|
28
|
-
<div id="history" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>" data-processed="<%= h Sidekiq.dump_json(@processed_history) %>" data-failed="<%= h Sidekiq.dump_json(@failed_history) %>" data-update-url="<%= root_path %>dashboard/stats"></div>
|
29
|
-
<div id="history-legend"></div>
|
32
|
+
<div id="history" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>" data-processed="<%= h Sidekiq.dump_json(@processed_history) %>" data-failed="<%= h Sidekiq.dump_json(@failed_history) %>" data-update-url="<%= root_path %>dashboard/stats"></div>
|
33
|
+
<div id="history-legend"></div>
|
34
|
+
</div>
|
30
35
|
|
31
36
|
<br/>
|
32
37
|
<h5>Redis</h5>
|
data/web/views/layout.erb
CHANGED
@@ -7,13 +7,10 @@
|
|
7
7
|
<link href="<%= root_path %>stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
|
8
8
|
<script type="text/javascript" src="<%= root_path %>javascripts/application.js"></script>
|
9
9
|
<script type="text/javascript" src="<%= root_path %>javascripts/locales/jquery.timeago.<%= locale %>.js"></script>
|
10
|
-
<meta name="google"
|
10
|
+
<meta name="google" content="notranslate" />
|
11
11
|
</head>
|
12
12
|
<body class="admin">
|
13
|
-
|
14
|
-
<%= erb :_nav %>
|
15
|
-
</div>
|
16
|
-
|
13
|
+
<%= erb :_nav %>
|
17
14
|
<div id="page">
|
18
15
|
<div class="container">
|
19
16
|
<div class="row">
|
@@ -27,28 +24,6 @@
|
|
27
24
|
</div>
|
28
25
|
</div>
|
29
26
|
</div>
|
30
|
-
|
31
|
-
<div class="navbar navbar-fixed-bottom navbar-inverse">
|
32
|
-
<div class="navbar-inner">
|
33
|
-
<div class="container">
|
34
|
-
<ul class="nav">
|
35
|
-
<li>
|
36
|
-
<p class="navbar-text" style="color:white;">Sidekiq v<%= Sidekiq::VERSION %></p>
|
37
|
-
</li>
|
38
|
-
<li>
|
39
|
-
<p class="navbar-text">Redis: <%= redis_connection %></p>
|
40
|
-
</li>
|
41
|
-
<li>
|
42
|
-
<p class="navbar-text"><%= t('Time') %>: <%= Time.now.utc.strftime('%H:%M:%S UTC') %></p>
|
43
|
-
</li>
|
44
|
-
<% if namespace %>
|
45
|
-
<li>
|
46
|
-
<p class="navbar-text"><%= t('Namespace') %>: <%= namespace %></p>
|
47
|
-
</li>
|
48
|
-
<% end %>
|
49
|
-
</ul>
|
50
|
-
</div>
|
51
|
-
</div>
|
52
|
-
</div>
|
27
|
+
<%= erb :_footer %>
|
53
28
|
</body>
|
54
29
|
</html>
|
data/web/views/retries.erb
CHANGED
@@ -54,6 +54,7 @@
|
|
54
54
|
</table>
|
55
55
|
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="<%= t('RetryNow') %>" />
|
56
56
|
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="<%= t('Delete') %>" />
|
57
|
+
<input class="btn btn-danger btn-xs pull-left" type="submit" name="kill" value="<%= t('Kill') %>" />
|
57
58
|
</form>
|
58
59
|
|
59
60
|
<form action="<%= root_path %>retries/all/delete" method="post">
|
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.2.
|
4
|
+
version: 3.2.2
|
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-
|
11
|
+
date: 2014-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -302,6 +302,7 @@ files:
|
|
302
302
|
- web/locales/sv.yml
|
303
303
|
- web/locales/zh-cn.yml
|
304
304
|
- web/locales/zh-tw.yml
|
305
|
+
- web/views/_footer.erb
|
305
306
|
- web/views/_job_info.erb
|
306
307
|
- web/views/_nav.erb
|
307
308
|
- web/views/_paging.erb
|