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/processor.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'sidekiq/util'
|
3
|
-
require 'sidekiq/fetch'
|
4
|
-
require 'sidekiq/job_logger'
|
5
|
-
require 'sidekiq/job_retry'
|
6
|
-
require 'thread'
|
7
2
|
|
3
|
+
require "sidekiq/util"
|
4
|
+
require "sidekiq/fetch"
|
5
|
+
require "sidekiq/job_logger"
|
6
|
+
require "sidekiq/job_retry"
|
8
7
|
module Sidekiq
|
9
8
|
##
|
10
9
|
# The Processor is a standalone thread which:
|
@@ -23,7 +22,6 @@ module Sidekiq
|
|
23
22
|
# to replace itself and exits.
|
24
23
|
#
|
25
24
|
class Processor
|
26
|
-
|
27
25
|
include Util
|
28
26
|
|
29
27
|
attr_reader :thread
|
@@ -37,19 +35,19 @@ module Sidekiq
|
|
37
35
|
@thread = nil
|
38
36
|
@strategy = (mgr.options[:fetch] || Sidekiq::BasicFetch).new(mgr.options)
|
39
37
|
@reloader = Sidekiq.options[:reloader]
|
40
|
-
@
|
38
|
+
@job_logger = (mgr.options[:job_logger] || Sidekiq::JobLogger).new
|
41
39
|
@retrier = Sidekiq::JobRetry.new
|
42
40
|
end
|
43
41
|
|
44
|
-
def terminate(wait=false)
|
42
|
+
def terminate(wait = false)
|
45
43
|
@done = true
|
46
|
-
return
|
44
|
+
return unless @thread
|
47
45
|
@thread.value if wait
|
48
46
|
end
|
49
47
|
|
50
|
-
def kill(wait=false)
|
48
|
+
def kill(wait = false)
|
51
49
|
@done = true
|
52
|
-
return
|
50
|
+
return unless @thread
|
53
51
|
# unlike the other actors, terminate does not wait
|
54
52
|
# for the thread to finish because we don't know how
|
55
53
|
# long the job will take to finish. Instead we
|
@@ -66,16 +64,12 @@ module Sidekiq
|
|
66
64
|
private unless $TESTING
|
67
65
|
|
68
66
|
def run
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
@mgr.processor_stopped(self)
|
76
|
-
rescue Exception => ex
|
77
|
-
@mgr.processor_died(self, ex)
|
78
|
-
end
|
67
|
+
process_one until @done
|
68
|
+
@mgr.processor_stopped(self)
|
69
|
+
rescue Sidekiq::Shutdown
|
70
|
+
@mgr.processor_stopped(self)
|
71
|
+
rescue Exception => ex
|
72
|
+
@mgr.processor_died(self, ex)
|
79
73
|
end
|
80
74
|
|
81
75
|
def process_one
|
@@ -85,14 +79,15 @@ module Sidekiq
|
|
85
79
|
end
|
86
80
|
|
87
81
|
def get_one
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
rescue Sidekiq::Shutdown
|
93
|
-
rescue => ex
|
94
|
-
handle_fetch_exception(ex)
|
82
|
+
work = @strategy.retrieve_work
|
83
|
+
if @down
|
84
|
+
logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }
|
85
|
+
@down = nil
|
95
86
|
end
|
87
|
+
work
|
88
|
+
rescue Sidekiq::Shutdown
|
89
|
+
rescue => ex
|
90
|
+
handle_fetch_exception(ex)
|
96
91
|
end
|
97
92
|
|
98
93
|
def fetch
|
@@ -106,7 +101,7 @@ module Sidekiq
|
|
106
101
|
end
|
107
102
|
|
108
103
|
def handle_fetch_exception(ex)
|
109
|
-
|
104
|
+
unless @down
|
110
105
|
@down = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
111
106
|
logger.error("Error fetching job: #{ex}")
|
112
107
|
handle_exception(ex)
|
@@ -121,18 +116,18 @@ module Sidekiq
|
|
121
116
|
# job structure to the Web UI
|
122
117
|
pristine = cloned(job_hash)
|
123
118
|
|
124
|
-
|
119
|
+
@job_logger.with_job_hash_context(job_hash) do
|
125
120
|
@retrier.global(pristine, queue) do
|
126
|
-
@
|
121
|
+
@job_logger.call(job_hash, queue) do
|
127
122
|
stats(pristine, queue) do
|
128
123
|
# Rails 5 requires a Reloader to wrap code execution. In order to
|
129
124
|
# constantize the worker and instantiate an instance, we have to call
|
130
125
|
# the Reloader. It handles code loading, db connection management, etc.
|
131
126
|
# Effectively this block denotes a "unit of work" to Rails.
|
132
127
|
@reloader.call do
|
133
|
-
klass = constantize(job_hash[
|
128
|
+
klass = constantize(job_hash["class"])
|
134
129
|
worker = klass.new
|
135
|
-
worker.jid = job_hash[
|
130
|
+
worker.jid = job_hash["jid"]
|
136
131
|
@retrier.local(worker, pristine, queue) do
|
137
132
|
yield worker
|
138
133
|
end
|
@@ -152,7 +147,7 @@ module Sidekiq
|
|
152
147
|
begin
|
153
148
|
job_hash = Sidekiq.load_json(jobstr)
|
154
149
|
rescue => ex
|
155
|
-
handle_exception(ex, {
|
150
|
+
handle_exception(ex, {context: "Invalid JSON for job", jobstr: jobstr})
|
156
151
|
# we can't notify because the job isn't a valid hash payload.
|
157
152
|
DeadSet.new.kill(jobstr, notify_failure: false)
|
158
153
|
return work.acknowledge
|
@@ -162,7 +157,7 @@ module Sidekiq
|
|
162
157
|
begin
|
163
158
|
dispatch(job_hash, queue) do |worker|
|
164
159
|
Sidekiq.server_middleware.invoke(worker, job_hash, queue) do
|
165
|
-
execute_job(worker, cloned(job_hash[
|
160
|
+
execute_job(worker, cloned(job_hash["args"]))
|
166
161
|
end
|
167
162
|
end
|
168
163
|
rescue Sidekiq::Shutdown
|
@@ -173,15 +168,15 @@ module Sidekiq
|
|
173
168
|
rescue Sidekiq::JobRetry::Handled => h
|
174
169
|
# this is the common case: job raised error and Sidekiq::JobRetry::Handled
|
175
170
|
# signals that we created a retry successfully. We can acknowlege the job.
|
176
|
-
e = h.cause
|
177
|
-
handle_exception(e, {
|
171
|
+
e = h.cause || h
|
172
|
+
handle_exception(e, {context: "Job raised exception", job: job_hash, jobstr: jobstr})
|
178
173
|
raise e
|
179
174
|
rescue Exception => ex
|
180
175
|
# Unexpected error! This is very bad and indicates an exception that got past
|
181
176
|
# the retry subsystem (e.g. network partition). We won't acknowledge the job
|
182
177
|
# so it can be rescued when using Sidekiq Pro.
|
183
178
|
ack = false
|
184
|
-
handle_exception(ex, {
|
179
|
+
handle_exception(ex, {context: "Internal exception!", job: job_hash, jobstr: jobstr})
|
185
180
|
raise e
|
186
181
|
ensure
|
187
182
|
work.acknowledge if ack
|
@@ -201,12 +196,16 @@ module Sidekiq
|
|
201
196
|
@lock = Mutex.new
|
202
197
|
end
|
203
198
|
|
204
|
-
def incr(amount=1)
|
205
|
-
@lock.synchronize { @value
|
199
|
+
def incr(amount = 1)
|
200
|
+
@lock.synchronize { @value += amount }
|
206
201
|
end
|
207
202
|
|
208
203
|
def reset
|
209
|
-
@lock.synchronize {
|
204
|
+
@lock.synchronize {
|
205
|
+
val = @value
|
206
|
+
@value = 0
|
207
|
+
val
|
208
|
+
}
|
210
209
|
end
|
211
210
|
end
|
212
211
|
|
@@ -243,8 +242,7 @@ module Sidekiq
|
|
243
242
|
WORKER_STATE = SharedWorkerState.new
|
244
243
|
|
245
244
|
def stats(job_hash, queue)
|
246
|
-
tid
|
247
|
-
WORKER_STATE.set(tid, {:queue => queue, :payload => job_hash, :run_at => Time.now.to_i })
|
245
|
+
WORKER_STATE.set(tid, {queue: queue, payload: job_hash, run_at: Time.now.to_i})
|
248
246
|
|
249
247
|
begin
|
250
248
|
yield
|
@@ -265,7 +263,7 @@ module Sidekiq
|
|
265
263
|
end
|
266
264
|
|
267
265
|
def constantize(str)
|
268
|
-
names = str.split(
|
266
|
+
names = str.split("::")
|
269
267
|
names.shift if names.empty? || names.first.empty?
|
270
268
|
|
271
269
|
names.inject(Object) do |constant, name|
|
@@ -274,6 +272,5 @@ module Sidekiq
|
|
274
272
|
constant.const_defined?(name, false) ? constant.const_get(name, false) : constant.const_missing(name)
|
275
273
|
end
|
276
274
|
end
|
277
|
-
|
278
275
|
end
|
279
276
|
end
|
data/lib/sidekiq/rails.rb
CHANGED
@@ -2,22 +2,6 @@
|
|
2
2
|
|
3
3
|
module Sidekiq
|
4
4
|
class Rails < ::Rails::Engine
|
5
|
-
# We need to setup this up before any application configuration which might
|
6
|
-
# change Sidekiq middleware.
|
7
|
-
#
|
8
|
-
# This hook happens after `Rails::Application` is inherited within
|
9
|
-
# config/application.rb and before config is touched, usually within the
|
10
|
-
# class block. Definitely before config/environments/*.rb and
|
11
|
-
# config/initializers/*.rb.
|
12
|
-
config.before_configuration do
|
13
|
-
if ::Rails::VERSION::MAJOR < 5 && defined?(::ActiveRecord)
|
14
|
-
Sidekiq.server_middleware do |chain|
|
15
|
-
require 'sidekiq/middleware/server/active_record'
|
16
|
-
chain.add Sidekiq::Middleware::Server::ActiveRecord
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
5
|
config.after_initialize do
|
22
6
|
# This hook happens after all initializers are run, just before returning
|
23
7
|
# from config/environment.rb back to sidekiq/cli.rb.
|
@@ -27,9 +11,7 @@ module Sidekiq
|
|
27
11
|
# None of this matters on the client-side, only within the Sidekiq process itself.
|
28
12
|
#
|
29
13
|
Sidekiq.configure_server do |_|
|
30
|
-
|
31
|
-
Sidekiq.options[:reloader] = Sidekiq::Rails::Reloader.new
|
32
|
-
end
|
14
|
+
Sidekiq.options[:reloader] = Sidekiq::Rails::Reloader.new
|
33
15
|
end
|
34
16
|
end
|
35
17
|
|
@@ -48,11 +30,5 @@ module Sidekiq
|
|
48
30
|
"#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
|
49
31
|
end
|
50
32
|
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
if defined?(::Rails) && ::Rails::VERSION::MAJOR < 4
|
55
|
-
$stderr.puts("**************************************************")
|
56
|
-
$stderr.puts("⛔️ WARNING: Sidekiq server is no longer supported by Rails 3.2 - please ensure your server/workers are updated")
|
57
|
-
$stderr.puts("**************************************************")
|
33
|
+
end
|
58
34
|
end
|
@@ -1,36 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
2
|
+
|
3
|
+
require "connection_pool"
|
4
|
+
require "redis"
|
5
|
+
require "uri"
|
5
6
|
|
6
7
|
module Sidekiq
|
7
8
|
class RedisConnection
|
8
9
|
class << self
|
9
|
-
|
10
|
-
def create(options={})
|
10
|
+
def create(options = {})
|
11
11
|
options.keys.each do |key|
|
12
12
|
options[key.to_sym] = options.delete(key)
|
13
13
|
end
|
14
14
|
|
15
|
-
options[:id] = "Sidekiq-#{Sidekiq.server? ? "server" : "client"}-PID-#{
|
15
|
+
options[:id] = "Sidekiq-#{Sidekiq.server? ? "server" : "client"}-PID-#{$PID}" unless options.key?(:id)
|
16
16
|
options[:url] ||= determine_redis_provider
|
17
17
|
|
18
18
|
size = if options[:size]
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
options[:size]
|
20
|
+
elsif Sidekiq.server?
|
21
|
+
# Give ourselves plenty of connections. pool is lazy
|
22
|
+
# so we won't create them until we need them.
|
23
|
+
Sidekiq.options[:concurrency] + 5
|
24
|
+
elsif ENV["RAILS_MAX_THREADS"]
|
25
|
+
Integer(ENV["RAILS_MAX_THREADS"])
|
26
|
+
else
|
27
|
+
5
|
28
|
+
end
|
27
29
|
|
28
30
|
verify_sizing(size, Sidekiq.options[:concurrency]) if Sidekiq.server?
|
29
31
|
|
30
32
|
pool_timeout = options[:pool_timeout] || 1
|
31
33
|
log_info(options)
|
32
34
|
|
33
|
-
ConnectionPool.new(:
|
35
|
+
ConnectionPool.new(timeout: pool_timeout, size: size) do
|
34
36
|
build_client(options)
|
35
37
|
end
|
36
38
|
end
|
@@ -46,7 +48,7 @@ module Sidekiq
|
|
46
48
|
# - enterprise's leader election
|
47
49
|
# - enterprise's cron support
|
48
50
|
def verify_sizing(size, concurrency)
|
49
|
-
raise ArgumentError, "Your Redis connection pool is too small for Sidekiq to work. Your pool has #{size} connections but must have at least #{concurrency + 2}" if size
|
51
|
+
raise ArgumentError, "Your Redis connection pool is too small for Sidekiq to work. Your pool has #{size} connections but must have at least #{concurrency + 2}" if size < (concurrency + 2)
|
50
52
|
end
|
51
53
|
|
52
54
|
def build_client(options)
|
@@ -55,8 +57,8 @@ module Sidekiq
|
|
55
57
|
client = Redis.new client_opts(options)
|
56
58
|
if namespace
|
57
59
|
begin
|
58
|
-
require
|
59
|
-
Redis::Namespace.new(namespace, :
|
60
|
+
require "redis/namespace"
|
61
|
+
Redis::Namespace.new(namespace, redis: client)
|
60
62
|
rescue LoadError
|
61
63
|
Sidekiq.logger.error("Your Redis configuration uses the namespace '#{namespace}' but the redis-namespace gem is not included in the Gemfile." \
|
62
64
|
"Add the gem to your Gemfile to continue using a namespace. Otherwise, remove the namespace parameter.")
|
@@ -78,7 +80,7 @@ module Sidekiq
|
|
78
80
|
opts.delete(:network_timeout)
|
79
81
|
end
|
80
82
|
|
81
|
-
opts[:driver] ||= Redis::Connection.drivers.last ||
|
83
|
+
opts[:driver] ||= Redis::Connection.drivers.last || "ruby"
|
82
84
|
|
83
85
|
# Issue #3303, redis-rb will silently retry an operation.
|
84
86
|
# This can lead to duplicate jobs if Sidekiq::Client's LPUSH
|
@@ -115,30 +117,22 @@ module Sidekiq
|
|
115
117
|
# REDIS_PROVIDER=MY_REDIS_URL
|
116
118
|
# and Sidekiq will find your custom URL variable with no custom
|
117
119
|
# initialization code at all.
|
118
|
-
|
120
|
+
#
|
121
|
+
p = ENV["REDIS_PROVIDER"]
|
119
122
|
if p && p =~ /\:/
|
120
|
-
|
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.:
|
123
|
+
raise <<~EOM
|
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 will sell addons that publish a *_URL variable. You need to tell Sidekiq with REDIS_PROVIDER, e.g.:
|
126
126
|
|
127
|
-
|
128
|
-
|
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
|
127
|
+
REDIS_PROVIDER=REDISTOGO_URL
|
128
|
+
REDISTOGO_URL=redis://somehost.example.com:6379/4
|
129
|
+
EOM
|
136
130
|
end
|
131
|
+
|
137
132
|
ENV[
|
138
|
-
|
133
|
+
p || "REDIS_URL"
|
139
134
|
]
|
140
135
|
end
|
141
|
-
|
142
136
|
end
|
143
137
|
end
|
144
138
|
end
|
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
2
|
+
|
3
|
+
require "sidekiq"
|
4
|
+
require "sidekiq/util"
|
5
|
+
require "sidekiq/api"
|
5
6
|
|
6
7
|
module Sidekiq
|
7
8
|
module Scheduled
|
8
|
-
SETS = %w
|
9
|
+
SETS = %w[retry schedule]
|
9
10
|
|
10
11
|
class Enq
|
11
|
-
def enqueue_jobs(now=Time.now.to_f.to_s, sorted_sets=SETS)
|
12
|
+
def enqueue_jobs(now = Time.now.to_f.to_s, sorted_sets = SETS)
|
12
13
|
# A job's "score" in Redis is the time at which it should be processed.
|
13
14
|
# Just check Redis for the set of jobs with a timestamp before now.
|
14
15
|
Sidekiq.redis do |conn|
|
@@ -17,14 +18,14 @@ module Sidekiq
|
|
17
18
|
# We need to go through the list one at a time to reduce the risk of something
|
18
19
|
# going wrong between the time jobs are popped from the scheduled queue and when
|
19
20
|
# they are pushed onto a work queue and losing the jobs.
|
20
|
-
while job = conn.zrangebyscore(sorted_set,
|
21
|
+
while (job = conn.zrangebyscore(sorted_set, "-inf", now, limit: [0, 1]).first)
|
21
22
|
|
22
23
|
# Pop item off the queue and add it to the work queue. If the job can't be popped from
|
23
24
|
# the queue, it's because another process already popped it so we can move on to the
|
24
25
|
# next one.
|
25
26
|
if conn.zrem(sorted_set, job)
|
26
27
|
Sidekiq::Client.push(Sidekiq.load_json(job))
|
27
|
-
Sidekiq
|
28
|
+
Sidekiq.logger.debug { "enqueued #{sorted_set}: #{job}" }
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -61,26 +62,24 @@ module Sidekiq
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def start
|
64
|
-
@thread ||= safe_thread("scheduler")
|
65
|
+
@thread ||= safe_thread("scheduler") {
|
65
66
|
initial_wait
|
66
67
|
|
67
|
-
|
68
|
+
until @done
|
68
69
|
enqueue
|
69
70
|
wait
|
70
71
|
end
|
71
72
|
Sidekiq.logger.info("Scheduler exiting...")
|
72
|
-
|
73
|
+
}
|
73
74
|
end
|
74
75
|
|
75
76
|
def enqueue
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
handle_exception(ex)
|
83
|
-
end
|
77
|
+
@enq.enqueue_jobs
|
78
|
+
rescue => ex
|
79
|
+
# Most likely a problem with redis networking.
|
80
|
+
# Punt and try again at the next interval
|
81
|
+
logger.error ex.message
|
82
|
+
handle_exception(ex)
|
84
83
|
end
|
85
84
|
|
86
85
|
private
|
@@ -168,7 +167,6 @@ module Sidekiq
|
|
168
167
|
@sleeper.pop(total)
|
169
168
|
rescue Timeout::Error
|
170
169
|
end
|
171
|
-
|
172
170
|
end
|
173
171
|
end
|
174
172
|
end
|
data/lib/sidekiq/testing.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'securerandom'
|
3
|
-
require 'sidekiq'
|
4
2
|
|
5
|
-
|
3
|
+
require "securerandom"
|
4
|
+
require "sidekiq"
|
6
5
|
|
6
|
+
module Sidekiq
|
7
7
|
class Testing
|
8
8
|
class << self
|
9
9
|
attr_accessor :__test_mode
|
10
10
|
|
11
11
|
def __set_test_mode(mode)
|
12
12
|
if block_given?
|
13
|
-
current_mode =
|
13
|
+
current_mode = __test_mode
|
14
14
|
begin
|
15
15
|
self.__test_mode = mode
|
16
16
|
yield
|
@@ -35,19 +35,19 @@ module Sidekiq
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def enabled?
|
38
|
-
|
38
|
+
__test_mode != :disable
|
39
39
|
end
|
40
40
|
|
41
41
|
def disabled?
|
42
|
-
|
42
|
+
__test_mode == :disable
|
43
43
|
end
|
44
44
|
|
45
45
|
def fake?
|
46
|
-
|
46
|
+
__test_mode == :fake
|
47
47
|
end
|
48
48
|
|
49
49
|
def inline?
|
50
|
-
|
50
|
+
__test_mode == :inline
|
51
51
|
end
|
52
52
|
|
53
53
|
def server_middleware
|
@@ -57,7 +57,7 @@ module Sidekiq
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def constantize(str)
|
60
|
-
names = str.split(
|
60
|
+
names = str.split("::")
|
61
61
|
names.shift if names.empty? || names.first.empty?
|
62
62
|
|
63
63
|
names.inject(Object) do |constant, name|
|
@@ -77,14 +77,14 @@ module Sidekiq
|
|
77
77
|
if Sidekiq::Testing.fake?
|
78
78
|
payloads.each do |job|
|
79
79
|
job = Sidekiq.load_json(Sidekiq.dump_json(job))
|
80
|
-
job
|
81
|
-
Queues.push(job[
|
80
|
+
job["enqueued_at"] = Time.now.to_f unless job["at"]
|
81
|
+
Queues.push(job["queue"], job["class"], job)
|
82
82
|
end
|
83
83
|
true
|
84
84
|
elsif Sidekiq::Testing.inline?
|
85
85
|
payloads.each do |job|
|
86
|
-
klass = Sidekiq::Testing.constantize(job[
|
87
|
-
job[
|
86
|
+
klass = Sidekiq::Testing.constantize(job["class"])
|
87
|
+
job["id"] ||= SecureRandom.hex(12)
|
88
88
|
job_hash = Sidekiq.load_json(Sidekiq.dump_json(job))
|
89
89
|
klass.process_job(job_hash)
|
90
90
|
end
|
@@ -255,27 +255,26 @@ module Sidekiq
|
|
255
255
|
# Then I should receive a welcome email to "foo@example.com"
|
256
256
|
#
|
257
257
|
module ClassMethods
|
258
|
-
|
259
258
|
# Queue for this worker
|
260
259
|
def queue
|
261
|
-
|
260
|
+
sidekiq_options["queue"]
|
262
261
|
end
|
263
262
|
|
264
263
|
# Jobs queued for this worker
|
265
264
|
def jobs
|
266
|
-
Queues.jobs_by_worker[
|
265
|
+
Queues.jobs_by_worker[to_s]
|
267
266
|
end
|
268
267
|
|
269
268
|
# Clear all jobs for this worker
|
270
269
|
def clear
|
271
|
-
Queues.clear_for(queue,
|
270
|
+
Queues.clear_for(queue, to_s)
|
272
271
|
end
|
273
272
|
|
274
273
|
# Drain and run all jobs for this worker
|
275
274
|
def drain
|
276
275
|
while jobs.any?
|
277
276
|
next_job = jobs.first
|
278
|
-
Queues.delete_for(next_job["jid"], next_job["queue"],
|
277
|
+
Queues.delete_for(next_job["jid"], next_job["queue"], to_s)
|
279
278
|
process_job(next_job)
|
280
279
|
end
|
281
280
|
end
|
@@ -284,16 +283,16 @@ module Sidekiq
|
|
284
283
|
def perform_one
|
285
284
|
raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
|
286
285
|
next_job = jobs.first
|
287
|
-
Queues.delete_for(next_job["jid"], queue,
|
286
|
+
Queues.delete_for(next_job["jid"], queue, to_s)
|
288
287
|
process_job(next_job)
|
289
288
|
end
|
290
289
|
|
291
290
|
def process_job(job)
|
292
291
|
worker = new
|
293
|
-
worker.jid = job[
|
294
|
-
worker.bid = job[
|
295
|
-
Sidekiq::Testing.server_middleware.invoke(worker, job, job[
|
296
|
-
execute_job(worker, job[
|
292
|
+
worker.jid = job["jid"]
|
293
|
+
worker.bid = job["bid"] if worker.respond_to?(:bid=)
|
294
|
+
Sidekiq::Testing.server_middleware.invoke(worker, job, job["queue"]) do
|
295
|
+
execute_job(worker, job["args"])
|
297
296
|
end
|
298
297
|
end
|
299
298
|
|
data/lib/sidekiq/util.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
require "securerandom"
|
5
|
+
require "sidekiq/exception_handler"
|
5
6
|
|
6
7
|
module Sidekiq
|
7
8
|
##
|
@@ -15,13 +16,13 @@ module Sidekiq
|
|
15
16
|
def watchdog(last_words)
|
16
17
|
yield
|
17
18
|
rescue Exception => ex
|
18
|
-
handle_exception(ex, {
|
19
|
+
handle_exception(ex, {context: last_words})
|
19
20
|
raise ex
|
20
21
|
end
|
21
22
|
|
22
23
|
def safe_thread(name, &block)
|
23
24
|
Thread.new do
|
24
|
-
Thread.current[
|
25
|
+
Thread.current["sidekiq_label"] = name
|
25
26
|
watchdog(name, &block)
|
26
27
|
end
|
27
28
|
end
|
@@ -34,31 +35,33 @@ module Sidekiq
|
|
34
35
|
Sidekiq.redis(&block)
|
35
36
|
end
|
36
37
|
|
38
|
+
def tid
|
39
|
+
Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
|
40
|
+
end
|
41
|
+
|
37
42
|
def hostname
|
38
|
-
ENV[
|
43
|
+
ENV["DYNO"] || Socket.gethostname
|
39
44
|
end
|
40
45
|
|
41
46
|
def process_nonce
|
42
|
-
|
47
|
+
@process_nonce ||= SecureRandom.hex(6)
|
43
48
|
end
|
44
49
|
|
45
50
|
def identity
|
46
|
-
|
51
|
+
@identity ||= "#{hostname}:#{$PID}:#{process_nonce}"
|
47
52
|
end
|
48
53
|
|
49
|
-
def fire_event(event, options={})
|
54
|
+
def fire_event(event, options = {})
|
50
55
|
reverse = options[:reverse]
|
51
56
|
reraise = options[:reraise]
|
52
57
|
|
53
58
|
arr = Sidekiq.options[:lifecycle_events][event]
|
54
59
|
arr.reverse! if reverse
|
55
60
|
arr.each do |block|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
raise ex if reraise
|
61
|
-
end
|
61
|
+
block.call
|
62
|
+
rescue => ex
|
63
|
+
handle_exception(ex, {context: "Exception during Sidekiq lifecycle event.", event: event})
|
64
|
+
raise ex if reraise
|
62
65
|
end
|
63
66
|
arr.clear
|
64
67
|
end
|
data/lib/sidekiq/version.rb
CHANGED