sidekiq 6.1.0 → 6.2.1
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/Changes.md +64 -2
- data/README.md +1 -2
- data/lib/sidekiq.rb +1 -1
- data/lib/sidekiq/api.rb +27 -9
- data/lib/sidekiq/cli.rb +20 -12
- data/lib/sidekiq/client.rb +1 -5
- data/lib/sidekiq/extensions/action_mailer.rb +3 -2
- data/lib/sidekiq/extensions/active_record.rb +1 -1
- data/lib/sidekiq/fetch.rb +9 -3
- data/lib/sidekiq/job_retry.rb +1 -0
- data/lib/sidekiq/launcher.rb +58 -1
- data/lib/sidekiq/logger.rb +3 -2
- data/lib/sidekiq/manager.rb +1 -1
- data/lib/sidekiq/middleware/chain.rb +1 -1
- data/lib/sidekiq/util.rb +28 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +33 -78
- data/lib/sidekiq/web/action.rb +1 -1
- data/lib/sidekiq/web/application.rb +12 -6
- data/lib/sidekiq/web/csrf_protection.rb +30 -3
- data/lib/sidekiq/web/helpers.rb +23 -2
- data/lib/sidekiq/web/router.rb +4 -1
- data/sidekiq.gemspec +10 -2
- data/web/assets/images/apple-touch-icon.png +0 -0
- data/web/assets/javascripts/application.js +1 -6
- data/web/assets/stylesheets/application-dark.css +59 -32
- data/web/assets/stylesheets/application.css +19 -8
- data/web/locales/fr.yml +1 -1
- data/web/locales/ru.yml +4 -0
- data/web/views/busy.erb +47 -16
- data/web/views/layout.erb +1 -0
- data/web/views/morgue.erb +1 -1
- data/web/views/queue.erb +1 -1
- data/web/views/queues.erb +1 -1
- data/web/views/retries.erb +1 -1
- data/web/views/scheduled.erb +1 -1
- metadata +14 -29
- data/.circleci/config.yml +0 -71
- data/.github/contributing.md +0 -32
- data/.github/issue_template.md +0 -11
- data/.gitignore +0 -13
- data/.standard.yml +0 -20
- data/3.0-Upgrade.md +0 -70
- data/4.0-Upgrade.md +0 -53
- data/5.0-Upgrade.md +0 -56
- data/6.0-Upgrade.md +0 -72
- data/COMM-LICENSE +0 -97
- data/Ent-2.0-Upgrade.md +0 -37
- data/Ent-Changes.md +0 -269
- data/Gemfile +0 -24
- data/Gemfile.lock +0 -208
- data/Pro-2.0-Upgrade.md +0 -138
- data/Pro-3.0-Upgrade.md +0 -44
- data/Pro-4.0-Upgrade.md +0 -35
- data/Pro-5.0-Upgrade.md +0 -25
- data/Pro-Changes.md +0 -790
- data/Rakefile +0 -10
- data/code_of_conduct.md +0 -50
data/lib/sidekiq/manager.rb
CHANGED
data/lib/sidekiq/util.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "forwardable"
|
3
4
|
require "socket"
|
4
5
|
require "securerandom"
|
5
6
|
require "sidekiq/exception_handler"
|
@@ -8,6 +9,33 @@ module Sidekiq
|
|
8
9
|
##
|
9
10
|
# This module is part of Sidekiq core and not intended for extensions.
|
10
11
|
#
|
12
|
+
|
13
|
+
class RingBuffer
|
14
|
+
include Enumerable
|
15
|
+
extend Forwardable
|
16
|
+
def_delegators :@buf, :[], :each, :size
|
17
|
+
|
18
|
+
def initialize(size, default = 0)
|
19
|
+
@size = size
|
20
|
+
@buf = Array.new(size, default)
|
21
|
+
@index = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def <<(element)
|
25
|
+
@buf[@index % @size] = element
|
26
|
+
@index += 1
|
27
|
+
element
|
28
|
+
end
|
29
|
+
|
30
|
+
def buffer
|
31
|
+
@buf
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset(default = 0)
|
35
|
+
@buf.fill(default)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
11
39
|
module Util
|
12
40
|
include ExceptionHandler
|
13
41
|
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web.rb
CHANGED
@@ -13,10 +13,8 @@ require "sidekiq/web/application"
|
|
13
13
|
require "sidekiq/web/csrf_protection"
|
14
14
|
|
15
15
|
require "rack/content_length"
|
16
|
-
|
17
16
|
require "rack/builder"
|
18
|
-
require "rack/
|
19
|
-
require "rack/session/cookie"
|
17
|
+
require "rack/static"
|
20
18
|
|
21
19
|
module Sidekiq
|
22
20
|
class Web
|
@@ -40,14 +38,6 @@ module Sidekiq
|
|
40
38
|
self
|
41
39
|
end
|
42
40
|
|
43
|
-
def middlewares
|
44
|
-
@middlewares ||= []
|
45
|
-
end
|
46
|
-
|
47
|
-
def use(*middleware_args, &block)
|
48
|
-
middlewares << [middleware_args, block]
|
49
|
-
end
|
50
|
-
|
51
41
|
def default_tabs
|
52
42
|
DEFAULT_TABS
|
53
43
|
end
|
@@ -73,32 +63,45 @@ module Sidekiq
|
|
73
63
|
opts.each { |key| set(key, false) }
|
74
64
|
end
|
75
65
|
|
76
|
-
|
66
|
+
def middlewares
|
67
|
+
@middlewares ||= []
|
68
|
+
end
|
69
|
+
|
70
|
+
def use(*args, &block)
|
71
|
+
middlewares << [args, block]
|
72
|
+
end
|
73
|
+
|
77
74
|
def set(attribute, value)
|
78
75
|
send(:"#{attribute}=", value)
|
79
76
|
end
|
80
77
|
|
81
|
-
|
78
|
+
def sessions=(val)
|
79
|
+
puts "WARNING: Sidekiq::Web.sessions= is no longer relevant and will be removed in Sidekiq 7.0. #{caller(1..1).first}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def session_secret=(val)
|
83
|
+
puts "WARNING: Sidekiq::Web.session_secret= is no longer relevant and will be removed in Sidekiq 7.0. #{caller(1..1).first}"
|
84
|
+
end
|
85
|
+
|
86
|
+
attr_accessor :app_url, :redis_pool
|
82
87
|
attr_writer :locales, :views
|
83
88
|
end
|
84
89
|
|
85
90
|
def self.inherited(child)
|
86
91
|
child.app_url = app_url
|
87
|
-
child.session_secret = session_secret
|
88
92
|
child.redis_pool = redis_pool
|
89
|
-
child.sessions = sessions
|
90
93
|
end
|
91
94
|
|
92
95
|
def settings
|
93
96
|
self.class.settings
|
94
97
|
end
|
95
98
|
|
96
|
-
def
|
97
|
-
middlewares
|
99
|
+
def middlewares
|
100
|
+
@middlewares ||= self.class.middlewares
|
98
101
|
end
|
99
102
|
|
100
|
-
def
|
101
|
-
|
103
|
+
def use(*args, &block)
|
104
|
+
middlewares << [args, block]
|
102
105
|
end
|
103
106
|
|
104
107
|
def call(env)
|
@@ -126,18 +129,8 @@ module Sidekiq
|
|
126
129
|
send(:"#{attribute}=", value)
|
127
130
|
end
|
128
131
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
attr_writer :sessions
|
133
|
-
|
134
|
-
def sessions
|
135
|
-
unless instance_variable_defined?("@sessions")
|
136
|
-
@sessions = self.class.sessions
|
137
|
-
@sessions = @sessions.to_hash.dup if @sessions.respond_to?(:to_hash)
|
138
|
-
end
|
139
|
-
|
140
|
-
@sessions
|
132
|
+
def sessions=(val)
|
133
|
+
puts "Sidekiq::Web#sessions= is no longer relevant and will be removed in Sidekiq 7.0. #{caller[2..2].first}"
|
141
134
|
end
|
142
135
|
|
143
136
|
def self.register(extension)
|
@@ -146,57 +139,19 @@ module Sidekiq
|
|
146
139
|
|
147
140
|
private
|
148
141
|
|
149
|
-
def using?(middleware)
|
150
|
-
middlewares.any? do |(m, _)|
|
151
|
-
m.is_a?(Array) && (m[0] == middleware || m[0].is_a?(middleware))
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def build_sessions
|
156
|
-
middlewares = self.middlewares
|
157
|
-
|
158
|
-
s = sessions
|
159
|
-
|
160
|
-
# turn on CSRF protection if sessions are enabled and this is not the test env
|
161
|
-
if s && !using?(CsrfProtection) && ENV["RACK_ENV"] != "test"
|
162
|
-
middlewares.unshift [[CsrfProtection], nil]
|
163
|
-
end
|
164
|
-
|
165
|
-
if s && !using?(::Rack::Session::Cookie)
|
166
|
-
unless (secret = Web.session_secret)
|
167
|
-
require "securerandom"
|
168
|
-
secret = SecureRandom.hex(64)
|
169
|
-
end
|
170
|
-
|
171
|
-
options = {secret: secret}
|
172
|
-
options = options.merge(s.to_hash) if s.respond_to? :to_hash
|
173
|
-
|
174
|
-
middlewares.unshift [[::Rack::Session::Cookie, options], nil]
|
175
|
-
end
|
176
|
-
|
177
|
-
# Since Sidekiq::WebApplication no longer calculates its own
|
178
|
-
# Content-Length response header, we must ensure that the Rack middleware
|
179
|
-
# that does this is loaded
|
180
|
-
unless using? ::Rack::ContentLength
|
181
|
-
middlewares.unshift [[::Rack::ContentLength], nil]
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
142
|
def build
|
186
|
-
build_sessions
|
187
|
-
|
188
|
-
middlewares = self.middlewares
|
189
143
|
klass = self.class
|
144
|
+
m = middlewares
|
190
145
|
|
191
146
|
::Rack::Builder.new do
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
147
|
+
use Rack::Static, urls: ["/stylesheets", "/images", "/javascripts"],
|
148
|
+
root: ASSETS,
|
149
|
+
cascade: true,
|
150
|
+
header_rules: [
|
151
|
+
[:all, {"Cache-Control" => "public, max-age=86400"}]
|
152
|
+
]
|
153
|
+
m.each { |middleware, block| use(*middleware, &block) }
|
154
|
+
use Sidekiq::Web::CsrfProtection unless $TESTING
|
200
155
|
run WebApplication.new(klass)
|
201
156
|
end
|
202
157
|
end
|
data/lib/sidekiq/web/action.rb
CHANGED
@@ -4,7 +4,6 @@ module Sidekiq
|
|
4
4
|
class WebApplication
|
5
5
|
extend WebRouter
|
6
6
|
|
7
|
-
CONTENT_LENGTH = "Content-Length"
|
8
7
|
REDIS_KEYS = %w[redis_version uptime_in_days connected_clients used_memory_human used_memory_peak_human]
|
9
8
|
CSP_HEADER = [
|
10
9
|
"default-src 'self' https: http:",
|
@@ -42,6 +41,13 @@ module Sidekiq
|
|
42
41
|
# nothing, backwards compatibility
|
43
42
|
end
|
44
43
|
|
44
|
+
head "/" do
|
45
|
+
# HEAD / is the cheapest heartbeat possible,
|
46
|
+
# it hits Redis to ensure connectivity
|
47
|
+
Sidekiq.redis { |c| c.llen("queue:default") }
|
48
|
+
""
|
49
|
+
end
|
50
|
+
|
45
51
|
get "/" do
|
46
52
|
@redis_info = redis_info.select { |k, v| REDIS_KEYS.include? k }
|
47
53
|
stats_history = Sidekiq::Stats::History.new((params["days"] || 30).to_i)
|
@@ -76,10 +82,12 @@ module Sidekiq
|
|
76
82
|
erb(:queues)
|
77
83
|
end
|
78
84
|
|
85
|
+
QUEUE_NAME = /\A[a-z_:.\-0-9]+\z/i
|
86
|
+
|
79
87
|
get "/queues/:name" do
|
80
88
|
@name = route_params[:name]
|
81
89
|
|
82
|
-
halt(404)
|
90
|
+
halt(404) if !@name || @name !~ QUEUE_NAME
|
83
91
|
|
84
92
|
@count = (params["count"] || 25).to_i
|
85
93
|
@queue = Sidekiq::Queue.new(@name)
|
@@ -298,7 +306,7 @@ module Sidekiq
|
|
298
306
|
self.class.run_afters(app, action)
|
299
307
|
end
|
300
308
|
|
301
|
-
|
309
|
+
case resp
|
302
310
|
when Array
|
303
311
|
# redirects go here
|
304
312
|
resp
|
@@ -313,12 +321,10 @@ module Sidekiq
|
|
313
321
|
# we'll let Rack calculate Content-Length for us.
|
314
322
|
[200, headers, [resp]]
|
315
323
|
end
|
316
|
-
|
317
|
-
resp
|
318
324
|
end
|
319
325
|
|
320
326
|
def self.helpers(mod = nil, &block)
|
321
|
-
if
|
327
|
+
if block
|
322
328
|
WebAction.class_eval(&block)
|
323
329
|
else
|
324
330
|
WebAction.send(:include, mod)
|
@@ -66,13 +66,37 @@ module Sidekiq
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def session(env)
|
69
|
-
env["rack.session"] || fail(
|
69
|
+
env["rack.session"] || fail(<<~EOM)
|
70
|
+
Sidekiq::Web needs a valid Rack session for CSRF protection. If this is a Rails app,
|
71
|
+
make sure you mount Sidekiq::Web *inside* your application routes:
|
72
|
+
|
73
|
+
|
74
|
+
Rails.application.routes.draw do
|
75
|
+
mount Sidekiq::Web => "/sidekiq"
|
76
|
+
....
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
If this is a Rails app in API mode, you need to enable sessions.
|
81
|
+
|
82
|
+
https://guides.rubyonrails.org/api_app.html#using-session-middlewares
|
83
|
+
|
84
|
+
If this is a bare Rack app, use a session middleware before Sidekiq::Web:
|
85
|
+
|
86
|
+
# first, use IRB to create a shared secret key for sessions and commit it
|
87
|
+
require 'securerandom'; File.open(".session.key", "w") {|f| f.write(SecureRandom.hex(32)) }
|
88
|
+
|
89
|
+
# now use the secret with a session cookie middleware
|
90
|
+
use Rack::Session::Cookie, secret: File.read(".session.key"), same_site: true, max_age: 86400
|
91
|
+
run Sidekiq::Web
|
92
|
+
|
93
|
+
EOM
|
70
94
|
end
|
71
95
|
|
72
96
|
def accept?(env)
|
73
97
|
return true if safe?(env)
|
74
98
|
|
75
|
-
giventoken = Rack::Request.new(env).params["authenticity_token"]
|
99
|
+
giventoken = ::Rack::Request.new(env).params["authenticity_token"]
|
76
100
|
valid_token?(env, giventoken)
|
77
101
|
end
|
78
102
|
|
@@ -92,6 +116,9 @@ module Sidekiq
|
|
92
116
|
sess = session(env)
|
93
117
|
localtoken = sess[:csrf]
|
94
118
|
|
119
|
+
# Checks that Rack::Session::Cookie actualy contains the csrf toekn
|
120
|
+
return false if localtoken.nil?
|
121
|
+
|
95
122
|
# Rotate the session token after every use
|
96
123
|
sess[:csrf] = SecureRandom.base64(TOKEN_LENGTH)
|
97
124
|
|
@@ -138,7 +165,7 @@ module Sidekiq
|
|
138
165
|
end
|
139
166
|
|
140
167
|
def compare_with_real_token(token, local)
|
141
|
-
Rack::Utils.secure_compare(token.to_s, decode_token(local).to_s)
|
168
|
+
::Rack::Utils.secure_compare(token.to_s, decode_token(local).to_s)
|
142
169
|
end
|
143
170
|
|
144
171
|
def decode_token(token)
|
data/lib/sidekiq/web/helpers.rb
CHANGED
@@ -22,6 +22,14 @@ module Sidekiq
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def singularize(str, count)
|
26
|
+
if count == 1 && str.respond_to?(:singularize) # rails
|
27
|
+
str.singularize
|
28
|
+
else
|
29
|
+
str
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
25
33
|
def clear_caches
|
26
34
|
@strings = nil
|
27
35
|
@locale_files = nil
|
@@ -158,8 +166,7 @@ module Sidekiq
|
|
158
166
|
|
159
167
|
def redis_connection
|
160
168
|
Sidekiq.redis do |conn|
|
161
|
-
|
162
|
-
"redis://#{c[:location]}/#{c[:db]}"
|
169
|
+
conn.connection[:id]
|
163
170
|
end
|
164
171
|
end
|
165
172
|
|
@@ -258,7 +265,21 @@ module Sidekiq
|
|
258
265
|
end
|
259
266
|
end
|
260
267
|
|
268
|
+
def format_memory(rss_kb)
|
269
|
+
return "0" if rss_kb.nil? || rss_kb == 0
|
270
|
+
|
271
|
+
if rss_kb < 100_000
|
272
|
+
"#{number_with_delimiter(rss_kb)} KB"
|
273
|
+
elsif rss_kb < 10_000_000
|
274
|
+
"#{number_with_delimiter((rss_kb / 1024.0).to_i)} MB"
|
275
|
+
else
|
276
|
+
"#{number_with_delimiter((rss_kb / (1024.0 * 1024.0)).round(1))} GB"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
261
280
|
def number_with_delimiter(number)
|
281
|
+
return "" if number.nil?
|
282
|
+
|
262
283
|
begin
|
263
284
|
Float(number)
|
264
285
|
rescue ArgumentError, TypeError
|
data/lib/sidekiq/web/router.rb
CHANGED
@@ -15,6 +15,10 @@ module Sidekiq
|
|
15
15
|
REQUEST_METHOD = "REQUEST_METHOD"
|
16
16
|
PATH_INFO = "PATH_INFO"
|
17
17
|
|
18
|
+
def head(path, &block)
|
19
|
+
route(HEAD, path, &block)
|
20
|
+
end
|
21
|
+
|
18
22
|
def get(path, &block)
|
19
23
|
route(GET, path, &block)
|
20
24
|
end
|
@@ -39,7 +43,6 @@ module Sidekiq
|
|
39
43
|
@routes ||= {GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => []}
|
40
44
|
|
41
45
|
@routes[method] << WebRoute.new(method, path, block)
|
42
|
-
@routes[HEAD] << WebRoute.new(method, path, block) if method == GET
|
43
46
|
end
|
44
47
|
|
45
48
|
def match(env)
|
data/sidekiq.gemspec
CHANGED
@@ -5,15 +5,23 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.email = ["mperham@gmail.com"]
|
6
6
|
gem.summary = "Simple, efficient background processing for Ruby"
|
7
7
|
gem.description = "Simple, efficient background processing for Ruby."
|
8
|
-
gem.homepage = "
|
8
|
+
gem.homepage = "https://sidekiq.org"
|
9
9
|
gem.license = "LGPL-3.0"
|
10
10
|
|
11
11
|
gem.executables = ["sidekiq", "sidekiqmon"]
|
12
|
-
gem.files = `git ls-files | grep -
|
12
|
+
gem.files = ["sidekiq.gemspec", "README.md", "Changes.md", "LICENSE"] + `git ls-files | grep -E '^(bin|lib|web)'`.split("\n")
|
13
13
|
gem.name = "sidekiq"
|
14
14
|
gem.version = Sidekiq::VERSION
|
15
15
|
gem.required_ruby_version = ">= 2.5.0"
|
16
16
|
|
17
|
+
gem.metadata = {
|
18
|
+
"homepage_uri" => "https://sidekiq.org",
|
19
|
+
"bug_tracker_uri" => "https://github.com/mperham/sidekiq/issues",
|
20
|
+
"documentation_uri" => "https://github.com/mperham/sidekiq/wiki",
|
21
|
+
"changelog_uri" => "https://github.com/mperham/sidekiq/blob/master/Changes.md",
|
22
|
+
"source_code_uri" => "https://github.com/mperham/sidekiq"
|
23
|
+
}
|
24
|
+
|
17
25
|
gem.add_dependency "redis", ">= 4.2.0"
|
18
26
|
gem.add_dependency "connection_pool", ">= 2.2.2"
|
19
27
|
gem.add_dependency "rack", "~> 2.0"
|