sidekiq 6.5.12 → 7.0.0.beta1
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 +5 -24
- data/README.md +13 -12
- data/bin/sidekiq +3 -8
- data/bin/sidekiqload +14 -23
- data/lib/sidekiq/api.rb +51 -127
- data/lib/sidekiq/capsule.rb +110 -0
- data/lib/sidekiq/cli.rb +44 -59
- data/lib/sidekiq/client.rb +30 -17
- data/lib/sidekiq/component.rb +1 -0
- data/lib/sidekiq/config.rb +270 -0
- data/lib/sidekiq/deploy.rb +62 -0
- data/lib/sidekiq/embedded.rb +61 -0
- data/lib/sidekiq/fetch.rb +10 -11
- data/lib/sidekiq/job.rb +375 -10
- data/lib/sidekiq/job_logger.rb +1 -1
- data/lib/sidekiq/job_retry.rb +8 -8
- data/lib/sidekiq/job_util.rb +4 -4
- data/lib/sidekiq/launcher.rb +36 -46
- data/lib/sidekiq/logger.rb +1 -26
- data/lib/sidekiq/manager.rb +9 -11
- data/lib/sidekiq/metrics/query.rb +3 -3
- data/lib/sidekiq/metrics/shared.rb +4 -3
- data/lib/sidekiq/metrics/tracking.rb +18 -18
- data/lib/sidekiq/middleware/chain.rb +7 -9
- data/lib/sidekiq/middleware/current_attributes.rb +3 -8
- data/lib/sidekiq/monitor.rb +1 -1
- data/lib/sidekiq/paginator.rb +1 -9
- data/lib/sidekiq/pool.rb +7 -0
- data/lib/sidekiq/processor.rb +17 -26
- data/lib/sidekiq/rails.rb +11 -10
- data/lib/sidekiq/redis_client_adapter.rb +9 -45
- data/lib/sidekiq/redis_connection.rb +11 -111
- data/lib/sidekiq/scheduled.rb +19 -20
- data/lib/sidekiq/testing.rb +4 -32
- data/lib/sidekiq/transaction_aware_client.rb +4 -5
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +1 -4
- data/lib/sidekiq/web/csrf_protection.rb +1 -1
- data/lib/sidekiq/web/helpers.rb +21 -22
- data/lib/sidekiq/web.rb +2 -17
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +52 -274
- data/sidekiq.gemspec +29 -5
- data/web/assets/javascripts/application.js +0 -1
- data/web/assets/javascripts/base-charts.js +106 -0
- data/web/assets/javascripts/dashboard-charts.js +166 -0
- data/web/assets/javascripts/dashboard.js +3 -223
- data/web/assets/javascripts/metrics.js +90 -116
- data/web/assets/stylesheets/application-rtl.css +2 -91
- data/web/assets/stylesheets/application.css +21 -296
- data/web/locales/ar.yml +70 -70
- data/web/locales/cs.yml +62 -62
- data/web/locales/da.yml +52 -52
- data/web/locales/de.yml +65 -65
- data/web/locales/el.yml +2 -7
- data/web/locales/en.yml +76 -70
- data/web/locales/es.yml +68 -68
- data/web/locales/fa.yml +65 -65
- data/web/locales/fr.yml +67 -67
- data/web/locales/he.yml +65 -64
- data/web/locales/hi.yml +59 -59
- data/web/locales/it.yml +53 -53
- data/web/locales/ja.yml +64 -68
- data/web/locales/ko.yml +52 -52
- data/web/locales/lt.yml +66 -66
- data/web/locales/nb.yml +61 -61
- data/web/locales/nl.yml +52 -52
- data/web/locales/pl.yml +45 -45
- data/web/locales/pt-br.yml +59 -69
- data/web/locales/pt.yml +51 -51
- data/web/locales/ru.yml +67 -66
- data/web/locales/sv.yml +53 -53
- data/web/locales/ta.yml +60 -60
- data/web/locales/uk.yml +62 -61
- data/web/locales/ur.yml +64 -64
- data/web/locales/vi.yml +67 -67
- data/web/locales/zh-cn.yml +1 -0
- data/web/locales/zh-tw.yml +10 -1
- data/web/views/_footer.erb +5 -2
- data/web/views/busy.erb +1 -6
- data/web/views/dashboard.erb +36 -5
- data/web/views/metrics.erb +30 -19
- data/web/views/metrics_for_job.erb +16 -34
- metadata +60 -37
- data/lib/sidekiq/delay.rb +0 -43
- data/lib/sidekiq/extensions/action_mailer.rb +0 -48
- data/lib/sidekiq/extensions/active_record.rb +0 -43
- data/lib/sidekiq/extensions/class_methods.rb +0 -43
- data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
- data/lib/sidekiq/metrics/deploy.rb +0 -47
- data/lib/sidekiq/worker.rb +0 -370
- data/web/assets/javascripts/graph.js +0 -16
- /data/{LICENSE → LICENSE.txt} +0 -0
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "connection_pool"
|
4
3
|
require "redis_client"
|
5
4
|
require "redis_client/decorator"
|
6
|
-
require "uri"
|
7
5
|
|
8
6
|
module Sidekiq
|
9
7
|
class RedisClientAdapter
|
@@ -19,29 +17,10 @@ module Sidekiq
|
|
19
17
|
@client.call("EVALSHA", sha, keys.size, *keys, *argv)
|
20
18
|
end
|
21
19
|
|
22
|
-
def brpoplpush(*args)
|
23
|
-
@client.blocking_call(false, "BRPOPLPUSH", *args)
|
24
|
-
end
|
25
|
-
|
26
|
-
def brpop(*args)
|
27
|
-
@client.blocking_call(false, "BRPOP", *args)
|
28
|
-
end
|
29
|
-
|
30
|
-
def set(*args)
|
31
|
-
@client.call("SET", *args) { |r| r == "OK" }
|
32
|
-
end
|
33
|
-
ruby2_keywords :set if respond_to?(:ruby2_keywords, true)
|
34
|
-
|
35
|
-
def sismember(*args)
|
36
|
-
@client.call("SISMEMBER", *args) { |c| c > 0 }
|
37
|
-
end
|
38
|
-
|
39
|
-
def exists?(key)
|
40
|
-
@client.call("EXISTS", key) { |c| c > 0 }
|
41
|
-
end
|
42
|
-
|
43
20
|
private
|
44
21
|
|
22
|
+
# this allows us to use methods like `conn.hmset(...)` instead of having to use
|
23
|
+
# redis-client's native `conn.call("hmset", ...)`
|
45
24
|
def method_missing(*args, &block)
|
46
25
|
@client.call(*args, *block)
|
47
26
|
end
|
@@ -55,27 +34,15 @@ module Sidekiq
|
|
55
34
|
CompatClient = RedisClient::Decorator.create(CompatMethods)
|
56
35
|
|
57
36
|
class CompatClient
|
58
|
-
|
59
|
-
alias_method :"#{method}_each", method
|
60
|
-
undef_method method
|
61
|
-
end
|
62
|
-
|
63
|
-
def disconnect!
|
64
|
-
@client.close
|
65
|
-
end
|
66
|
-
|
67
|
-
def connection
|
68
|
-
{id: @client.id}
|
69
|
-
end
|
70
|
-
|
71
|
-
def redis
|
72
|
-
self
|
73
|
-
end
|
74
|
-
|
37
|
+
# underscore methods are not official API
|
75
38
|
def _client
|
76
39
|
@client
|
77
40
|
end
|
78
41
|
|
42
|
+
def _config
|
43
|
+
@client.config
|
44
|
+
end
|
45
|
+
|
79
46
|
def message
|
80
47
|
yield nil, @queue.pop
|
81
48
|
end
|
@@ -118,9 +85,8 @@ module Sidekiq
|
|
118
85
|
opts = options.dup
|
119
86
|
|
120
87
|
if opts[:namespace]
|
121
|
-
|
122
|
-
"Either use the redis adapter or remove the namespace."
|
123
|
-
Kernel.exit(-127)
|
88
|
+
raise ArgumentError, "Your Redis configuration uses the namespace '#{opts[:namespace]}' but this feature isn't supported by redis-client. " \
|
89
|
+
"Either use the redis adapter or remove the namespace."
|
124
90
|
end
|
125
91
|
|
126
92
|
opts.delete(:size)
|
@@ -150,5 +116,3 @@ module Sidekiq
|
|
150
116
|
end
|
151
117
|
end
|
152
118
|
end
|
153
|
-
|
154
|
-
Sidekiq::RedisConnection.adapter = Sidekiq::RedisClientAdapter
|
@@ -1,128 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "connection_pool"
|
4
|
-
require "redis"
|
5
4
|
require "uri"
|
5
|
+
require "sidekiq/redis_client_adapter"
|
6
6
|
|
7
7
|
module Sidekiq
|
8
8
|
module RedisConnection
|
9
|
-
class RedisAdapter
|
10
|
-
BaseError = Redis::BaseError
|
11
|
-
CommandError = Redis::CommandError
|
12
|
-
|
13
|
-
def initialize(options)
|
14
|
-
warn("Usage of the 'redis' gem within Sidekiq itself is deprecated, Sidekiq 7.0 will only use the new, simpler 'redis-client' gem", caller) if ENV["SIDEKIQ_REDIS_CLIENT"] == "1"
|
15
|
-
@options = options
|
16
|
-
end
|
17
|
-
|
18
|
-
def new_client
|
19
|
-
namespace = @options[:namespace]
|
20
|
-
|
21
|
-
client = Redis.new client_opts(@options)
|
22
|
-
if namespace
|
23
|
-
begin
|
24
|
-
require "redis/namespace"
|
25
|
-
Redis::Namespace.new(namespace, redis: client)
|
26
|
-
rescue LoadError
|
27
|
-
Sidekiq.logger.error("Your Redis configuration uses the namespace '#{namespace}' but the redis-namespace gem is not included in the Gemfile." \
|
28
|
-
"Add the gem to your Gemfile to continue using a namespace. Otherwise, remove the namespace parameter.")
|
29
|
-
exit(-127)
|
30
|
-
end
|
31
|
-
else
|
32
|
-
client
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def client_opts(options)
|
39
|
-
opts = options.dup
|
40
|
-
if opts[:namespace]
|
41
|
-
opts.delete(:namespace)
|
42
|
-
end
|
43
|
-
|
44
|
-
if opts[:network_timeout]
|
45
|
-
opts[:timeout] = opts[:network_timeout]
|
46
|
-
opts.delete(:network_timeout)
|
47
|
-
end
|
48
|
-
|
49
|
-
# Issue #3303, redis-rb will silently retry an operation.
|
50
|
-
# This can lead to duplicate jobs if Sidekiq::Client's LPUSH
|
51
|
-
# is performed twice but I believe this is much, much rarer
|
52
|
-
# than the reconnect silently fixing a problem; we keep it
|
53
|
-
# on by default.
|
54
|
-
opts[:reconnect_attempts] ||= 1
|
55
|
-
|
56
|
-
opts
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
@adapter = RedisAdapter
|
61
|
-
|
62
9
|
class << self
|
63
|
-
attr_reader :adapter
|
64
|
-
|
65
|
-
# RedisConnection.adapter = :redis
|
66
|
-
# RedisConnection.adapter = :redis_client
|
67
|
-
def adapter=(adapter)
|
68
|
-
raise "no" if adapter == self
|
69
|
-
result = case adapter
|
70
|
-
when :redis
|
71
|
-
RedisAdapter
|
72
|
-
when Class
|
73
|
-
adapter
|
74
|
-
else
|
75
|
-
require "sidekiq/#{adapter}_adapter"
|
76
|
-
nil
|
77
|
-
end
|
78
|
-
@adapter = result if result
|
79
|
-
end
|
80
|
-
|
81
10
|
def create(options = {})
|
82
11
|
symbolized_options = options.transform_keys(&:to_sym)
|
12
|
+
symbolized_options[:url] ||= determine_redis_provider
|
83
13
|
|
84
|
-
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
size = if symbolized_options[:size]
|
89
|
-
symbolized_options[:size]
|
90
|
-
elsif Sidekiq.server?
|
91
|
-
# Give ourselves plenty of connections. pool is lazy
|
92
|
-
# so we won't create them until we need them.
|
93
|
-
Sidekiq[:concurrency] + 5
|
94
|
-
elsif ENV["RAILS_MAX_THREADS"]
|
95
|
-
Integer(ENV["RAILS_MAX_THREADS"])
|
96
|
-
else
|
97
|
-
5
|
98
|
-
end
|
99
|
-
|
100
|
-
verify_sizing(size, Sidekiq[:concurrency]) if Sidekiq.server?
|
14
|
+
logger = symbolized_options.delete(:logger)
|
15
|
+
logger&.info { "Sidekiq #{Sidekiq::VERSION} connecting to Redis with options #{scrub(symbolized_options)}" }
|
101
16
|
|
102
|
-
|
103
|
-
|
17
|
+
size = symbolized_options.delete(:size) || 5
|
18
|
+
pool_timeout = symbolized_options.delete(:pool_timeout) || 1
|
19
|
+
pool_name = symbolized_options.delete(:pool_name)
|
104
20
|
|
105
|
-
redis_config =
|
106
|
-
ConnectionPool.new(timeout: pool_timeout, size: size) do
|
21
|
+
redis_config = Sidekiq::RedisClientAdapter.new(symbolized_options)
|
22
|
+
ConnectionPool.new(timeout: pool_timeout, size: size, name: pool_name) do
|
107
23
|
redis_config.new_client
|
108
24
|
end
|
109
25
|
end
|
110
26
|
|
111
27
|
private
|
112
28
|
|
113
|
-
|
114
|
-
#
|
115
|
-
# We need a connection for each Processor.
|
116
|
-
# We need a connection for Pro's real-time change listener
|
117
|
-
# We need a connection to various features to call Redis every few seconds:
|
118
|
-
# - the process heartbeat.
|
119
|
-
# - enterprise's leader election
|
120
|
-
# - enterprise's cron support
|
121
|
-
def verify_sizing(size, concurrency)
|
122
|
-
raise ArgumentError, "Your Redis connection pool is too small for Sidekiq. Your pool has #{size} connections but must have at least #{concurrency + 2}" if size < (concurrency + 2)
|
123
|
-
end
|
124
|
-
|
125
|
-
def log_info(options)
|
29
|
+
def scrub(options)
|
126
30
|
redacted = "REDACTED"
|
127
31
|
|
128
32
|
# Deep clone so we can muck with these options all we want and exclude
|
@@ -140,11 +44,7 @@ module Sidekiq
|
|
140
44
|
scrubbed_options[:sentinels]&.each do |sentinel|
|
141
45
|
sentinel[:password] = redacted if sentinel[:password]
|
142
46
|
end
|
143
|
-
|
144
|
-
Sidekiq.logger.info("Booting Sidekiq #{Sidekiq::VERSION} with #{adapter.name} options #{scrubbed_options}")
|
145
|
-
else
|
146
|
-
Sidekiq.logger.debug("#{Sidekiq::NAME} client with #{adapter.name} options #{scrubbed_options}")
|
147
|
-
end
|
47
|
+
scrubbed_options
|
148
48
|
end
|
149
49
|
|
150
50
|
def determine_redis_provider
|
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -8,6 +8,8 @@ module Sidekiq
|
|
8
8
|
SETS = %w[retry schedule]
|
9
9
|
|
10
10
|
class Enq
|
11
|
+
include Sidekiq::Component
|
12
|
+
|
11
13
|
LUA_ZPOPBYSCORE = <<~LUA
|
12
14
|
local key, now = KEYS[1], ARGV[1]
|
13
15
|
local jobs = redis.call("zrangebyscore", key, "-inf", now, "limit", 0, 1)
|
@@ -17,7 +19,9 @@ module Sidekiq
|
|
17
19
|
end
|
18
20
|
LUA
|
19
21
|
|
20
|
-
def initialize
|
22
|
+
def initialize(container)
|
23
|
+
@config = container
|
24
|
+
@client = Sidekiq::Client.new(config: container)
|
21
25
|
@done = false
|
22
26
|
@lua_zpopbyscore_sha = nil
|
23
27
|
end
|
@@ -25,15 +29,15 @@ module Sidekiq
|
|
25
29
|
def enqueue_jobs(sorted_sets = SETS)
|
26
30
|
# A job's "score" in Redis is the time at which it should be processed.
|
27
31
|
# Just check Redis for the set of jobs with a timestamp before now.
|
28
|
-
|
32
|
+
redis do |conn|
|
29
33
|
sorted_sets.each do |sorted_set|
|
30
34
|
# Get next item in the queue with score (time to execute) <= now.
|
31
35
|
# We need to go through the list one at a time to reduce the risk of something
|
32
36
|
# going wrong between the time jobs are popped from the scheduled queue and when
|
33
37
|
# they are pushed onto a work queue and losing the jobs.
|
34
38
|
while !@done && (job = zpopbyscore(conn, keys: [sorted_set], argv: [Time.now.to_f.to_s]))
|
35
|
-
|
36
|
-
|
39
|
+
@client.push(Sidekiq.load_json(job))
|
40
|
+
logger.debug { "enqueued #{sorted_set}: #{job}" }
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
@@ -47,12 +51,11 @@ module Sidekiq
|
|
47
51
|
|
48
52
|
def zpopbyscore(conn, keys: nil, argv: nil)
|
49
53
|
if @lua_zpopbyscore_sha.nil?
|
50
|
-
|
51
|
-
@lua_zpopbyscore_sha = raw_conn.script(:load, LUA_ZPOPBYSCORE)
|
54
|
+
@lua_zpopbyscore_sha = conn.script(:load, LUA_ZPOPBYSCORE)
|
52
55
|
end
|
53
56
|
|
54
57
|
conn.evalsha(@lua_zpopbyscore_sha, keys, argv)
|
55
|
-
rescue
|
58
|
+
rescue RedisClient::CommandError => e
|
56
59
|
raise unless e.message.start_with?("NOSCRIPT")
|
57
60
|
|
58
61
|
@lua_zpopbyscore_sha = nil
|
@@ -70,9 +73,9 @@ module Sidekiq
|
|
70
73
|
|
71
74
|
INITIAL_WAIT = 10
|
72
75
|
|
73
|
-
def initialize(
|
74
|
-
@config =
|
75
|
-
@enq = (
|
76
|
+
def initialize(config)
|
77
|
+
@config = config
|
78
|
+
@enq = (config[:scheduled_enq] || Sidekiq::Scheduled::Enq).new(config)
|
76
79
|
@sleeper = ConnectionPool::TimedStack.new
|
77
80
|
@done = false
|
78
81
|
@thread = nil
|
@@ -82,14 +85,10 @@ module Sidekiq
|
|
82
85
|
# Shut down this instance, will pause until the thread is dead.
|
83
86
|
def terminate
|
84
87
|
@done = true
|
85
|
-
@enq.terminate
|
88
|
+
@enq.terminate
|
86
89
|
|
87
|
-
|
88
|
-
|
89
|
-
@thread = nil
|
90
|
-
@sleeper << 0
|
91
|
-
t.value
|
92
|
-
end
|
90
|
+
@sleeper << 0
|
91
|
+
@thread&.value
|
93
92
|
end
|
94
93
|
|
95
94
|
def start
|
@@ -194,11 +193,11 @@ module Sidekiq
|
|
194
193
|
# should never depend on sidekiq/api.
|
195
194
|
def cleanup
|
196
195
|
# dont run cleanup more than once per minute
|
197
|
-
return 0 unless
|
196
|
+
return 0 unless redis { |conn| conn.set("process_cleanup", "1", nx: true, ex: 60) }
|
198
197
|
|
199
198
|
count = 0
|
200
|
-
|
201
|
-
procs = conn.
|
199
|
+
redis do |conn|
|
200
|
+
procs = conn.sscan("processes").to_a
|
202
201
|
heartbeats = conn.pipelined { |pipeline|
|
203
202
|
procs.each do |key|
|
204
203
|
pipeline.hget(key, "info")
|
data/lib/sidekiq/testing.rb
CHANGED
@@ -51,19 +51,10 @@ module Sidekiq
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def server_middleware
|
54
|
-
@server_chain ||= Middleware::Chain.new
|
54
|
+
@server_chain ||= Middleware::Chain.new(Sidekiq.default_configuration)
|
55
55
|
yield @server_chain if block_given?
|
56
56
|
@server_chain
|
57
57
|
end
|
58
|
-
|
59
|
-
def constantize(str)
|
60
|
-
names = str.split("::")
|
61
|
-
names.shift if names.empty? || names.first.empty?
|
62
|
-
|
63
|
-
names.inject(Object) do |constant, name|
|
64
|
-
constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
65
|
-
end
|
66
|
-
end
|
67
58
|
end
|
68
59
|
end
|
69
60
|
|
@@ -83,7 +74,7 @@ module Sidekiq
|
|
83
74
|
true
|
84
75
|
elsif Sidekiq::Testing.inline?
|
85
76
|
payloads.each do |job|
|
86
|
-
klass =
|
77
|
+
klass = Object.const_get(job["class"])
|
87
78
|
job["id"] ||= SecureRandom.hex(12)
|
88
79
|
job_hash = Sidekiq.load_json(Sidekiq.dump_json(job))
|
89
80
|
klass.process_job(job_hash)
|
@@ -218,26 +209,10 @@ module Sidekiq
|
|
218
209
|
# assert_equal 1, HardJob.jobs.size
|
219
210
|
# assert_equal :something, HardJob.jobs[0]['args'][0]
|
220
211
|
#
|
221
|
-
# assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
|
222
|
-
# MyMailer.delay.send_welcome_email('foo@example.com')
|
223
|
-
# assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
|
224
|
-
#
|
225
212
|
# You can also clear and drain all job types:
|
226
213
|
#
|
227
|
-
# assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
|
228
|
-
# assert_equal 0, Sidekiq::Extensions::DelayedModel.jobs.size
|
229
|
-
#
|
230
|
-
# MyMailer.delay.send_welcome_email('foo@example.com')
|
231
|
-
# MyModel.delay.do_something_hard
|
232
|
-
#
|
233
|
-
# assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
|
234
|
-
# assert_equal 1, Sidekiq::Extensions::DelayedModel.jobs.size
|
235
|
-
#
|
236
214
|
# Sidekiq::Worker.clear_all # or .drain_all
|
237
215
|
#
|
238
|
-
# assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
|
239
|
-
# assert_equal 0, Sidekiq::Extensions::DelayedModel.jobs.size
|
240
|
-
#
|
241
216
|
# This can be useful to make sure jobs don't linger between tests:
|
242
217
|
#
|
243
218
|
# RSpec.configure do |config|
|
@@ -318,7 +293,7 @@ module Sidekiq
|
|
318
293
|
job_classes = jobs.map { |job| job["class"] }.uniq
|
319
294
|
|
320
295
|
job_classes.each do |job_class|
|
321
|
-
|
296
|
+
Object.const_get(job_class).drain
|
322
297
|
end
|
323
298
|
end
|
324
299
|
end
|
@@ -329,13 +304,10 @@ module Sidekiq
|
|
329
304
|
def jobs_for(klass)
|
330
305
|
jobs.select do |job|
|
331
306
|
marshalled = job["args"][0]
|
332
|
-
marshalled.index(klass.to_s) && YAML.
|
307
|
+
marshalled.index(klass.to_s) && YAML.safe_load(marshalled)[0] == klass
|
333
308
|
end
|
334
309
|
end
|
335
310
|
end
|
336
|
-
|
337
|
-
Sidekiq::Extensions::DelayedMailer.extend(TestingExtensions) if defined?(Sidekiq::Extensions::DelayedMailer)
|
338
|
-
Sidekiq::Extensions::DelayedModel.extend(TestingExtensions) if defined?(Sidekiq::Extensions::DelayedModel)
|
339
311
|
end
|
340
312
|
|
341
313
|
if defined?(::Rails) && Rails.respond_to?(:env) && !Rails.env.test? && !$TESTING
|
@@ -5,8 +5,8 @@ require "sidekiq/client"
|
|
5
5
|
|
6
6
|
module Sidekiq
|
7
7
|
class TransactionAwareClient
|
8
|
-
def initialize(
|
9
|
-
@redis_client = Client.new(
|
8
|
+
def initialize(pool: nil, config: nil)
|
9
|
+
@redis_client = Client.new(pool: pool, config: config)
|
10
10
|
end
|
11
11
|
|
12
12
|
def push(item)
|
@@ -34,11 +34,10 @@ module Sidekiq
|
|
34
34
|
begin
|
35
35
|
require "after_commit_everywhere"
|
36
36
|
rescue LoadError
|
37
|
-
|
38
|
-
raise
|
37
|
+
raise %q(You need to add `gem "after_commit_everywhere"` to your Gemfile to use Sidekiq's transactional client)
|
39
38
|
end
|
40
39
|
|
41
|
-
default_job_options["client_class"] = Sidekiq::TransactionAwareClient
|
40
|
+
Sidekiq.default_job_options["client_class"] = Sidekiq::TransactionAwareClient
|
42
41
|
Sidekiq::JobUtil::TRANSIENT_ATTRIBUTES << "client_class"
|
43
42
|
true
|
44
43
|
end
|
data/lib/sidekiq/version.rb
CHANGED
@@ -74,9 +74,6 @@ module Sidekiq
|
|
74
74
|
end
|
75
75
|
|
76
76
|
get "/busy" do
|
77
|
-
@count = (params["count"] || 100).to_i
|
78
|
-
(@current_page, @total_size, @workset) = page_items(workset, params["page"], @count)
|
79
|
-
|
80
77
|
erb(:busy)
|
81
78
|
end
|
82
79
|
|
@@ -310,7 +307,7 @@ module Sidekiq
|
|
310
307
|
end
|
311
308
|
|
312
309
|
get "/stats/queues" do
|
313
|
-
json Sidekiq::Stats
|
310
|
+
json Sidekiq::Stats.new.queues
|
314
311
|
end
|
315
312
|
|
316
313
|
def call(env)
|
@@ -152,7 +152,7 @@ module Sidekiq
|
|
152
152
|
# value and decrypt it
|
153
153
|
token_length = masked_token.length / 2
|
154
154
|
one_time_pad = masked_token[0...token_length]
|
155
|
-
encrypted_token = masked_token[token_length
|
155
|
+
encrypted_token = masked_token[token_length..]
|
156
156
|
xor_byte_strings(one_time_pad, encrypted_token)
|
157
157
|
end
|
158
158
|
|
data/lib/sidekiq/web/helpers.rb
CHANGED
@@ -137,7 +137,7 @@ module Sidekiq
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def sort_direction_label
|
140
|
-
|
140
|
+
params[:direction] == "asc" ? "↑" : "↓"
|
141
141
|
end
|
142
142
|
|
143
143
|
def workset
|
@@ -148,15 +148,25 @@ module Sidekiq
|
|
148
148
|
@processes ||= Sidekiq::ProcessSet.new
|
149
149
|
end
|
150
150
|
|
151
|
-
# Sorts processes by hostname following the natural sort order
|
151
|
+
# Sorts processes by hostname following the natural sort order so that
|
152
|
+
# 'worker.1' < 'worker.2' < 'worker.10' < 'worker.20'
|
153
|
+
# '2.1.1.1' < '192.168.0.2' < '192.168.0.10'
|
152
154
|
def sorted_processes
|
153
155
|
@sorted_processes ||= begin
|
154
156
|
return processes unless processes.all? { |p| p["hostname"] }
|
155
157
|
|
158
|
+
split_characters = /[._-]+/
|
159
|
+
|
160
|
+
padding = processes.flat_map { |p| p["hostname"].split(split_characters) }.map(&:size).max
|
161
|
+
|
156
162
|
processes.to_a.sort_by do |process|
|
157
|
-
|
158
|
-
|
159
|
-
|
163
|
+
process["hostname"].split(split_characters).map do |substring|
|
164
|
+
# Left-pad the substring with '0' if it starts with a number or 'a'
|
165
|
+
# otherwise, so that '25' < 192' < 'a' ('025' < '192' < 'aaa')
|
166
|
+
padding_char = substring[0].match?(/\d/) ? "0" : "a"
|
167
|
+
|
168
|
+
substring.rjust(padding, padding_char)
|
169
|
+
end
|
160
170
|
end
|
161
171
|
end
|
162
172
|
end
|
@@ -165,18 +175,14 @@ module Sidekiq
|
|
165
175
|
@stats ||= Sidekiq::Stats.new
|
166
176
|
end
|
167
177
|
|
168
|
-
def
|
178
|
+
def redis_url
|
169
179
|
Sidekiq.redis do |conn|
|
170
|
-
conn.
|
180
|
+
conn._config.server_url
|
171
181
|
end
|
172
182
|
end
|
173
183
|
|
174
|
-
def namespace
|
175
|
-
@ns ||= Sidekiq.redis { |conn| conn.respond_to?(:namespace) ? conn.namespace : nil }
|
176
|
-
end
|
177
|
-
|
178
184
|
def redis_info
|
179
|
-
Sidekiq.redis_info
|
185
|
+
Sidekiq.default_configuration.redis_info
|
180
186
|
end
|
181
187
|
|
182
188
|
def root_path
|
@@ -188,7 +194,7 @@ module Sidekiq
|
|
188
194
|
end
|
189
195
|
|
190
196
|
def current_status
|
191
|
-
|
197
|
+
workset.size == 0 ? "idle" : "active"
|
192
198
|
end
|
193
199
|
|
194
200
|
def relative_time(time)
|
@@ -221,7 +227,7 @@ module Sidekiq
|
|
221
227
|
end
|
222
228
|
|
223
229
|
def truncate(text, truncate_after_chars = 2000)
|
224
|
-
|
230
|
+
truncate_after_chars && text.size > truncate_after_chars ? "#{text[0..truncate_after_chars]}..." : text
|
225
231
|
end
|
226
232
|
|
227
233
|
def display_args(args, truncate_after_chars = 2000)
|
@@ -314,7 +320,7 @@ module Sidekiq
|
|
314
320
|
end
|
315
321
|
|
316
322
|
def environment_title_prefix
|
317
|
-
environment = Sidekiq[:environment] || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
323
|
+
environment = Sidekiq.default_configuration[:environment] || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
318
324
|
|
319
325
|
"[#{environment.upcase}] " unless environment == "production"
|
320
326
|
end
|
@@ -327,13 +333,6 @@ module Sidekiq
|
|
327
333
|
Time.now.utc.strftime("%H:%M:%S UTC")
|
328
334
|
end
|
329
335
|
|
330
|
-
def redis_connection_and_namespace
|
331
|
-
@redis_connection_and_namespace ||= begin
|
332
|
-
namespace_suffix = namespace.nil? ? "" : "##{namespace}"
|
333
|
-
"#{redis_connection}#{namespace_suffix}"
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
336
|
def retry_or_delete_or_kill(job, params)
|
338
337
|
if params["retry"]
|
339
338
|
job.retry
|
data/lib/sidekiq/web.rb
CHANGED
@@ -30,13 +30,10 @@ module Sidekiq
|
|
30
30
|
"Queues" => "queues",
|
31
31
|
"Retries" => "retries",
|
32
32
|
"Scheduled" => "scheduled",
|
33
|
-
"Dead" => "morgue"
|
33
|
+
"Dead" => "morgue",
|
34
|
+
"Metrics" => "metrics"
|
34
35
|
}
|
35
36
|
|
36
|
-
if ENV["SIDEKIQ_METRICS_BETA"] == "1"
|
37
|
-
DEFAULT_TABS["Metrics"] = "metrics"
|
38
|
-
end
|
39
|
-
|
40
37
|
class << self
|
41
38
|
def settings
|
42
39
|
self
|
@@ -79,14 +76,6 @@ module Sidekiq
|
|
79
76
|
send(:"#{attribute}=", value)
|
80
77
|
end
|
81
78
|
|
82
|
-
def sessions=(val)
|
83
|
-
puts "WARNING: Sidekiq::Web.sessions= is no longer relevant and will be removed in Sidekiq 7.0. #{caller(1..1).first}"
|
84
|
-
end
|
85
|
-
|
86
|
-
def session_secret=(val)
|
87
|
-
puts "WARNING: Sidekiq::Web.session_secret= is no longer relevant and will be removed in Sidekiq 7.0. #{caller(1..1).first}"
|
88
|
-
end
|
89
|
-
|
90
79
|
attr_accessor :app_url, :redis_pool
|
91
80
|
attr_writer :locales, :views
|
92
81
|
end
|
@@ -133,10 +122,6 @@ module Sidekiq
|
|
133
122
|
send(:"#{attribute}=", value)
|
134
123
|
end
|
135
124
|
|
136
|
-
def sessions=(val)
|
137
|
-
puts "Sidekiq::Web#sessions= is no longer relevant and will be removed in Sidekiq 7.0. #{caller[2..2].first}"
|
138
|
-
end
|
139
|
-
|
140
125
|
def self.register(extension)
|
141
126
|
extension.registered(WebApplication)
|
142
127
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "sidekiq/job"
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
# Sidekiq::Job is a new alias for Sidekiq::Worker as of Sidekiq 6.3.0.
|
5
|
+
# Use `include Sidekiq::Job` rather than `include Sidekiq::Worker`.
|
6
|
+
#
|
7
|
+
# The term "worker" is too generic and overly confusing, used in several
|
8
|
+
# different contexts meaning different things. Many people call a Sidekiq
|
9
|
+
# process a "worker". Some people call the thread that executes jobs a
|
10
|
+
# "worker". This change brings Sidekiq closer to ActiveJob where your job
|
11
|
+
# classes extend ApplicationJob.
|
12
|
+
Worker = Job
|
13
|
+
end
|