sidekiq 5.2.2 → 5.2.9
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 +5 -5
- data/.circleci/config.yml +61 -0
- data/.gitignore +2 -0
- data/.travis.yml +2 -5
- data/COMM-LICENSE +11 -9
- data/Changes.md +50 -0
- data/Ent-Changes.md +18 -1
- data/Gemfile +15 -6
- data/Pro-Changes.md +13 -0
- data/README.md +1 -1
- data/Rakefile +2 -1
- data/bin/sidekiqctl +13 -92
- data/bin/sidekiqload +1 -1
- data/lib/sidekiq/cli.rb +57 -57
- data/lib/sidekiq/ctl.rb +221 -0
- data/lib/sidekiq/job_logger.rb +2 -2
- data/lib/sidekiq/job_retry.rb +33 -12
- data/lib/sidekiq/launcher.rb +1 -1
- data/lib/sidekiq/manager.rb +3 -3
- data/lib/sidekiq/middleware/server/active_record.rb +1 -1
- data/lib/sidekiq/processor.rb +24 -17
- data/lib/sidekiq/rails.rb +2 -1
- data/lib/sidekiq/redis_connection.rb +19 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +1 -1
- data/lib/sidekiq/web/helpers.rb +10 -3
- data/lib/sidekiq/worker.rb +24 -8
- data/lib/sidekiq.rb +4 -2
- data/sidekiq.gemspec +3 -5
- data/web/assets/javascripts/dashboard.js +15 -5
- data/web/assets/stylesheets/application.css +35 -2
- data/web/assets/stylesheets/bootstrap.css +1 -1
- data/web/views/_nav.erb +3 -17
- data/web/views/queues.erb +1 -1
- metadata +21 -6
data/lib/sidekiq/processor.rb
CHANGED
@@ -87,7 +87,7 @@ module Sidekiq
|
|
87
87
|
def get_one
|
88
88
|
begin
|
89
89
|
work = @strategy.retrieve_work
|
90
|
-
(logger.info { "Redis is online, #{
|
90
|
+
(logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }; @down = nil) if @down
|
91
91
|
work
|
92
92
|
rescue Sidekiq::Shutdown
|
93
93
|
rescue => ex
|
@@ -107,7 +107,7 @@ module Sidekiq
|
|
107
107
|
|
108
108
|
def handle_fetch_exception(ex)
|
109
109
|
if !@down
|
110
|
-
@down =
|
110
|
+
@down = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
111
111
|
logger.error("Error fetching job: #{ex}")
|
112
112
|
handle_exception(ex)
|
113
113
|
end
|
@@ -147,21 +147,19 @@ module Sidekiq
|
|
147
147
|
jobstr = work.job
|
148
148
|
queue = work.queue_name
|
149
149
|
|
150
|
-
|
150
|
+
# Treat malformed JSON as a special case: job goes straight to the morgue.
|
151
|
+
job_hash = nil
|
151
152
|
begin
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
DeadSet.new.kill(jobstr, notify_failure: false)
|
160
|
-
ack = true
|
161
|
-
raise
|
162
|
-
end
|
153
|
+
job_hash = Sidekiq.load_json(jobstr)
|
154
|
+
rescue => ex
|
155
|
+
handle_exception(ex, { :context => "Invalid JSON for job", :jobstr => jobstr })
|
156
|
+
# we can't notify because the job isn't a valid hash payload.
|
157
|
+
DeadSet.new.kill(jobstr, notify_failure: false)
|
158
|
+
return work.acknowledge
|
159
|
+
end
|
163
160
|
|
164
|
-
|
161
|
+
ack = true
|
162
|
+
begin
|
165
163
|
dispatch(job_hash, queue) do |worker|
|
166
164
|
Sidekiq.server_middleware.invoke(worker, job_hash, queue) do
|
167
165
|
execute_job(worker, cloned(job_hash['args']))
|
@@ -172,10 +170,19 @@ module Sidekiq
|
|
172
170
|
# within the timeout. Don't acknowledge the work since
|
173
171
|
# we didn't properly finish it.
|
174
172
|
ack = false
|
175
|
-
rescue
|
176
|
-
|
173
|
+
rescue Sidekiq::JobRetry::Handled => h
|
174
|
+
# this is the common case: job raised error and Sidekiq::JobRetry::Handled
|
175
|
+
# signals that we created a retry successfully. We can acknowlege the job.
|
176
|
+
e = h.cause ? h.cause : h
|
177
177
|
handle_exception(e, { :context => "Job raised exception", :job => job_hash, :jobstr => jobstr })
|
178
178
|
raise e
|
179
|
+
rescue Exception => ex
|
180
|
+
# Unexpected error! This is very bad and indicates an exception that got past
|
181
|
+
# the retry subsystem (e.g. network partition). We won't acknowledge the job
|
182
|
+
# so it can be rescued when using Sidekiq Pro.
|
183
|
+
ack = false
|
184
|
+
handle_exception(ex, { :context => "Internal exception!", :job => job_hash, :jobstr => jobstr })
|
185
|
+
raise e
|
179
186
|
ensure
|
180
187
|
work.acknowledge if ack
|
181
188
|
end
|
data/lib/sidekiq/rails.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Sidekiq
|
3
4
|
class Rails < ::Rails::Engine
|
4
5
|
# We need to setup this up before any application configuration which might
|
@@ -54,4 +55,4 @@ if defined?(::Rails) && ::Rails::VERSION::MAJOR < 4
|
|
54
55
|
$stderr.puts("**************************************************")
|
55
56
|
$stderr.puts("⛔️ WARNING: Sidekiq server is no longer supported by Rails 3.2 - please ensure your server/workers are updated")
|
56
57
|
$stderr.puts("**************************************************")
|
57
|
-
end
|
58
|
+
end
|
@@ -115,6 +115,25 @@ module Sidekiq
|
|
115
115
|
# REDIS_PROVIDER=MY_REDIS_URL
|
116
116
|
# and Sidekiq will find your custom URL variable with no custom
|
117
117
|
# initialization code at all.
|
118
|
+
p = ENV['REDIS_PROVIDER']
|
119
|
+
if p && p =~ /\:/
|
120
|
+
Sidekiq.logger.error <<-EOM
|
121
|
+
|
122
|
+
#################################################################################
|
123
|
+
|
124
|
+
REDIS_PROVIDER should be set to the **name** of the variable which contains the Redis URL, not a URL itself.
|
125
|
+
Platforms like Heroku sell addons that publish a *_URL variable. You tell Sidekiq with REDIS_PROVIDER, e.g.:
|
126
|
+
|
127
|
+
REDIS_PROVIDER=REDISTOGO_URL
|
128
|
+
REDISTOGO_URL=redis://somehost.example.com:6379/4
|
129
|
+
|
130
|
+
Use REDIS_URL if you wish to point Sidekiq to a URL directly.
|
131
|
+
|
132
|
+
This configuration error will crash starting in Sidekiq 5.3.
|
133
|
+
|
134
|
+
#################################################################################
|
135
|
+
EOM
|
136
|
+
end
|
118
137
|
ENV[
|
119
138
|
ENV['REDIS_PROVIDER'] || 'REDIS_URL'
|
120
139
|
]
|
data/lib/sidekiq/version.rb
CHANGED
@@ -17,7 +17,7 @@ module Sidekiq
|
|
17
17
|
"manifest-src 'self'",
|
18
18
|
"media-src 'self'",
|
19
19
|
"object-src 'none'",
|
20
|
-
"script-src 'self' https: http:",
|
20
|
+
"script-src 'self' https: http: 'unsafe-inline'",
|
21
21
|
"style-src 'self' https: http: 'unsafe-inline'",
|
22
22
|
"worker-src 'self'",
|
23
23
|
"base-uri 'self'"
|
data/lib/sidekiq/web/helpers.rb
CHANGED
@@ -207,9 +207,16 @@ module Sidekiq
|
|
207
207
|
end
|
208
208
|
|
209
209
|
def display_args(args, truncate_after_chars = 2000)
|
210
|
-
args
|
211
|
-
|
212
|
-
|
210
|
+
return "Invalid job payload, args is nil" if args == nil
|
211
|
+
return "Invalid job payload, args must be an Array, not #{args.class.name}" if !args.is_a?(Array)
|
212
|
+
|
213
|
+
begin
|
214
|
+
args.map do |arg|
|
215
|
+
h(truncate(to_display(arg), truncate_after_chars))
|
216
|
+
end.join(", ")
|
217
|
+
rescue
|
218
|
+
"Illegal job arguments: #{h args.inspect}"
|
219
|
+
end
|
213
220
|
end
|
214
221
|
|
215
222
|
def csrf_tag
|
data/lib/sidekiq/worker.rb
CHANGED
@@ -7,13 +7,13 @@ module Sidekiq
|
|
7
7
|
# Include this module in your worker class and you can easily create
|
8
8
|
# asynchronous jobs:
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# class HardWorker
|
11
|
+
# include Sidekiq::Worker
|
12
12
|
#
|
13
|
-
#
|
14
|
-
#
|
13
|
+
# def perform(*args)
|
14
|
+
# # do some work
|
15
|
+
# end
|
15
16
|
# end
|
16
|
-
# end
|
17
17
|
#
|
18
18
|
# Then in your Rails app, you can do this:
|
19
19
|
#
|
@@ -46,6 +46,11 @@ module Sidekiq
|
|
46
46
|
@opts = opts
|
47
47
|
end
|
48
48
|
|
49
|
+
def set(options)
|
50
|
+
@opts.merge!(options)
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
49
54
|
def perform_async(*args)
|
50
55
|
@klass.client_push(@opts.merge('args' => args, 'class' => @klass))
|
51
56
|
end
|
@@ -66,6 +71,7 @@ module Sidekiq
|
|
66
71
|
end
|
67
72
|
|
68
73
|
module ClassMethods
|
74
|
+
ACCESSOR_MUTEX = Mutex.new
|
69
75
|
|
70
76
|
def delay(*args)
|
71
77
|
raise ArgumentError, "Do not call .delay on a Sidekiq::Worker class, call .perform_async"
|
@@ -148,10 +154,18 @@ module Sidekiq
|
|
148
154
|
instance_writer = true
|
149
155
|
|
150
156
|
attrs.each do |name|
|
157
|
+
synchronized_getter = "__synchronized_#{name}"
|
158
|
+
|
151
159
|
singleton_class.instance_eval do
|
152
160
|
undef_method(name) if method_defined?(name) || private_method_defined?(name)
|
153
161
|
end
|
154
|
-
|
162
|
+
|
163
|
+
define_singleton_method(synchronized_getter) { nil }
|
164
|
+
singleton_class.class_eval do
|
165
|
+
private(synchronized_getter)
|
166
|
+
end
|
167
|
+
|
168
|
+
define_singleton_method(name) { ACCESSOR_MUTEX.synchronize { send synchronized_getter } }
|
155
169
|
|
156
170
|
ivar = "@#{name}"
|
157
171
|
|
@@ -161,8 +175,10 @@ module Sidekiq
|
|
161
175
|
end
|
162
176
|
define_singleton_method("#{name}=") do |val|
|
163
177
|
singleton_class.class_eval do
|
164
|
-
|
165
|
-
|
178
|
+
ACCESSOR_MUTEX.synchronize do
|
179
|
+
undef_method(synchronized_getter) if method_defined?(synchronized_getter) || private_method_defined?(synchronized_getter)
|
180
|
+
define_method(synchronized_getter) { val }
|
181
|
+
end
|
166
182
|
end
|
167
183
|
|
168
184
|
if singleton_class?
|
data/lib/sidekiq.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'sidekiq/version'
|
3
4
|
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.2.2." if RUBY_PLATFORM != 'java' && Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.2')
|
4
5
|
|
@@ -56,6 +57,7 @@ module Sidekiq
|
|
56
57
|
def self.options
|
57
58
|
@options ||= DEFAULTS.dup
|
58
59
|
end
|
60
|
+
|
59
61
|
def self.options=(opts)
|
60
62
|
@options = opts
|
61
63
|
end
|
@@ -94,8 +96,8 @@ module Sidekiq
|
|
94
96
|
begin
|
95
97
|
yield conn
|
96
98
|
rescue Redis::CommandError => ex
|
97
|
-
#2550 Failover can cause the server to become a
|
98
|
-
# to disconnect and reopen the socket to get back to the
|
99
|
+
#2550 Failover can cause the server to become a replica, need
|
100
|
+
# to disconnect and reopen the socket to get back to the primary.
|
99
101
|
(conn.disconnect!; retryable = false; retry) if retryable && ex.message =~ /READONLY/
|
100
102
|
raise
|
101
103
|
end
|
data/sidekiq.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
require File.expand_path('../lib/sidekiq/version', __FILE__)
|
1
|
+
require_relative 'lib/sidekiq/version'
|
3
2
|
|
4
3
|
Gem::Specification.new do |gem|
|
5
4
|
gem.authors = ["Mike Perham"]
|
@@ -11,13 +10,12 @@ Gem::Specification.new do |gem|
|
|
11
10
|
|
12
11
|
gem.executables = ['sidekiq', 'sidekiqctl']
|
13
12
|
gem.files = `git ls-files | grep -Ev '^(test|myapp|examples)'`.split("\n")
|
14
|
-
gem.test_files = []
|
15
13
|
gem.name = "sidekiq"
|
16
|
-
gem.require_paths = ["lib"]
|
17
14
|
gem.version = Sidekiq::VERSION
|
18
15
|
gem.required_ruby_version = ">= 2.2.2"
|
19
16
|
|
20
|
-
gem.add_dependency 'redis', '>= 3.3.5', '<
|
17
|
+
gem.add_dependency 'redis', '>= 3.3.5', '< 4.2'
|
21
18
|
gem.add_dependency 'connection_pool', '~> 2.2', '>= 2.2.2'
|
19
|
+
gem.add_dependency 'rack', '~> 2.0'
|
22
20
|
gem.add_dependency 'rack-protection', '>= 1.5.0'
|
23
21
|
end
|
@@ -298,8 +298,18 @@ var debounce = function(fn, timeout)
|
|
298
298
|
}
|
299
299
|
};
|
300
300
|
|
301
|
-
window.onresize =
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
301
|
+
window.onresize = function() {
|
302
|
+
var prevWidth = window.innerWidth;
|
303
|
+
|
304
|
+
return debounce(function () {
|
305
|
+
var currWidth = window.innerWidth;
|
306
|
+
|
307
|
+
if (prevWidth !== currWidth) {
|
308
|
+
prevWidth = currWidth;
|
309
|
+
|
310
|
+
clearInterval(poller);
|
311
|
+
resetGraphs();
|
312
|
+
renderGraphs();
|
313
|
+
}
|
314
|
+
}, 125);
|
315
|
+
}();
|
@@ -126,7 +126,7 @@ header.row .pagination {
|
|
126
126
|
text-align: center;
|
127
127
|
width: 14%;
|
128
128
|
}
|
129
|
-
@media (max-width: 767px) and (min-width:
|
129
|
+
@media (max-width: 767px) and (min-width: 200px) {
|
130
130
|
.summary_bar ul li {
|
131
131
|
width: 100%;
|
132
132
|
}
|
@@ -219,6 +219,29 @@ table .table-checkbox label {
|
|
219
219
|
color: #585454;
|
220
220
|
}
|
221
221
|
|
222
|
+
|
223
|
+
.nav.navbar-nav{
|
224
|
+
display: flex;
|
225
|
+
width: 100%;
|
226
|
+
}
|
227
|
+
|
228
|
+
.navbar-livereload{
|
229
|
+
margin-left: auto;
|
230
|
+
white-space: nowrap;
|
231
|
+
}
|
232
|
+
|
233
|
+
.navbar-livereload .poll-wrapper a:last-child{
|
234
|
+
margin-left: 8px;
|
235
|
+
}
|
236
|
+
|
237
|
+
.navbar-right{
|
238
|
+
margin-right: 0;
|
239
|
+
}
|
240
|
+
|
241
|
+
.navbar-collapse.collapse{
|
242
|
+
overflow-x: auto !important;
|
243
|
+
}
|
244
|
+
|
222
245
|
@media (max-width: 768px) {
|
223
246
|
.navbar .navbar-header .navbar-livereload {
|
224
247
|
border: none;
|
@@ -234,13 +257,19 @@ table .table-checkbox label {
|
|
234
257
|
display: none;
|
235
258
|
}
|
236
259
|
|
260
|
+
.nav.navbar-nav{
|
261
|
+
display: block;
|
262
|
+
width: auto;
|
263
|
+
}
|
264
|
+
|
237
265
|
.navbar.navbar-fixed-top ul {
|
238
266
|
margin-right: -15px!important;
|
239
267
|
}
|
240
268
|
|
241
269
|
.navbar .nav a {
|
242
270
|
text-align: center;
|
243
|
-
}
|
271
|
+
}
|
272
|
+
|
244
273
|
}
|
245
274
|
|
246
275
|
@media (width: 768px) {
|
@@ -645,6 +674,10 @@ div.interval-slider input {
|
|
645
674
|
margin-right: 0;
|
646
675
|
}
|
647
676
|
|
677
|
+
.navbar #navbar-menu{
|
678
|
+
display: none;
|
679
|
+
}
|
680
|
+
|
648
681
|
.poll-wrapper {
|
649
682
|
width: 100%;
|
650
683
|
text-align: center;
|