sidekiq 5.2.10 → 6.0.0.pre1
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/.standard.yml +20 -0
- data/.travis.yml +5 -2
- data/6.0-Upgrade.md +58 -0
- data/Changes.md +21 -16
- data/Gemfile +15 -10
- data/Rakefile +5 -4
- data/bin/sidekiqctl +1 -10
- data/lib/generators/sidekiq/worker_generator.rb +12 -14
- data/lib/sidekiq/api.rb +133 -148
- data/lib/sidekiq/cli.rb +95 -147
- data/lib/sidekiq/client.rb +44 -45
- data/lib/sidekiq/ctl.rb +35 -109
- data/lib/sidekiq/delay.rb +5 -6
- data/lib/sidekiq/exception_handler.rb +10 -12
- data/lib/sidekiq/extensions/action_mailer.rb +10 -20
- data/lib/sidekiq/extensions/active_record.rb +9 -7
- data/lib/sidekiq/extensions/class_methods.rb +9 -7
- data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
- data/lib/sidekiq/fetch.rb +5 -6
- data/lib/sidekiq/job_logger.rb +37 -7
- data/lib/sidekiq/job_retry.rb +45 -58
- data/lib/sidekiq/launcher.rb +59 -48
- data/lib/sidekiq/logger.rb +69 -0
- data/lib/sidekiq/manager.rb +6 -8
- data/lib/sidekiq/middleware/chain.rb +2 -1
- data/lib/sidekiq/middleware/i18n.rb +5 -7
- data/lib/sidekiq/paginator.rb +11 -12
- data/lib/sidekiq/processor.rb +42 -45
- data/lib/sidekiq/rails.rb +2 -26
- data/lib/sidekiq/redis_connection.rb +31 -37
- data/lib/sidekiq/scheduled.rb +17 -19
- data/lib/sidekiq/testing/inline.rb +2 -1
- data/lib/sidekiq/testing.rb +22 -23
- data/lib/sidekiq/util.rb +18 -15
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +15 -11
- data/lib/sidekiq/web/application.rb +59 -59
- data/lib/sidekiq/web/helpers.rb +66 -67
- data/lib/sidekiq/web/router.rb +17 -14
- data/lib/sidekiq/web.rb +36 -44
- data/lib/sidekiq/worker.rb +12 -13
- data/lib/sidekiq.rb +53 -42
- data/sidekiq.gemspec +7 -7
- metadata +20 -32
- data/lib/sidekiq/core_ext.rb +0 -1
- data/lib/sidekiq/logging.rb +0 -122
- data/lib/sidekiq/middleware/server/active_record.rb +0 -23
data/lib/sidekiq/job_retry.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
2
|
+
|
3
|
+
require "sidekiq/scheduled"
|
4
|
+
require "sidekiq/api"
|
4
5
|
|
5
6
|
module Sidekiq
|
6
7
|
##
|
@@ -81,22 +82,19 @@ module Sidekiq
|
|
81
82
|
# ignore, will be pushed back onto queue during hard_shutdown
|
82
83
|
raise Sidekiq::Shutdown if exception_caused_by_shutdown?(e)
|
83
84
|
|
84
|
-
if msg[
|
85
|
+
if msg["retry"]
|
85
86
|
attempt_retry(nil, msg, queue, e)
|
86
87
|
else
|
87
88
|
Sidekiq.death_handlers.each do |handler|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
handle_exception(handler_ex, { context: "Error calling death handler", job: msg })
|
92
|
-
end
|
89
|
+
handler.call(msg, e)
|
90
|
+
rescue => handler_ex
|
91
|
+
handle_exception(handler_ex, {context: "Error calling death handler", job: msg})
|
93
92
|
end
|
94
93
|
end
|
95
94
|
|
96
95
|
raise Handled
|
97
96
|
end
|
98
97
|
|
99
|
-
|
100
98
|
# The local retry support means that any errors that occur within
|
101
99
|
# this block can be associated with the given worker instance.
|
102
100
|
# This is required to support the `sidekiq_retries_exhausted` block.
|
@@ -116,11 +114,11 @@ module Sidekiq
|
|
116
114
|
# ignore, will be pushed back onto queue during hard_shutdown
|
117
115
|
raise Sidekiq::Shutdown if exception_caused_by_shutdown?(e)
|
118
116
|
|
119
|
-
if msg[
|
120
|
-
msg[
|
117
|
+
if msg["retry"].nil?
|
118
|
+
msg["retry"] = worker.class.get_sidekiq_options["retry"]
|
121
119
|
end
|
122
120
|
|
123
|
-
raise e unless msg[
|
121
|
+
raise e unless msg["retry"]
|
124
122
|
attempt_retry(worker, msg, queue, e)
|
125
123
|
# We've handled this error associated with this job, don't
|
126
124
|
# need to handle it at the global level
|
@@ -133,13 +131,9 @@ module Sidekiq
|
|
133
131
|
# instantiate the worker instance. All access must be guarded and
|
134
132
|
# best effort.
|
135
133
|
def attempt_retry(worker, msg, queue, exception)
|
136
|
-
max_retry_attempts = retry_attempts_from(msg[
|
134
|
+
max_retry_attempts = retry_attempts_from(msg["retry"], @max_retries)
|
137
135
|
|
138
|
-
msg[
|
139
|
-
msg['retry_queue']
|
140
|
-
else
|
141
|
-
queue
|
142
|
-
end
|
136
|
+
msg["queue"] = (msg["retry_queue"] || queue)
|
143
137
|
|
144
138
|
m = exception_message(exception)
|
145
139
|
if m.respond_to?(:scrub!)
|
@@ -147,32 +141,32 @@ module Sidekiq
|
|
147
141
|
m.scrub!
|
148
142
|
end
|
149
143
|
|
150
|
-
msg[
|
151
|
-
msg[
|
152
|
-
count = if msg[
|
153
|
-
msg[
|
154
|
-
msg[
|
144
|
+
msg["error_message"] = m
|
145
|
+
msg["error_class"] = exception.class.name
|
146
|
+
count = if msg["retry_count"]
|
147
|
+
msg["retried_at"] = Time.now.to_f
|
148
|
+
msg["retry_count"] += 1
|
155
149
|
else
|
156
|
-
msg[
|
157
|
-
msg[
|
150
|
+
msg["failed_at"] = Time.now.to_f
|
151
|
+
msg["retry_count"] = 0
|
158
152
|
end
|
159
153
|
|
160
|
-
if msg[
|
161
|
-
msg[
|
162
|
-
elsif !msg[
|
154
|
+
if msg["backtrace"] == true
|
155
|
+
msg["error_backtrace"] = exception.backtrace
|
156
|
+
elsif !msg["backtrace"]
|
163
157
|
# do nothing
|
164
|
-
elsif msg[
|
165
|
-
msg[
|
158
|
+
elsif msg["backtrace"].to_i != 0
|
159
|
+
msg["error_backtrace"] = exception.backtrace[0...msg["backtrace"].to_i]
|
166
160
|
end
|
167
161
|
|
168
162
|
if count < max_retry_attempts
|
169
163
|
delay = delay_for(worker, count, exception)
|
170
164
|
# Logging here can break retries if the logging device raises ENOSPC #3979
|
171
|
-
#logger.debug { "Failure! Retry #{count} in #{delay} seconds" }
|
165
|
+
# logger.debug { "Failure! Retry #{count} in #{delay} seconds" }
|
172
166
|
retry_at = Time.now.to_f + delay
|
173
167
|
payload = Sidekiq.dump_json(msg)
|
174
168
|
Sidekiq.redis do |conn|
|
175
|
-
conn.zadd(
|
169
|
+
conn.zadd("retry", retry_at.to_s, payload)
|
176
170
|
end
|
177
171
|
else
|
178
172
|
# Goodbye dear message, you (re)tried your best I'm sure.
|
@@ -182,25 +176,23 @@ module Sidekiq
|
|
182
176
|
|
183
177
|
def retries_exhausted(worker, msg, exception)
|
184
178
|
begin
|
185
|
-
block = worker
|
186
|
-
block
|
179
|
+
block = worker&.sidekiq_retries_exhausted_block
|
180
|
+
block&.call(msg, exception)
|
187
181
|
rescue => e
|
188
|
-
handle_exception(e, {
|
182
|
+
handle_exception(e, {context: "Error calling retries_exhausted", job: msg})
|
189
183
|
end
|
190
184
|
|
191
185
|
Sidekiq.death_handlers.each do |handler|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
handle_exception(e, { context: "Error calling death handler", job: msg })
|
196
|
-
end
|
186
|
+
handler.call(msg, exception)
|
187
|
+
rescue => e
|
188
|
+
handle_exception(e, {context: "Error calling death handler", job: msg})
|
197
189
|
end
|
198
190
|
|
199
|
-
send_to_morgue(msg) unless msg[
|
191
|
+
send_to_morgue(msg) unless msg["dead"] == false
|
200
192
|
end
|
201
193
|
|
202
194
|
def send_to_morgue(msg)
|
203
|
-
logger.info { "Adding dead #{msg[
|
195
|
+
logger.info { "Adding dead #{msg["class"]} job #{msg["jid"]}" }
|
204
196
|
payload = Sidekiq.dump_json(msg)
|
205
197
|
DeadSet.new.kill(payload, notify_failure: false)
|
206
198
|
end
|
@@ -214,7 +206,7 @@ module Sidekiq
|
|
214
206
|
end
|
215
207
|
|
216
208
|
def delay_for(worker, count, exception)
|
217
|
-
if worker
|
209
|
+
if worker&.sidekiq_retry_in_block
|
218
210
|
custom_retry_in = retry_in(worker, count, exception).to_i
|
219
211
|
return custom_retry_in if custom_retry_in > 0
|
220
212
|
end
|
@@ -223,16 +215,14 @@ module Sidekiq
|
|
223
215
|
|
224
216
|
# delayed_job uses the same basic formula
|
225
217
|
def seconds_to_delay(count)
|
226
|
-
(count
|
218
|
+
(count**4) + 15 + (rand(30) * (count + 1))
|
227
219
|
end
|
228
220
|
|
229
221
|
def retry_in(worker, count, exception)
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
nil
|
235
|
-
end
|
222
|
+
worker.sidekiq_retry_in_block.call(count, exception)
|
223
|
+
rescue Exception => e
|
224
|
+
handle_exception(e, {context: "Failure scheduling retry using the defined `sidekiq_retry_in` in #{worker.class.name}, falling back to default"})
|
225
|
+
nil
|
236
226
|
end
|
237
227
|
|
238
228
|
def exception_caused_by_shutdown?(e, checked_causes = [])
|
@@ -249,14 +239,11 @@ module Sidekiq
|
|
249
239
|
# Extract message from exception.
|
250
240
|
# Set a default if the message raises an error
|
251
241
|
def exception_message(exception)
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
"!!! ERROR MESSAGE THREW AN ERROR !!!".dup
|
258
|
-
end
|
242
|
+
# App code can stuff all sorts of crazy binary data into the error message
|
243
|
+
# that won't convert to JSON.
|
244
|
+
exception.message.to_s[0, 10_000]
|
245
|
+
rescue
|
246
|
+
+"!!! ERROR MESSAGE THREW AN ERROR !!!"
|
259
247
|
end
|
260
|
-
|
261
248
|
end
|
262
249
|
end
|
data/lib/sidekiq/launcher.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
2
|
+
|
3
|
+
require "sidekiq/manager"
|
4
|
+
require "sidekiq/fetch"
|
5
|
+
require "sidekiq/scheduled"
|
5
6
|
|
6
7
|
module Sidekiq
|
7
8
|
# The Launcher is a very simple Actor whose job is to
|
@@ -11,9 +12,17 @@ module Sidekiq
|
|
11
12
|
class Launcher
|
12
13
|
include Util
|
13
14
|
|
14
|
-
|
15
|
+
STATS_TTL = 5 * 365 * 24 * 60 * 60 # 5 years
|
15
16
|
|
16
|
-
|
17
|
+
PROCTITLES = [
|
18
|
+
proc { "sidekiq" },
|
19
|
+
proc { Sidekiq::VERSION },
|
20
|
+
proc { |me, data| data["tag"] },
|
21
|
+
proc { |me, data| "[#{Processor::WORKER_STATE.size} of #{data["concurrency"]} busy]" },
|
22
|
+
proc { |me, data| "stopping" if me.stopping? },
|
23
|
+
]
|
24
|
+
|
25
|
+
attr_accessor :manager, :poller, :fetcher
|
17
26
|
|
18
27
|
def initialize(options)
|
19
28
|
@manager = Sidekiq::Manager.new(options)
|
@@ -62,10 +71,30 @@ module Sidekiq
|
|
62
71
|
|
63
72
|
private unless $TESTING
|
64
73
|
|
74
|
+
def start_heartbeat
|
75
|
+
loop do
|
76
|
+
heartbeat
|
77
|
+
sleep 5
|
78
|
+
end
|
79
|
+
Sidekiq.logger.info("Heartbeat stopping...")
|
80
|
+
end
|
81
|
+
|
82
|
+
def clear_heartbeat
|
83
|
+
# Remove record from Redis since we are shutting down.
|
84
|
+
# Note we don't stop the heartbeat thread; if the process
|
85
|
+
# doesn't actually exit, it'll reappear in the Web UI.
|
86
|
+
Sidekiq.redis do |conn|
|
87
|
+
conn.pipelined do
|
88
|
+
conn.srem("processes", identity)
|
89
|
+
conn.del("#{identity}:workers")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
rescue
|
93
|
+
# best effort, ignore network errors
|
94
|
+
end
|
95
|
+
|
65
96
|
def heartbeat
|
66
|
-
|
67
|
-
results.compact!
|
68
|
-
$0 = results.join(' ')
|
97
|
+
$0 = PROCTITLES.map { |proc| proc.call(self, to_data) }.compact.join(" ")
|
69
98
|
|
70
99
|
❤
|
71
100
|
end
|
@@ -73,6 +102,7 @@ module Sidekiq
|
|
73
102
|
def ❤
|
74
103
|
key = identity
|
75
104
|
fails = procd = 0
|
105
|
+
|
76
106
|
begin
|
77
107
|
fails = Processor::FAILURE.reset
|
78
108
|
procd = Processor::PROCESSED.reset
|
@@ -80,6 +110,7 @@ module Sidekiq
|
|
80
110
|
|
81
111
|
workers_key = "#{key}:workers"
|
82
112
|
nowdate = Time.now.utc.strftime("%Y-%m-%d")
|
113
|
+
|
83
114
|
Sidekiq.redis do |conn|
|
84
115
|
conn.multi do
|
85
116
|
conn.incrby("stat:processed", procd)
|
@@ -97,24 +128,27 @@ module Sidekiq
|
|
97
128
|
conn.expire(workers_key, 60)
|
98
129
|
end
|
99
130
|
end
|
131
|
+
|
100
132
|
fails = procd = 0
|
101
133
|
|
102
|
-
_, exists, _, _, msg = Sidekiq.redis
|
103
|
-
conn.multi
|
104
|
-
conn.sadd(
|
105
|
-
conn.exists
|
106
|
-
conn.hmset(key,
|
134
|
+
_, exists, _, _, msg = Sidekiq.redis { |conn|
|
135
|
+
res = conn.multi {
|
136
|
+
conn.sadd("processes", key)
|
137
|
+
conn.exists(key)
|
138
|
+
conn.hmset(key, "info", to_json, "busy", curstate.size, "beat", Time.now.to_f, "quiet", @done)
|
107
139
|
conn.expire(key, 60)
|
108
140
|
conn.rpop("#{key}-signals")
|
109
|
-
|
110
|
-
|
141
|
+
}
|
142
|
+
|
143
|
+
res
|
144
|
+
}
|
111
145
|
|
112
146
|
# first heartbeat or recovering from an outage and need to reestablish our heartbeat
|
113
|
-
fire_event(:heartbeat)
|
147
|
+
fire_event(:heartbeat) unless exists
|
114
148
|
|
115
149
|
return unless msg
|
116
150
|
|
117
|
-
::Process.kill(msg,
|
151
|
+
::Process.kill(msg, $PID)
|
118
152
|
rescue => e
|
119
153
|
# ignore all redis/network issues
|
120
154
|
logger.error("heartbeat: #{e.message}")
|
@@ -124,25 +158,17 @@ module Sidekiq
|
|
124
158
|
end
|
125
159
|
end
|
126
160
|
|
127
|
-
def start_heartbeat
|
128
|
-
while true
|
129
|
-
heartbeat
|
130
|
-
sleep 5
|
131
|
-
end
|
132
|
-
Sidekiq.logger.info("Heartbeat stopping...")
|
133
|
-
end
|
134
|
-
|
135
161
|
def to_data
|
136
162
|
@data ||= begin
|
137
163
|
{
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
164
|
+
"hostname" => hostname,
|
165
|
+
"started_at" => Time.now.to_f,
|
166
|
+
"pid" => $PID,
|
167
|
+
"tag" => @options[:tag] || "",
|
168
|
+
"concurrency" => @options[:concurrency],
|
169
|
+
"queues" => @options[:queues].uniq,
|
170
|
+
"labels" => @options[:labels],
|
171
|
+
"identity" => identity,
|
146
172
|
}
|
147
173
|
end
|
148
174
|
end
|
@@ -154,20 +180,5 @@ module Sidekiq
|
|
154
180
|
Sidekiq.dump_json(to_data)
|
155
181
|
end
|
156
182
|
end
|
157
|
-
|
158
|
-
def clear_heartbeat
|
159
|
-
# Remove record from Redis since we are shutting down.
|
160
|
-
# Note we don't stop the heartbeat thread; if the process
|
161
|
-
# doesn't actually exit, it'll reappear in the Web UI.
|
162
|
-
Sidekiq.redis do |conn|
|
163
|
-
conn.pipelined do
|
164
|
-
conn.srem('processes', identity)
|
165
|
-
conn.del("#{identity}:workers")
|
166
|
-
end
|
167
|
-
end
|
168
|
-
rescue
|
169
|
-
# best effort, ignore network errors
|
170
|
-
end
|
171
|
-
|
172
183
|
end
|
173
184
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
module Sidekiq
|
7
|
+
class Logger < ::Logger
|
8
|
+
def initialize(*args)
|
9
|
+
super
|
10
|
+
|
11
|
+
self.formatter = Sidekiq.log_formatter
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_context(hash)
|
15
|
+
ctx.merge!(hash)
|
16
|
+
yield
|
17
|
+
ensure
|
18
|
+
hash.keys.each { |key| ctx.delete(key) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def ctx
|
22
|
+
Thread.current[:sidekiq_context] ||= {}
|
23
|
+
end
|
24
|
+
|
25
|
+
module Formatters
|
26
|
+
class Base < ::Logger::Formatter
|
27
|
+
def tid
|
28
|
+
Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
|
29
|
+
end
|
30
|
+
|
31
|
+
def ctx
|
32
|
+
Thread.current[:sidekiq_context] ||= {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def format_context
|
36
|
+
" " + ctx.compact.map { |k, v| "#{k}=#{v}" }.join(" ") if ctx.any?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Pretty < Base
|
41
|
+
def call(severity, time, program_name, message)
|
42
|
+
"#{time.utc.iso8601(3)} pid=#{::Process.pid} tid=#{tid}#{format_context} #{severity}: #{message}\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class WithoutTimestamp < Pretty
|
47
|
+
def call(severity, time, program_name, message)
|
48
|
+
"pid=#{::Process.pid} tid=#{tid}#{format_context} #{severity}: #{message}\n"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class JSON < Base
|
53
|
+
def call(severity, time, program_name, message)
|
54
|
+
hash = {
|
55
|
+
ts: time.utc.iso8601(3),
|
56
|
+
pid: ::Process.pid,
|
57
|
+
tid: tid,
|
58
|
+
lvl: severity,
|
59
|
+
msg: message,
|
60
|
+
}
|
61
|
+
c = ctx
|
62
|
+
hash["ctx"] = c unless c.empty?
|
63
|
+
|
64
|
+
Sidekiq.dump_json(hash) << "\n"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'sidekiq/util'
|
3
|
-
require 'sidekiq/processor'
|
4
|
-
require 'sidekiq/fetch'
|
5
|
-
require 'thread'
|
6
|
-
require 'set'
|
7
2
|
|
8
|
-
|
3
|
+
require "sidekiq/util"
|
4
|
+
require "sidekiq/processor"
|
5
|
+
require "sidekiq/fetch"
|
6
|
+
require "set"
|
9
7
|
|
8
|
+
module Sidekiq
|
10
9
|
##
|
11
10
|
# The Manager is the central coordination point in Sidekiq, controlling
|
12
11
|
# the lifecycle of the Processors.
|
@@ -27,7 +26,7 @@ module Sidekiq
|
|
27
26
|
attr_reader :workers
|
28
27
|
attr_reader :options
|
29
28
|
|
30
|
-
def initialize(options={})
|
29
|
+
def initialize(options = {})
|
31
30
|
logger.debug { options.inspect }
|
32
31
|
@options = options
|
33
32
|
@count = options[:concurrency] || 10
|
@@ -132,6 +131,5 @@ module Sidekiq
|
|
132
131
|
processor.kill
|
133
132
|
end
|
134
133
|
end
|
135
|
-
|
136
134
|
end
|
137
135
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Sidekiq
|
3
4
|
# Middleware is code configured to run before/after
|
4
5
|
# a message is processed. It is patterned after Rack
|
@@ -106,7 +107,7 @@ module Sidekiq
|
|
106
107
|
i = entries.index { |entry| entry.klass == newklass }
|
107
108
|
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
108
109
|
i = entries.index { |entry| entry.klass == oldklass } || entries.count - 1
|
109
|
-
entries.insert(i+1, new_entry)
|
110
|
+
entries.insert(i + 1, new_entry)
|
110
111
|
end
|
111
112
|
|
112
113
|
def exists?(klass)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
#
|
3
4
|
# Simple middleware to save the current locale and restore it when the job executes.
|
4
5
|
# Use it by requiring it in your initializer:
|
@@ -9,19 +10,16 @@ module Sidekiq::Middleware::I18n
|
|
9
10
|
# Get the current locale and store it in the message
|
10
11
|
# to be sent to Sidekiq.
|
11
12
|
class Client
|
12
|
-
def call(
|
13
|
-
msg[
|
13
|
+
def call(_worker, msg, _queue, _redis)
|
14
|
+
msg["locale"] ||= I18n.locale
|
14
15
|
yield
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
19
|
# Pull the msg locale out and set the current thread to use it.
|
19
20
|
class Server
|
20
|
-
def call(
|
21
|
-
I18n.
|
22
|
-
yield
|
23
|
-
ensure
|
24
|
-
I18n.locale = I18n.default_locale
|
21
|
+
def call(_worker, msg, _queue, &block)
|
22
|
+
I18n.with_locale(msg.fetch("locale", I18n.default_locale), &block)
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
data/lib/sidekiq/paginator.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Sidekiq
|
3
4
|
module Paginator
|
4
|
-
|
5
|
-
def page(key, pageidx=1, page_size=25, opts=nil)
|
5
|
+
def page(key, pageidx = 1, page_size = 25, opts = nil)
|
6
6
|
current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
|
7
7
|
pageidx = current_page - 1
|
8
8
|
total_size = 0
|
@@ -14,30 +14,29 @@ module Sidekiq
|
|
14
14
|
type = conn.type(key)
|
15
15
|
|
16
16
|
case type
|
17
|
-
when
|
17
|
+
when "zset"
|
18
18
|
rev = opts && opts[:reverse]
|
19
|
-
total_size, items = conn.multi
|
19
|
+
total_size, items = conn.multi {
|
20
20
|
conn.zcard(key)
|
21
21
|
if rev
|
22
|
-
conn.zrevrange(key, starting, ending, :
|
22
|
+
conn.zrevrange(key, starting, ending, with_scores: true)
|
23
23
|
else
|
24
|
-
conn.zrange(key, starting, ending, :
|
24
|
+
conn.zrange(key, starting, ending, with_scores: true)
|
25
25
|
end
|
26
|
-
|
26
|
+
}
|
27
27
|
[current_page, total_size, items]
|
28
|
-
when
|
29
|
-
total_size, items = conn.multi
|
28
|
+
when "list"
|
29
|
+
total_size, items = conn.multi {
|
30
30
|
conn.llen(key)
|
31
31
|
conn.lrange(key, starting, ending)
|
32
|
-
|
32
|
+
}
|
33
33
|
[current_page, total_size, items]
|
34
|
-
when
|
34
|
+
when "none"
|
35
35
|
[1, 0, []]
|
36
36
|
else
|
37
37
|
raise "can't page a #{type}"
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
42
41
|
end
|
43
42
|
end
|