sidekiq 6.4.0 → 6.5.0
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 +50 -1
- data/README.md +6 -1
- data/bin/sidekiq +3 -3
- data/bin/sidekiqload +70 -66
- data/bin/sidekiqmon +1 -1
- data/lib/sidekiq/api.rb +78 -65
- data/lib/sidekiq/cli.rb +46 -37
- data/lib/sidekiq/client.rb +42 -28
- data/lib/sidekiq/component.rb +64 -0
- data/lib/sidekiq/delay.rb +1 -1
- data/lib/sidekiq/extensions/action_mailer.rb +2 -2
- data/lib/sidekiq/extensions/active_record.rb +2 -2
- data/lib/sidekiq/extensions/class_methods.rb +2 -2
- data/lib/sidekiq/extensions/generic_proxy.rb +3 -3
- data/lib/sidekiq/fetch.rb +17 -15
- data/lib/sidekiq/job_logger.rb +15 -27
- data/lib/sidekiq/job_retry.rb +27 -26
- data/lib/sidekiq/job_util.rb +15 -9
- data/lib/sidekiq/launcher.rb +54 -52
- data/lib/sidekiq/logger.rb +8 -18
- data/lib/sidekiq/manager.rb +28 -25
- data/lib/sidekiq/middleware/chain.rb +22 -13
- data/lib/sidekiq/middleware/current_attributes.rb +4 -0
- data/lib/sidekiq/middleware/i18n.rb +6 -4
- data/lib/sidekiq/middleware/modules.rb +19 -0
- data/lib/sidekiq/monitor.rb +1 -1
- data/lib/sidekiq/paginator.rb +8 -8
- data/lib/sidekiq/processor.rb +38 -38
- data/lib/sidekiq/rails.rb +15 -8
- data/lib/sidekiq/redis_client_adapter.rb +154 -0
- data/lib/sidekiq/redis_connection.rb +81 -48
- data/lib/sidekiq/ring_buffer.rb +29 -0
- data/lib/sidekiq/scheduled.rb +11 -10
- data/lib/sidekiq/testing/inline.rb +4 -4
- data/lib/sidekiq/testing.rb +37 -36
- data/lib/sidekiq/transaction_aware_client.rb +45 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/csrf_protection.rb +2 -2
- data/lib/sidekiq/web/helpers.rb +5 -5
- data/lib/sidekiq/web.rb +3 -3
- data/lib/sidekiq/worker.rb +20 -17
- data/lib/sidekiq.rb +98 -30
- data/web/assets/javascripts/application.js +58 -26
- data/web/assets/stylesheets/application.css +1 -0
- data/web/locales/pt-br.yml +27 -9
- data/web/views/_summary.erb +1 -1
- data/web/views/busy.erb +3 -3
- metadata +8 -5
- data/lib/sidekiq/exception_handler.rb +0 -27
- data/lib/sidekiq/util.rb +0 -108
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "sidekiq/middleware/modules"
|
4
|
+
|
3
5
|
module Sidekiq
|
4
6
|
# Middleware is code configured to run before/after
|
5
7
|
# a message is processed. It is patterned after Rack
|
@@ -44,10 +46,12 @@ module Sidekiq
|
|
44
46
|
# This is an example of a minimal server middleware:
|
45
47
|
#
|
46
48
|
# class MyServerHook
|
47
|
-
#
|
48
|
-
#
|
49
|
+
# include Sidekiq::ServerMiddleware
|
50
|
+
# def call(job_instance, msg, queue)
|
51
|
+
# logger.info "Before job"
|
52
|
+
# redis {|conn| conn.get("foo") } # do something in Redis
|
49
53
|
# yield
|
50
|
-
#
|
54
|
+
# logger.info "After job"
|
51
55
|
# end
|
52
56
|
# end
|
53
57
|
#
|
@@ -56,10 +60,11 @@ module Sidekiq
|
|
56
60
|
# to Redis:
|
57
61
|
#
|
58
62
|
# class MyClientHook
|
59
|
-
#
|
60
|
-
#
|
63
|
+
# include Sidekiq::ClientMiddleware
|
64
|
+
# def call(job_class, msg, queue, redis_pool)
|
65
|
+
# logger.info "Before push"
|
61
66
|
# result = yield
|
62
|
-
#
|
67
|
+
# logger.info "After push"
|
63
68
|
# result
|
64
69
|
# end
|
65
70
|
# end
|
@@ -76,7 +81,8 @@ module Sidekiq
|
|
76
81
|
entries.each(&block)
|
77
82
|
end
|
78
83
|
|
79
|
-
def initialize
|
84
|
+
def initialize(config = nil)
|
85
|
+
@config = config
|
80
86
|
@entries = nil
|
81
87
|
yield self if block_given?
|
82
88
|
end
|
@@ -91,24 +97,24 @@ module Sidekiq
|
|
91
97
|
|
92
98
|
def add(klass, *args)
|
93
99
|
remove(klass)
|
94
|
-
entries << Entry.new(klass, *args)
|
100
|
+
entries << Entry.new(@config, klass, *args)
|
95
101
|
end
|
96
102
|
|
97
103
|
def prepend(klass, *args)
|
98
104
|
remove(klass)
|
99
|
-
entries.insert(0, Entry.new(klass, *args))
|
105
|
+
entries.insert(0, Entry.new(@config, klass, *args))
|
100
106
|
end
|
101
107
|
|
102
108
|
def insert_before(oldklass, newklass, *args)
|
103
109
|
i = entries.index { |entry| entry.klass == newklass }
|
104
|
-
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
110
|
+
new_entry = i.nil? ? Entry.new(@config, newklass, *args) : entries.delete_at(i)
|
105
111
|
i = entries.index { |entry| entry.klass == oldklass } || 0
|
106
112
|
entries.insert(i, new_entry)
|
107
113
|
end
|
108
114
|
|
109
115
|
def insert_after(oldklass, newklass, *args)
|
110
116
|
i = entries.index { |entry| entry.klass == newklass }
|
111
|
-
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
117
|
+
new_entry = i.nil? ? Entry.new(@config, newklass, *args) : entries.delete_at(i)
|
112
118
|
i = entries.index { |entry| entry.klass == oldklass } || entries.count - 1
|
113
119
|
entries.insert(i + 1, new_entry)
|
114
120
|
end
|
@@ -149,13 +155,16 @@ module Sidekiq
|
|
149
155
|
class Entry
|
150
156
|
attr_reader :klass
|
151
157
|
|
152
|
-
def initialize(klass, *args)
|
158
|
+
def initialize(config, klass, *args)
|
159
|
+
@config = config
|
153
160
|
@klass = klass
|
154
161
|
@args = args
|
155
162
|
end
|
156
163
|
|
157
164
|
def make_new
|
158
|
-
@klass.new(*@args)
|
165
|
+
x = @klass.new(*@args)
|
166
|
+
x.config = @config if @config && x.respond_to?(:config=)
|
167
|
+
x
|
159
168
|
end
|
160
169
|
end
|
161
170
|
end
|
@@ -15,6 +15,8 @@ module Sidekiq
|
|
15
15
|
#
|
16
16
|
module CurrentAttributes
|
17
17
|
class Save
|
18
|
+
include Sidekiq::ClientMiddleware
|
19
|
+
|
18
20
|
def initialize(cattr)
|
19
21
|
@klass = cattr
|
20
22
|
end
|
@@ -31,6 +33,8 @@ module Sidekiq
|
|
31
33
|
end
|
32
34
|
|
33
35
|
class Load
|
36
|
+
include Sidekiq::ServerMiddleware
|
37
|
+
|
34
38
|
def initialize(cattr)
|
35
39
|
@klass = cattr
|
36
40
|
end
|
@@ -10,16 +10,18 @@ module Sidekiq::Middleware::I18n
|
|
10
10
|
# Get the current locale and store it in the message
|
11
11
|
# to be sent to Sidekiq.
|
12
12
|
class Client
|
13
|
-
|
14
|
-
|
13
|
+
include Sidekiq::ClientMiddleware
|
14
|
+
def call(_jobclass, job, _queue, _redis)
|
15
|
+
job["locale"] ||= I18n.locale
|
15
16
|
yield
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
20
|
# Pull the msg locale out and set the current thread to use it.
|
20
21
|
class Server
|
21
|
-
|
22
|
-
|
22
|
+
include Sidekiq::ServerMiddleware
|
23
|
+
def call(_jobclass, job, _queue, &block)
|
24
|
+
I18n.with_locale(job.fetch("locale", I18n.default_locale), &block)
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module ServerMiddleware
|
3
|
+
attr_accessor :config
|
4
|
+
def redis_pool
|
5
|
+
config.redis_pool
|
6
|
+
end
|
7
|
+
|
8
|
+
def logger
|
9
|
+
config.logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def redis(&block)
|
13
|
+
config.redis(&block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# no difference for now
|
18
|
+
ClientMiddleware = ServerMiddleware
|
19
|
+
end
|
data/lib/sidekiq/monitor.rb
CHANGED
data/lib/sidekiq/paginator.rb
CHANGED
@@ -16,22 +16,22 @@ module Sidekiq
|
|
16
16
|
|
17
17
|
case type
|
18
18
|
when "zset"
|
19
|
-
total_size, items = conn.multi {
|
20
|
-
|
19
|
+
total_size, items = conn.multi { |transaction|
|
20
|
+
transaction.zcard(key)
|
21
21
|
if rev
|
22
|
-
|
22
|
+
transaction.zrevrange(key, starting, ending, withscores: true)
|
23
23
|
else
|
24
|
-
|
24
|
+
transaction.zrange(key, starting, ending, withscores: true)
|
25
25
|
end
|
26
26
|
}
|
27
27
|
[current_page, total_size, items]
|
28
28
|
when "list"
|
29
|
-
total_size, items = conn.multi {
|
30
|
-
|
29
|
+
total_size, items = conn.multi { |transaction|
|
30
|
+
transaction.llen(key)
|
31
31
|
if rev
|
32
|
-
|
32
|
+
transaction.lrange(key, -ending - 1, -starting - 1)
|
33
33
|
else
|
34
|
-
|
34
|
+
transaction.lrange(key, starting, ending)
|
35
35
|
end
|
36
36
|
}
|
37
37
|
items.reverse! if rev
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "sidekiq/util"
|
4
3
|
require "sidekiq/fetch"
|
5
4
|
require "sidekiq/job_logger"
|
6
5
|
require "sidekiq/job_retry"
|
@@ -11,33 +10,34 @@ module Sidekiq
|
|
11
10
|
#
|
12
11
|
# 1. fetches a job from Redis
|
13
12
|
# 2. executes the job
|
14
|
-
# a. instantiate the
|
13
|
+
# a. instantiate the job class
|
15
14
|
# b. run the middleware chain
|
16
15
|
# c. call #perform
|
17
16
|
#
|
18
|
-
# A Processor can exit due to shutdown
|
19
|
-
#
|
17
|
+
# A Processor can exit due to shutdown or due to
|
18
|
+
# an error during job execution.
|
20
19
|
#
|
21
20
|
# If an error occurs in the job execution, the
|
22
21
|
# Processor calls the Manager to create a new one
|
23
22
|
# to replace itself and exits.
|
24
23
|
#
|
25
24
|
class Processor
|
26
|
-
include
|
25
|
+
include Sidekiq::Component
|
27
26
|
|
28
27
|
attr_reader :thread
|
29
28
|
attr_reader :job
|
30
29
|
|
31
|
-
def initialize(
|
32
|
-
@
|
30
|
+
def initialize(options, &block)
|
31
|
+
@callback = block
|
33
32
|
@down = false
|
34
33
|
@done = false
|
35
34
|
@job = nil
|
36
35
|
@thread = nil
|
36
|
+
@config = options
|
37
37
|
@strategy = options[:fetch]
|
38
38
|
@reloader = options[:reloader] || proc { |&block| block.call }
|
39
39
|
@job_logger = (options[:job_logger] || Sidekiq::JobLogger).new
|
40
|
-
@retrier = Sidekiq::JobRetry.new
|
40
|
+
@retrier = Sidekiq::JobRetry.new(options)
|
41
41
|
end
|
42
42
|
|
43
43
|
def terminate(wait = false)
|
@@ -66,26 +66,26 @@ module Sidekiq
|
|
66
66
|
|
67
67
|
def run
|
68
68
|
process_one until @done
|
69
|
-
@
|
69
|
+
@callback.call(self)
|
70
70
|
rescue Sidekiq::Shutdown
|
71
|
-
@
|
71
|
+
@callback.call(self)
|
72
72
|
rescue Exception => ex
|
73
|
-
@
|
73
|
+
@callback.call(self, ex)
|
74
74
|
end
|
75
75
|
|
76
|
-
def process_one
|
76
|
+
def process_one(&block)
|
77
77
|
@job = fetch
|
78
78
|
process(@job) if @job
|
79
79
|
@job = nil
|
80
80
|
end
|
81
81
|
|
82
82
|
def get_one
|
83
|
-
|
83
|
+
uow = @strategy.retrieve_work
|
84
84
|
if @down
|
85
85
|
logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }
|
86
86
|
@down = nil
|
87
87
|
end
|
88
|
-
|
88
|
+
uow
|
89
89
|
rescue Sidekiq::Shutdown
|
90
90
|
rescue => ex
|
91
91
|
handle_fetch_exception(ex)
|
@@ -130,10 +130,10 @@ module Sidekiq
|
|
130
130
|
# Effectively this block denotes a "unit of work" to Rails.
|
131
131
|
@reloader.call do
|
132
132
|
klass = constantize(job_hash["class"])
|
133
|
-
|
134
|
-
|
135
|
-
@retrier.local(
|
136
|
-
yield
|
133
|
+
inst = klass.new
|
134
|
+
inst.jid = job_hash["jid"]
|
135
|
+
@retrier.local(inst, jobstr, queue) do
|
136
|
+
yield inst
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
@@ -142,9 +142,9 @@ module Sidekiq
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
145
|
-
def process(
|
146
|
-
jobstr =
|
147
|
-
queue =
|
145
|
+
def process(uow)
|
146
|
+
jobstr = uow.job
|
147
|
+
queue = uow.queue_name
|
148
148
|
|
149
149
|
# Treat malformed JSON as a special case: job goes straight to the morgue.
|
150
150
|
job_hash = nil
|
@@ -154,14 +154,14 @@ module Sidekiq
|
|
154
154
|
handle_exception(ex, {context: "Invalid JSON for job", jobstr: jobstr})
|
155
155
|
# we can't notify because the job isn't a valid hash payload.
|
156
156
|
DeadSet.new.kill(jobstr, notify_failure: false)
|
157
|
-
return
|
157
|
+
return uow.acknowledge
|
158
158
|
end
|
159
159
|
|
160
160
|
ack = false
|
161
161
|
begin
|
162
|
-
dispatch(job_hash, queue, jobstr) do |
|
163
|
-
|
164
|
-
execute_job(
|
162
|
+
dispatch(job_hash, queue, jobstr) do |inst|
|
163
|
+
@config.server_middleware.invoke(inst, job_hash, queue) do
|
164
|
+
execute_job(inst, job_hash["args"])
|
165
165
|
end
|
166
166
|
end
|
167
167
|
ack = true
|
@@ -186,14 +186,14 @@ module Sidekiq
|
|
186
186
|
if ack
|
187
187
|
# We don't want a shutdown signal to interrupt job acknowledgment.
|
188
188
|
Thread.handle_interrupt(Sidekiq::Shutdown => :never) do
|
189
|
-
|
189
|
+
uow.acknowledge
|
190
190
|
end
|
191
191
|
end
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
|
-
def execute_job(
|
196
|
-
|
195
|
+
def execute_job(inst, cloned_args)
|
196
|
+
inst.perform(*cloned_args)
|
197
197
|
end
|
198
198
|
|
199
199
|
# Ruby doesn't provide atomic counters out of the box so we'll
|
@@ -219,39 +219,39 @@ module Sidekiq
|
|
219
219
|
end
|
220
220
|
|
221
221
|
# jruby's Hash implementation is not threadsafe, so we wrap it in a mutex here
|
222
|
-
class
|
222
|
+
class SharedWorkState
|
223
223
|
def initialize
|
224
|
-
@
|
224
|
+
@work_state = {}
|
225
225
|
@lock = Mutex.new
|
226
226
|
end
|
227
227
|
|
228
228
|
def set(tid, hash)
|
229
|
-
@lock.synchronize { @
|
229
|
+
@lock.synchronize { @work_state[tid] = hash }
|
230
230
|
end
|
231
231
|
|
232
232
|
def delete(tid)
|
233
|
-
@lock.synchronize { @
|
233
|
+
@lock.synchronize { @work_state.delete(tid) }
|
234
234
|
end
|
235
235
|
|
236
236
|
def dup
|
237
|
-
@lock.synchronize { @
|
237
|
+
@lock.synchronize { @work_state.dup }
|
238
238
|
end
|
239
239
|
|
240
240
|
def size
|
241
|
-
@lock.synchronize { @
|
241
|
+
@lock.synchronize { @work_state.size }
|
242
242
|
end
|
243
243
|
|
244
244
|
def clear
|
245
|
-
@lock.synchronize { @
|
245
|
+
@lock.synchronize { @work_state.clear }
|
246
246
|
end
|
247
247
|
end
|
248
248
|
|
249
249
|
PROCESSED = Counter.new
|
250
250
|
FAILURE = Counter.new
|
251
|
-
|
251
|
+
WORK_STATE = SharedWorkState.new
|
252
252
|
|
253
253
|
def stats(jobstr, queue)
|
254
|
-
|
254
|
+
WORK_STATE.set(tid, {queue: queue, payload: jobstr, run_at: Time.now.to_i})
|
255
255
|
|
256
256
|
begin
|
257
257
|
yield
|
@@ -259,7 +259,7 @@ module Sidekiq
|
|
259
259
|
FAILURE.incr
|
260
260
|
raise
|
261
261
|
ensure
|
262
|
-
|
262
|
+
WORK_STATE.delete(tid)
|
263
263
|
PROCESSED.incr
|
264
264
|
end
|
265
265
|
end
|
data/lib/sidekiq/rails.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "sidekiq/
|
3
|
+
require "sidekiq/job"
|
4
4
|
|
5
5
|
module Sidekiq
|
6
6
|
class Rails < ::Rails::Engine
|
@@ -33,28 +33,35 @@ module Sidekiq
|
|
33
33
|
# end
|
34
34
|
initializer "sidekiq.active_job_integration" do
|
35
35
|
ActiveSupport.on_load(:active_job) do
|
36
|
-
include ::Sidekiq::
|
36
|
+
include ::Sidekiq::Job::Options unless respond_to?(:sidekiq_options)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
40
|
initializer "sidekiq.rails_logger" do
|
41
|
-
Sidekiq.configure_server do |
|
42
|
-
# This is the integration code necessary so that if
|
41
|
+
Sidekiq.configure_server do |config|
|
42
|
+
# This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
|
43
43
|
# it will appear in the Sidekiq console with all of the job context. See #5021 and
|
44
44
|
# https://github.com/rails/rails/blob/b5f2b550f69a99336482739000c58e4e04e033aa/railties/lib/rails/commands/server/server_command.rb#L82-L84
|
45
|
-
unless ::Rails.logger ==
|
46
|
-
::Rails.logger.extend(::ActiveSupport::Logger.broadcast(
|
45
|
+
unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
|
46
|
+
::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
config.before_configuration do
|
52
|
+
dep = ActiveSupport::Deprecation.new("7.0", "Sidekiq")
|
53
|
+
dep.deprecate_methods(Sidekiq.singleton_class,
|
54
|
+
default_worker_options: :default_job_options,
|
55
|
+
"default_worker_options=": :default_job_options=)
|
56
|
+
end
|
57
|
+
|
51
58
|
# This hook happens after all initializers are run, just before returning
|
52
59
|
# from config/environment.rb back to sidekiq/cli.rb.
|
53
60
|
#
|
54
61
|
# None of this matters on the client-side, only within the Sidekiq process itself.
|
55
62
|
config.after_initialize do
|
56
|
-
Sidekiq.configure_server do |
|
57
|
-
|
63
|
+
Sidekiq.configure_server do |config|
|
64
|
+
config[:reloader] = Sidekiq::Rails::Reloader.new
|
58
65
|
end
|
59
66
|
end
|
60
67
|
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "connection_pool"
|
4
|
+
require "redis_client"
|
5
|
+
require "redis_client/decorator"
|
6
|
+
require "uri"
|
7
|
+
|
8
|
+
module Sidekiq
|
9
|
+
class RedisClientAdapter
|
10
|
+
BaseError = RedisClient::Error
|
11
|
+
CommandError = RedisClient::CommandError
|
12
|
+
|
13
|
+
module CompatMethods
|
14
|
+
def info
|
15
|
+
@client.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
|
16
|
+
end
|
17
|
+
|
18
|
+
def evalsha(sha, keys, argv)
|
19
|
+
@client.call("EVALSHA", sha, keys.size, *keys, *argv)
|
20
|
+
end
|
21
|
+
|
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
|
+
private
|
44
|
+
|
45
|
+
def method_missing(*args, &block)
|
46
|
+
@client.call(*args, *block)
|
47
|
+
end
|
48
|
+
ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
|
49
|
+
|
50
|
+
def respond_to_missing?(name, include_private = false)
|
51
|
+
super # Appease the linter. We can't tell what is a valid command.
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
CompatClient = RedisClient::Decorator.create(CompatMethods)
|
56
|
+
|
57
|
+
class CompatClient
|
58
|
+
%i[scan sscan zscan hscan].each do |method|
|
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
|
+
|
75
|
+
def _client
|
76
|
+
@client
|
77
|
+
end
|
78
|
+
|
79
|
+
def message
|
80
|
+
yield nil, @queue.pop
|
81
|
+
end
|
82
|
+
|
83
|
+
# NB: this method does not return
|
84
|
+
def subscribe(chan)
|
85
|
+
@queue = ::Queue.new
|
86
|
+
|
87
|
+
pubsub = @client.pubsub
|
88
|
+
pubsub.call("subscribe", chan)
|
89
|
+
|
90
|
+
loop do
|
91
|
+
evt = pubsub.next_event
|
92
|
+
next if evt.nil?
|
93
|
+
next unless evt[0] == "message" && evt[1] == chan
|
94
|
+
|
95
|
+
(_, _, msg) = evt
|
96
|
+
@queue << msg
|
97
|
+
yield self
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def initialize(options)
|
103
|
+
opts = client_opts(options)
|
104
|
+
@config = if opts.key?(:sentinels)
|
105
|
+
RedisClient.sentinel(**opts)
|
106
|
+
else
|
107
|
+
RedisClient.config(**opts)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def new_client
|
112
|
+
CompatClient.new(@config.new_client)
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def client_opts(options)
|
118
|
+
opts = options.dup
|
119
|
+
|
120
|
+
if opts[:namespace]
|
121
|
+
Sidekiq.logger.error("Your Redis configuration uses the namespace '#{opts[:namespace]}' but this feature isn't supported by redis-client. " \
|
122
|
+
"Either use the redis adapter or remove the namespace.")
|
123
|
+
Kernel.exit(-127)
|
124
|
+
end
|
125
|
+
|
126
|
+
opts.delete(:size)
|
127
|
+
opts.delete(:pool_timeout)
|
128
|
+
|
129
|
+
if opts[:network_timeout]
|
130
|
+
opts[:timeout] = opts[:network_timeout]
|
131
|
+
opts.delete(:network_timeout)
|
132
|
+
end
|
133
|
+
|
134
|
+
if opts[:driver]
|
135
|
+
opts[:driver] = opts[:driver].to_sym
|
136
|
+
end
|
137
|
+
|
138
|
+
opts[:name] = opts.delete(:master_name) if opts.key?(:master_name)
|
139
|
+
opts[:role] = opts[:role].to_sym if opts.key?(:role)
|
140
|
+
opts.delete(:url) if opts.key?(:sentinels)
|
141
|
+
|
142
|
+
# Issue #3303, redis-rb will silently retry an operation.
|
143
|
+
# This can lead to duplicate jobs if Sidekiq::Client's LPUSH
|
144
|
+
# is performed twice but I believe this is much, much rarer
|
145
|
+
# than the reconnect silently fixing a problem; we keep it
|
146
|
+
# on by default.
|
147
|
+
opts[:reconnect_attempts] ||= 1
|
148
|
+
|
149
|
+
opts
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
Sidekiq::RedisConnection.adapter = Sidekiq::RedisClientAdapter
|